transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / contrib / bobtoolz / cportals.cpp
1 /*\r
2 BobToolz plugin for GtkRadiant\r
3 Copyright (C) 2001 Gordon Biggans\r
4 \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
9 \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
14 \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
18 */\r
19 \r
20 #include "StdAfx.h"\r
21 #include "CPortals.h"\r
22 #include "misc.h"\r
23 \r
24 #define LINE_BUF 1000\r
25 #define MSG_PREFIX "bobToolz plugin: "\r
26 \r
27 // these classes are far less of a mess than my code was, \r
28 // thanq to G.DeWan 4 the prtview source on which it was based\r
29 \r
30 CBspPortal::CBspPortal()\r
31 {\r
32         memset(this, 0, sizeof(CBspPortal));\r
33 }\r
34 \r
35 CBspPortal::~CBspPortal()\r
36 {\r
37         delete[] point;\r
38 }\r
39 \r
40 void ClampFloat(float* p)\r
41 {\r
42         double i;\r
43         double frac = modf(*p, &i);\r
44 \r
45         if(!frac)\r
46                 return;\r
47 \r
48         if(fabs(*p - ceil(*p)) < MAX_ROUND_ERROR)\r
49                 *p = ceilf(*p);\r
50 \r
51         if(fabs(*p - floor(*p)) < MAX_ROUND_ERROR)\r
52                 *p = floorf(*p);\r
53 }\r
54 \r
55 bool CBspPortal::Build(char *def, unsigned int pointCnt, bool bInverse)\r
56 {\r
57         char *c = def;\r
58         unsigned int n;\r
59 \r
60         point_count = pointCnt;\r
61 \r
62         if(point_count < 3)\r
63                 return FALSE;\r
64 \r
65         point = new CBspPoint[point_count];\r
66 \r
67         for(n = 0; n < point_count; n++)\r
68         {\r
69                 for(; *c != 0 && *c != '('; c++);\r
70 \r
71                 if(*c == 0)\r
72                         return FALSE;\r
73 \r
74                 c++;\r
75 \r
76                 int x;\r
77                 if(bInverse)\r
78                         x = point_count - n - 1;\r
79                 else\r
80                         x = n;\r
81 \r
82                 sscanf(c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2]);\r
83 \r
84                 ClampFloat(&point[x].p[0]);\r
85                 ClampFloat(&point[x].p[1]);\r
86                 ClampFloat(&point[x].p[2]);\r
87         }\r
88 \r
89         return TRUE;\r
90 }\r
91 \r
92 CPortals::CPortals()\r
93 {\r
94         memset(this, 0, sizeof(CPortals));\r
95 }\r
96 \r
97 CPortals::~CPortals()\r
98 {\r
99         Purge();\r
100 }\r
101 \r
102 void CPortals::Purge()\r
103 {\r
104         if(node)\r
105                 delete[] node;\r
106         node = NULL;\r
107         node_count = 0;\r
108 }\r
109 \r
110 void CPortals::Load()\r
111 {\r
112         char buf[LINE_BUF+1];\r
113 \r
114         memset(buf, 0, LINE_BUF + 1);\r
115         \r
116         Purge();\r
117 \r
118         Sys_Printf(MSG_PREFIX "Loading portal file %s.\n", fn);\r
119 \r
120         FILE *in;\r
121 \r
122         in = fopen(fn, "rt");\r
123 \r
124         if(in == NULL)\r
125         {\r
126                 Sys_Printf("  ERROR - could not open file.\n");\r
127 \r
128                 return;\r
129         }\r
130 \r
131         if(!fgets(buf, LINE_BUF, in))\r
132         {\r
133                 fclose(in);\r
134 \r
135                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
136 \r
137                 return;\r
138         }\r
139 \r
140         if(strncmp("PRT1", buf, 4) != 0)\r
141         {\r
142                 fclose(in);\r
143 \r
144                 Sys_Printf("  ERROR - File header indicates wrong file type (should be \"PRT1\").\n");\r
145 \r
146                 return;\r
147         }\r
148 \r
149         if(!fgets(buf, LINE_BUF, in))\r
150         {\r
151                 fclose(in);\r
152 \r
153                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
154 \r
155                 return;\r
156         }\r
157 \r
158         sscanf(buf, "%u", &node_count);\r
159 \r
160         if(node_count > 0xFFFF)\r
161         {\r
162                 fclose(in);\r
163 \r
164                 node_count = 0;\r
165 \r
166                 Sys_Printf("  ERROR - Extreme number of nodes, aborting.\n");\r
167 \r
168                 return;\r
169         }\r
170 \r
171         if(!fgets(buf, LINE_BUF, in))\r
172         {\r
173                 fclose(in);\r
174 \r
175                 node_count = 0;\r
176 \r
177                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
178 \r
179                 return;\r
180         }\r
181 \r
182         unsigned int p_count;\r
183         sscanf(buf, "%u", &p_count);\r
184 \r
185         if(!fgets(buf, LINE_BUF, in))\r
186         {\r
187                 fclose(in);\r
188 \r
189                 node_count = 0;\r
190 \r
191                 Sys_Printf("  ERROR - File ended prematurely.\n");\r
192 \r
193                 return;\r
194         }\r
195 \r
196         unsigned int p_count2;\r
197         sscanf(buf, "%u", &p_count2);\r
198 \r
199         node = new CBspNode[node_count];\r
200 \r
201         unsigned int i;\r
202         for(i = 0; i < p_count; i++)\r
203         {\r
204                 if(!fgets(buf, LINE_BUF, in))\r
205                 {\r
206                         fclose(in);\r
207 \r
208                         node_count = 0;\r
209 \r
210                         Sys_Printf("  ERROR - File ended prematurely.\n");\r
211 \r
212                         return;\r
213                 }\r
214 \r
215                 unsigned int dummy, node1, node2;\r
216                 sscanf(buf, "%u %u %u", &dummy, &node1, &node2);\r
217 \r
218                 node[node1].portal_count++;\r
219                 node[node2].portal_count++;\r
220         }\r
221 \r
222         for(i = 0; i < p_count2; i++)\r
223         {\r
224                 if(!fgets(buf, LINE_BUF, in))\r
225                 {\r
226                         fclose(in);\r
227 \r
228                         node_count = 0;\r
229 \r
230                         Sys_Printf("  ERROR - File ended prematurely.\n");\r
231 \r
232                         return;\r
233                 }\r
234 \r
235                 unsigned int dummy, node1;\r
236                 sscanf(buf, "%u %u", &dummy, &node1);\r
237 \r
238                 node[node1].portal_count++;\r
239         }\r
240 \r
241         for(i = 0; i < node_count; i++)\r
242                 node[i].portal = new CBspPortal[node[i].portal_count];\r
243 \r
244         fclose(in);\r
245 \r
246         in = fopen(fn, "rt");\r
247 \r
248         fgets(buf, LINE_BUF, in);\r
249         fgets(buf, LINE_BUF, in);\r
250         fgets(buf, LINE_BUF, in);\r
251         fgets(buf, LINE_BUF, in);\r
252 \r
253         unsigned int n;\r
254         for(n = 0; n < p_count; n++)\r
255         {\r
256                 if(!fgets(buf, LINE_BUF, in))\r
257                 {\r
258                         fclose(in);\r
259 \r
260                         Purge();\r
261 \r
262                         Sys_Printf("  ERROR - Could not find information for portal number %d of %d.\n", n + 1, p_count);\r
263 \r
264                         return;\r
265                 }\r
266 \r
267                 unsigned int pCount, node1, node2;\r
268                 sscanf(buf, "%u %u %u", &pCount, &node1, &node2);\r
269 \r
270                 if(!node[node1].AddPortal(buf, pCount, FALSE))\r
271                 {\r
272                         fclose(in);\r
273 \r
274                         Purge();\r
275 \r
276                         Sys_Printf("  ERROR - Information for portal number %d of %d is not formatted correctly.\n", n + 1, p_count);\r
277 \r
278                         return;\r
279                 }\r
280 \r
281                 if(!node[node2].AddPortal(buf, pCount, TRUE))\r
282                 {\r
283                         fclose(in);\r
284 \r
285                         Purge();\r
286 \r
287                         Sys_Printf("  ERROR - Information for portal number %d of %d is not formatted correctly.\n", n + 1, p_count);\r
288 \r
289                         return;\r
290                 }\r
291         }\r
292 \r
293  for(n = 0; n < p_count2; n++)\r
294         {\r
295                 if(!fgets(buf, LINE_BUF, in))\r
296                 {\r
297                         fclose(in);\r
298 \r
299                         Purge();\r
300 \r
301                         Sys_Printf("  ERROR - Could not find information for portal number %d of %d.\n", n + 1, p_count);\r
302 \r
303                         return;\r
304                 }\r
305 \r
306                 unsigned int pCount, node1;\r
307                 sscanf(buf, "%u %u", &pCount, &node1);\r
308 \r
309                 if(!node[node1].AddPortal(buf, pCount, FALSE))\r
310                 {\r
311                         fclose(in);\r
312 \r
313                         Purge();\r
314 \r
315                         Sys_Printf("  ERROR - Information for portal number %d of %d is not formatted correctly.\n", n + 1, p_count);\r
316 \r
317                         return;\r
318                 }\r
319         }\r
320 \r
321         fclose(in);\r
322 }\r
323 \r
324 CBspNode::CBspNode()\r
325 {\r
326         portal = NULL;\r
327         portal_count = 0;\r
328         portal_next = 0;\r
329 }\r
330 \r
331 CBspNode::~CBspNode()\r
332 {\r
333         if(portal != NULL)\r
334                 delete[] portal;\r
335 }\r
336 \r
337 bool CBspNode::AddPortal(char *def, unsigned int pointCnt, bool bInverse)\r
338 {\r
339         return portal[portal_next++].Build(def, pointCnt, bInverse);\r
340 }\r