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