2 PrtView plugin for GtkRadiant
\r
3 Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
\r
5 This library is free software; you can redistribute it and/or
\r
6 modify it under the terms of the GNU Lesser General Public
\r
7 License as published by the Free Software Foundation; either
\r
8 version 2.1 of the License, or (at your option) any later version.
\r
10 This library is distributed in the hope that it will be useful,
\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
13 Lesser General Public License for more details.
\r
15 You should have received a copy of the GNU Lesser General Public
\r
16 License along with this library; if not, write to the Free Software
\r
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 // PrtView.cpp : Defines the initialization routines for the DLL.
\r
27 #define Q3R_CMD_SPLITTER "-"
\r
28 #define Q3R_CMD_ABOUT "About Portal Viewer"
\r
29 #define Q3R_CMD_LOAD "Load .prt file"
\r
30 #define Q3R_CMD_RELEASE "Unload .prt file"
\r
31 #define Q3R_CMD_SHOW_3D "Toggle portals (3D)"
\r
32 #define Q3R_CMD_SHOW_2D "Toggle portals (2D)"
\r
33 #define Q3R_CMD_OPTIONS "Configure Portal Viewer"
\r
35 static char INIfn[NAME_MAX];
\r
37 /////////////////////////////////////////////////////////////////////////////
\r
38 // CPrtViewApp construction
\r
40 #define RENDER_2D "Render2D"
\r
41 #define WIDTH_2D "Width2D"
\r
42 #define AA_2D "AntiAlias2D"
\r
43 #define COLOR_2D "Color2D"
\r
45 #define RENDER_3D "Render3D"
\r
46 #define WIDTH_3D "Width3D"
\r
47 #define AA_3D "AntiAlias3D"
\r
48 #define COLOR_3D "Color3D"
\r
49 #define COLOR_FOG "ColorFog"
\r
51 #define ZBUFFER "ZBuffer"
\r
52 #define POLYGON "Polygons"
\r
53 #define LINE "Lines"
\r
54 #define TRANS_3D "Transparency"
\r
55 #define CLIP_RANGE "ClipRange"
\r
58 void InitInstance ()
\r
62 char fn_drive[_MAX_DRIVE];
\r
63 char fn_dir[_MAX_DIR];
\r
64 char fn_name[_MAX_FNAME];
\r
65 char fn_ext[_MAX_EXT];
\r
67 GetModuleFileName(GetModuleHandle("PrtView.dll"), fn, _MAX_PATH);
\r
69 _splitpath(fn, fn_drive, fn_dir, fn_name, fn_ext);
\r
71 strcpy(INIfn, fn_drive);
\r
72 strcat(INIfn, fn_dir);
\r
73 strcat(INIfn, fn_name);
\r
74 strcat(INIfn, ".ini");
\r
75 #else // if def __linux__
\r
76 strcpy (INIfn, g_get_home_dir ());
\r
77 strcat (INIfn, "/.radiant/");
\r
78 strcat (INIfn, RADIANT_VERSION);
\r
79 strcat (INIfn, "/prtview.ini");
\r
82 portals.show_2d = INIGetInt(RENDER_2D, FALSE) ? true : false;
\r
83 portals.aa_2d = INIGetInt(AA_2D, FALSE) ? true : false;
\r
84 portals.width_2d = (float)INIGetInt(WIDTH_2D, 10);
\r
85 portals.color_2d = (COLORREF)INIGetInt(COLOR_2D, RGB(0, 0, 255)) & 0xFFFFFF;
\r
87 if (portals.width_2d > 40.0f)
\r
88 portals.width_2d = 40.0f;
\r
89 else if (portals.width_2d < 2.0f)
\r
90 portals.width_2d = 2.0f;
\r
92 portals.show_3d = INIGetInt(RENDER_3D, TRUE) ? true : false;
\r
94 portals.zbuffer = INIGetInt(ZBUFFER, 1);
\r
95 portals.fog = INIGetInt(FOG, FALSE) ? true : false;
\r
96 portals.polygons = INIGetInt(POLYGON, TRUE);
\r
97 portals.lines = INIGetInt(LINE, TRUE);
\r
98 portals.aa_3d = INIGetInt(AA_3D, FALSE) ? true : false;
\r
99 portals.width_3d = (float)INIGetInt(WIDTH_3D, 4);
\r
100 portals.color_3d = (COLORREF)INIGetInt(COLOR_3D, RGB(255, 255, 0)) & 0xFFFFFF;
\r
101 portals.color_fog = (COLORREF)INIGetInt(COLOR_FOG, RGB(127, 127, 127)) & 0xFFFFFF;
\r
102 portals.trans_3d = (float)INIGetInt(TRANS_3D, 50);
\r
103 portals.clip = INIGetInt(CLIP, FALSE) ? true : false;
\r
104 portals.clip_range = (float)INIGetInt(CLIP_RANGE, 16);
\r
106 if (portals.clip_range < 1)
\r
107 portals.clip_range = 1;
\r
108 else if (portals.clip_range > 128)
\r
109 portals.clip_range = 128;
\r
111 if (portals.zbuffer < 0)
\r
112 portals.zbuffer = 0;
\r
113 else if (portals.zbuffer > 2)
\r
114 portals.zbuffer = 0;
\r
116 if (portals.width_3d > 40.0f)
\r
117 portals.width_3d = 40.0f;
\r
118 else if (portals.width_3d < 2.0f)
\r
119 portals.width_3d = 2.0f;
\r
121 if (portals.trans_3d > 100.0f)
\r
122 portals.trans_3d = 100.0f;
\r
123 else if (portals.trans_3d < 0.0f)
\r
124 portals.trans_3d = 0.0f;
\r
128 portals.FixColors();
\r
131 void SaveConfig ()
\r
133 INISetInt(RENDER_2D, portals.show_2d, "Draw in 2D windows");
\r
134 INISetInt(WIDTH_2D, (int)portals.width_2d, "Width of lines in 2D windows (in units of 1/2)");
\r
135 INISetInt(COLOR_2D, (int)portals.color_2d, "Color of lines in 2D windows");
\r
136 INISetInt(AA_2D, portals.aa_2d, "Draw lines in 2D window anti-aliased");
\r
138 INISetInt(ZBUFFER, portals.zbuffer, "ZBuffer level in 3D window");
\r
139 INISetInt(FOG, portals.fog, "Use depth cueing in 3D window");
\r
140 INISetInt(POLYGON, portals.polygons, "Render using polygons polygons in 3D window");
\r
141 INISetInt(LINE, portals.polygons, "Render using lines in 3D window");
\r
142 INISetInt(RENDER_3D, portals.show_3d, "Draw in 3D windows");
\r
143 INISetInt(WIDTH_3D, (int)portals.width_3d, "Width of lines in 3D window (in units of 1/2)");
\r
144 INISetInt(COLOR_3D, (int)portals.color_3d, "Color of lines/polygons in 3D window");
\r
145 INISetInt(COLOR_FOG, (int)portals.color_fog, "Color of distant lines/polygons in 3D window");
\r
146 INISetInt(AA_3D, portals.aa_3d, "Draw lines in 3D window anti-aliased");
\r
147 INISetInt(TRANS_3D, (int)portals.trans_3d, "Transparency in 3d view (0 = solid, 100 = invisible)");
\r
148 INISetInt(CLIP, portals.clip, "Cubic clipper active for portal viewer");
\r
149 INISetInt(CLIP_RANGE, (int)portals.clip_range, "Portal viewer cubic clip distance (in units of 64)");
\r
152 // Radiant function table
\r
153 // use to access what Radiant provides
\r
154 _QERFuncTable_1 g_FuncTable;
\r
155 _QERQglTable g_QglTable;
\r
157 #define CONFIG_SECTION "Configuration"
\r
159 #if defined(__linux__) || defined(__APPLE__)
\r
161 static bool read_var (const char *filename, const char *section, const char *key, char *value)
\r
163 char line[1024], *ptr;
\r
166 rc = fopen (filename, "rt");
\r
171 while (fgets (line, 1024, rc) != 0)
\r
173 // First we find the section
\r
174 if (line[0] != '[')
\r
177 ptr = strchr (line, ']');
\r
180 if (strcmp (&line[1], section) == 0)
\r
182 while (fgets (line, 1024, rc) != 0)
\r
184 ptr = strchr (line, '=');
\r
188 // reached the end of the section
\r
194 if (strcmp (line, key) == 0)
\r
196 strcpy (value, ptr+1);
\r
199 while (value[strlen (value)-1] == 10 ||
\r
200 value[strlen (value)-1] == 13 ||
\r
201 value[strlen (value)-1] == 32)
\r
202 value[strlen (value)-1] = 0;
\r
213 static bool save_var (const char *filename, const char *section, const char *key, const char *value)
\r
215 char line[1024], *ptr;
\r
216 FILE *old_rc = NULL, *rc;
\r
219 rc = fopen (filename, "rb");
\r
226 char *tmpname = g_strdup_printf ("%s.tmp", filename);
\r
227 old_rc = fopen (tmpname, "w+b");
\r
230 fseek (rc, 0, SEEK_END);
\r
233 buf = g_malloc (len);
\r
234 fread (buf, len, 1, rc);
\r
235 fwrite (buf, len, 1, old_rc);
\r
241 rc = fopen (filename, "wb");
\r
246 // First we need to find the section
\r
248 if (old_rc != NULL)
\r
249 while (fgets (line, 1024, old_rc) != NULL)
\r
253 if (line[0] == '[')
\r
255 ptr = strchr (line, ']');
\r
258 if (strcmp (&line[1], section) == 0)
\r
269 fprintf (rc, "[%s]\n", section);
\r
272 fprintf (rc, "%s=%s\n", key, value);
\r
274 if (old_rc != NULL)
\r
276 while (fgets (line, 1024, old_rc) != NULL)
\r
278 ptr = strchr (line, '=');
\r
284 if (strcmp (line, key) == 0)
\r
297 while (fgets (line, 1024, old_rc) != NULL)
\r
302 char *tmpname = g_strdup_printf ("%s.tmp", filename);
\r
314 int INIGetInt(char *key, int def)
\r
316 #if defined(__linux__) || defined(__APPLE__)
\r
319 if (read_var (INIfn, CONFIG_SECTION, key, value))
\r
320 return atoi (value);
\r
324 return GetPrivateProfileInt(CONFIG_SECTION, key, def, INIfn);
\r
328 void INISetInt(char *key, int val, char *comment /* = NULL */)
\r
333 sprintf(s, "%d ; %s", val, comment);
\r
335 sprintf(s, "%d", val);
\r
336 #if defined(__linux__) || defined(__APPLE__)
\r
337 save_var (INIfn, CONFIG_SECTION, key, s);
\r
339 WritePrivateProfileString(CONFIG_SECTION, key, s, INIfn);
\r
345 static const char *PLUGIN_NAME = "Portal Viewer";
\r
346 // commands in the menu
\r
347 static const char *PLUGIN_COMMANDS =
\r
349 Q3R_CMD_SPLITTER ";"
\r
350 Q3R_CMD_OPTIONS ";"
\r
351 Q3R_CMD_SPLITTER ";"
\r
352 Q3R_CMD_SHOW_2D ";"
\r
353 Q3R_CMD_SHOW_3D ";"
\r
354 Q3R_CMD_SPLITTER ";"
\r
355 Q3R_CMD_RELEASE ";"
\r
358 extern "C" LPVOID WINAPI QERPlug_GetFuncTable()
\r
360 return &g_FuncTable;
\r
364 //extern "C" LPCSTR WINAPI QERPlug_Init (HMODULE hApp, GtkWidget* hwndMain)
\r
365 extern "C" const char* QERPlug_Init (void *hApp, void* pMainWidget)
\r
367 // Setup defaults & load config
\r
370 return "Portal Viewer for Q3Radiant";
\r
373 extern "C" const char* QERPlug_GetName()
\r
375 return (char*)PLUGIN_NAME;
\r
378 extern "C" const char* QERPlug_GetCommandList()
\r
380 return (char*)PLUGIN_COMMANDS;
\r
384 void Sys_Printf (char *text, ...)
\r
389 va_start (argptr,text);
\r
390 vsprintf (buf, text, argptr);
\r
393 g_FuncTable.m_pfnSysMsg (buf);
\r
397 bool interfaces_started = false;
\r
399 static void CheckInterfaces()
\r
401 if (interfaces_started)
\r
406 interfaces_started = true;
\r
409 extern "C" void QERPlug_Dispatch(const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
\r
411 Sys_Printf (MSG_PREFIX "Command \"%s\"\n",p);
\r
413 if (!strcmp(p,Q3R_CMD_ABOUT))
\r
417 else if (!strcmp(p,Q3R_CMD_LOAD))
\r
421 if (interfaces_started)
\r
423 if (DoLoadPortalFileDialog () == IDOK)
\r
426 g_FuncTable.m_pfnSysUpdateWindows(UPDATE_ALL);
\r
430 Sys_Printf(MSG_PREFIX "Portal file load aborted.\n", portals.fn);
\r
434 else if (!strcmp(p,Q3R_CMD_RELEASE))
\r
438 if (interfaces_started)
\r
439 g_FuncTable.m_pfnSysUpdateWindows(UPDATE_ALL);
\r
441 Sys_Printf(MSG_PREFIX "Portals unloaded.\n");
\r
443 else if (!strcmp(p,Q3R_CMD_SHOW_2D))
\r
445 portals.show_2d = !portals.show_2d;
\r
447 if(interfaces_started)
\r
448 g_FuncTable.m_pfnSysUpdateWindows(UPDATE_ALL);
\r
451 if(portals.show_2d)
\r
452 Sys_Printf(MSG_PREFIX "Portals will be rendered in 2D view.\n");
\r
454 Sys_Printf(MSG_PREFIX "Portals will NOT be rendered in 2D view.\n");
\r
456 else if (!strcmp(p,Q3R_CMD_SHOW_3D))
\r
458 portals.show_3d = !portals.show_3d;
\r
461 if (interfaces_started)
\r
462 g_FuncTable.m_pfnSysUpdateWindows(UPDATE_ALL);
\r
464 if (portals.show_3d)
\r
465 Sys_Printf(MSG_PREFIX "Portals will be rendered in 3D view.\n");
\r
467 Sys_Printf(MSG_PREFIX "Portals will NOT be rendered in 3D view.\n");
\r
469 else if (!strcmp(p,Q3R_CMD_OPTIONS))
\r
474 if (interfaces_started)
\r
475 g_FuncTable.m_pfnSysUpdateWindows(UPDATE_ALL);
\r
481 // =============================================================================
\r
484 class CSynapseClientPrtView : public CSynapseClient
\r
487 // CSynapseClient API
\r
488 bool RequestAPI(APIDescriptor_t *pAPI);
\r
489 const char* GetInfo();
\r
491 CSynapseClientPrtView() { }
\r
492 virtual ~CSynapseClientPrtView() { }
\r
496 CSynapseServer* g_pSynapseServer = NULL;
\r
497 CSynapseClientPrtView g_SynapseClient;
\r
500 #pragma GCC visibility push(default)
\r
502 extern "C" CSynapseClient* SYNAPSE_DLL_EXPORT Synapse_EnumerateInterfaces( const char *version, CSynapseServer *pServer ) {
\r
504 #pragma GCC visibility pop
\r
506 if (strcmp(version, SYNAPSE_VERSION))
\r
508 Syn_Printf("ERROR: synapse API version mismatch: should be '" SYNAPSE_VERSION "', got '%s'\n", version);
\r
511 g_pSynapseServer = pServer;
\r
512 g_pSynapseServer->IncRef();
\r
513 Set_Syn_Printf(g_pSynapseServer->Get_Syn_Printf());
\r
515 g_SynapseClient.AddAPI(PLUGIN_MAJOR, PRTVIEW_MINOR, sizeof(_QERPluginTable));
\r
517 g_SynapseClient.AddAPI(RADIANT_MAJOR, NULL, sizeof(g_FuncTable), SYN_REQUIRE, &g_FuncTable);
\r
518 g_SynapseClient.AddAPI(QGL_MAJOR, NULL, sizeof(g_QglTable), SYN_REQUIRE, &g_QglTable);
\r
520 return &g_SynapseClient;
\r
523 bool CSynapseClientPrtView::RequestAPI(APIDescriptor_t *pAPI)
\r
525 if( !strcmp(pAPI->major_name, PLUGIN_MAJOR) )
\r
527 if( !strcmp(pAPI->minor_name, PRTVIEW_MINOR) )
\r
529 _QERPluginTable* pTable= static_cast<_QERPluginTable*>(pAPI->mpTable);
\r
531 pTable->m_pfnQERPlug_Init = QERPlug_Init;
\r
532 pTable->m_pfnQERPlug_GetName = QERPlug_GetName;
\r
533 pTable->m_pfnQERPlug_GetCommandList = QERPlug_GetCommandList;
\r
534 pTable->m_pfnQERPlug_Dispatch = QERPlug_Dispatch;
\r
539 Syn_Printf("ERROR: RequestAPI( '%s' ) not found in '%s'\n", pAPI->major_name, GetInfo());
\r
543 #include "version.h"
\r
545 const char* CSynapseClientPrtView::GetInfo()
\r
547 return "PrtView module built " __DATE__ " " RADIANT_VERSION;
\r