1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #if !defined( INCLUDED_BRUSHTOKENS_H )
23 #define INCLUDED_BRUSHTOKENS_H
24
25 #include "stringio.h"
26 #include "stream/stringstream.h"
27 #include "brush.h"
28
FaceShader_importContentsFlagsValue(FaceShader & faceShader,Tokeniser & tokeniser)29 inline bool FaceShader_importContentsFlagsValue( FaceShader& faceShader, Tokeniser& tokeniser ){
30 // parse the optional contents/flags/value
31 RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_contentFlags ) );
32 RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_surfaceFlags ) );
33 RETURN_FALSE_IF_FAIL( Tokeniser_getInteger( tokeniser, faceShader.m_flags.m_value ) );
34 return true;
35 }
36
FaceTexdef_importTokens(FaceTexdef & texdef,Tokeniser & tokeniser)37 inline bool FaceTexdef_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
38 // parse texdef
39 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[0] ) );
40 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[1] ) );
41 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.rotate ) );
42 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[0] ) );
43 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[1] ) );
44
45 ASSERT_MESSAGE( texdef_sane( texdef.m_projection.m_texdef ), "FaceTexdef_importTokens: bad texdef" );
46 return true;
47 }
48
FaceTexdef_BP_importTokens(FaceTexdef & texdef,Tokeniser & tokeniser)49 inline bool FaceTexdef_BP_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
50 // parse alternate texdef
51 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
52 {
53 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
54 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][0] ) );
55 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][1] ) );
56 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[0][2] ) );
57 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
58 }
59 {
60 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
61 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][0] ) );
62 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][1] ) );
63 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_brushprimit_texdef.coords[1][2] ) );
64 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
65 }
66 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
67 return true;
68 }
69
FaceTexdef_HalfLife_importTokens(FaceTexdef & texdef,Tokeniser & tokeniser)70 inline bool FaceTexdef_HalfLife_importTokens( FaceTexdef& texdef, Tokeniser& tokeniser ){
71 // parse texdef
72 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
73 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.x() ) );
74 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.y() ) );
75 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_s.z() ) );
76 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[0] ) );
77 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "]" ) );
78 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "[" ) );
79 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.x() ) );
80 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.y() ) );
81 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_basis_t.z() ) );
82 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.shift[1] ) );
83 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "]" ) );
84 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.rotate ) );
85 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[0] ) );
86 RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, texdef.m_projection.m_texdef.scale[1] ) );
87
88 texdef.m_projection.m_texdef.rotate = -texdef.m_projection.m_texdef.rotate;
89
90 ASSERT_MESSAGE( texdef_sane( texdef.m_projection.m_texdef ), "FaceTexdef_importTokens: bad texdef" );
91 return true;
92 }
93
FacePlane_importTokens(FacePlane & facePlane,Tokeniser & tokeniser)94 inline bool FacePlane_importTokens( FacePlane& facePlane, Tokeniser& tokeniser ){
95 // parse planepts
96 for ( std::size_t i = 0; i < 3; i++ )
97 {
98 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
99 for ( std::size_t j = 0; j < 3; ++j )
100 {
101 RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, facePlane.planePoints()[i][j] ) );
102 }
103 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
104 }
105 facePlane.MakePlane();
106 return true;
107 }
108
FacePlane_Doom3_importTokens(FacePlane & facePlane,Tokeniser & tokeniser)109 inline bool FacePlane_Doom3_importTokens( FacePlane& facePlane, Tokeniser& tokeniser ){
110 Plane3 plane;
111 // parse plane equation
112 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) );
113 RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.a ) );
114 RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.b ) );
115 RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.c ) );
116 RETURN_FALSE_IF_FAIL( Tokeniser_getDouble( tokeniser, plane.d ) );
117 plane.d = -plane.d;
118 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) );
119
120 facePlane.setDoom3Plane( plane );
121 return true;
122 }
123
FaceShader_Doom3_importTokens(FaceShader & faceShader,Tokeniser & tokeniser)124 inline bool FaceShader_Doom3_importTokens( FaceShader& faceShader, Tokeniser& tokeniser ){
125 const char *shader = tokeniser.getToken();
126 if ( shader == 0 ) {
127 Tokeniser_unexpectedError( tokeniser, shader, "#shader-name" );
128 return false;
129 }
130 if ( string_equal( shader, "_emptyname" ) ) {
131 shader = texdef_name_default();
132 }
133 faceShader.setShader( shader );
134 return true;
135 }
136
FaceShader_importTokens(FaceShader & faceShader,Tokeniser & tokeniser)137 inline bool FaceShader_importTokens( FaceShader& faceShader, Tokeniser& tokeniser ){
138 const char* texture = tokeniser.getToken();
139 if ( texture == 0 ) {
140 Tokeniser_unexpectedError( tokeniser, texture, "#texture-name" );
141 return false;
142 }
143 if ( string_equal( texture, "NULL" ) ) {
144 faceShader.setShader( texdef_name_default() );
145 }
146 else
147 {
148 StringOutputStream shader( string_length( GlobalTexturePrefix_get() ) + string_length( texture ) );
149 shader << GlobalTexturePrefix_get() << texture;
150 faceShader.setShader( shader.c_str() );
151 }
152 return true;
153 }
154
155
156
157
158 class Doom3FaceTokenImporter
159 {
160 Face& m_face;
161 public:
Doom3FaceTokenImporter(Face & face)162 Doom3FaceTokenImporter( Face& face ) : m_face( face ){
163 }
importTokens(Tokeniser & tokeniser)164 bool importTokens( Tokeniser& tokeniser ){
165 RETURN_FALSE_IF_FAIL( FacePlane_Doom3_importTokens( m_face.getPlane(), tokeniser ) );
166 RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
167 RETURN_FALSE_IF_FAIL( FaceShader_Doom3_importTokens( m_face.getShader(), tokeniser ) );
168 RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
169
170 m_face.getTexdef().m_projectionInitialised = true;
171 m_face.getTexdef().m_scaleApplied = true;
172
173 return true;
174 }
175 };
176
177 class Quake4FaceTokenImporter
178 {
179 Face& m_face;
180 public:
Quake4FaceTokenImporter(Face & face)181 Quake4FaceTokenImporter( Face& face ) : m_face( face ){
182 }
importTokens(Tokeniser & tokeniser)183 bool importTokens( Tokeniser& tokeniser ){
184 RETURN_FALSE_IF_FAIL( FacePlane_Doom3_importTokens( m_face.getPlane(), tokeniser ) );
185 RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
186 RETURN_FALSE_IF_FAIL( FaceShader_Doom3_importTokens( m_face.getShader(), tokeniser ) );
187
188 m_face.getTexdef().m_projectionInitialised = true;
189 m_face.getTexdef().m_scaleApplied = true;
190
191 return true;
192 }
193 };
194
195 class Quake2FaceTokenImporter
196 {
197 Face& m_face;
198 public:
Quake2FaceTokenImporter(Face & face)199 Quake2FaceTokenImporter( Face& face ) : m_face( face ){
200 }
importTokens(Tokeniser & tokeniser)201 bool importTokens( Tokeniser& tokeniser ){
202 RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
203 RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
204 RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
205 if ( Tokeniser_nextTokenIsDigit( tokeniser ) ) {
206 m_face.getShader().m_flags.m_specified = true;
207 RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
208 }
209 m_face.getTexdef().m_scaleApplied = true;
210 return true;
211 }
212 };
213
214 class Quake3FaceTokenImporter
215 {
216 Face& m_face;
217 public:
Quake3FaceTokenImporter(Face & face)218 Quake3FaceTokenImporter( Face& face ) : m_face( face ){
219 }
importTokens(Tokeniser & tokeniser)220 bool importTokens( Tokeniser& tokeniser ){
221 RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
222 RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
223 RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
224 RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
225 m_face.getTexdef().m_scaleApplied = true;
226 return true;
227 }
228 };
229
230 class Quake3BPFaceTokenImporter
231 {
232 Face& m_face;
233 public:
Quake3BPFaceTokenImporter(Face & face)234 Quake3BPFaceTokenImporter( Face& face ) : m_face( face ){
235 }
importTokens(Tokeniser & tokeniser)236 bool importTokens( Tokeniser& tokeniser ){
237 RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
238 RETURN_FALSE_IF_FAIL( FaceTexdef_BP_importTokens( m_face.getTexdef(), tokeniser ) );
239 RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
240 RETURN_FALSE_IF_FAIL( FaceShader_importContentsFlagsValue( m_face.getShader(), tokeniser ) );
241
242 m_face.getTexdef().m_projectionInitialised = true;
243 m_face.getTexdef().m_scaleApplied = true;
244
245 return true;
246 }
247 };
248
249 class QuakeFaceTokenImporter
250 {
251 Face& m_face;
252 public:
QuakeFaceTokenImporter(Face & face)253 QuakeFaceTokenImporter( Face& face ) : m_face( face ){
254 }
importTokens(Tokeniser & tokeniser)255 bool importTokens( Tokeniser& tokeniser ){
256 RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
257 RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
258 RETURN_FALSE_IF_FAIL( FaceTexdef_importTokens( m_face.getTexdef(), tokeniser ) );
259 m_face.getTexdef().m_scaleApplied = true;
260 return true;
261 }
262 };
263
264 class HalfLifeFaceTokenImporter
265 {
266 Face& m_face;
267 public:
HalfLifeFaceTokenImporter(Face & face)268 HalfLifeFaceTokenImporter( Face& face ) : m_face( face ){
269 }
importTokens(Tokeniser & tokeniser)270 bool importTokens( Tokeniser& tokeniser ){
271 RETURN_FALSE_IF_FAIL( FacePlane_importTokens( m_face.getPlane(), tokeniser ) );
272 RETURN_FALSE_IF_FAIL( FaceShader_importTokens( m_face.getShader(), tokeniser ) );
273 RETURN_FALSE_IF_FAIL( FaceTexdef_HalfLife_importTokens( m_face.getTexdef(), tokeniser ) );
274 m_face.getTexdef().m_scaleApplied = true;
275 return true;
276 }
277 };
278
279
FacePlane_Doom3_exportTokens(const FacePlane & facePlane,TokenWriter & writer)280 inline void FacePlane_Doom3_exportTokens( const FacePlane& facePlane, TokenWriter& writer ){
281 // write plane equation
282 writer.writeToken( "(" );
283 writer.writeFloat( facePlane.getDoom3Plane().a );
284 writer.writeFloat( facePlane.getDoom3Plane().b );
285 writer.writeFloat( facePlane.getDoom3Plane().c );
286 writer.writeFloat( -facePlane.getDoom3Plane().d );
287 writer.writeToken( ")" );
288 }
289
FacePlane_exportTokens(const FacePlane & facePlane,TokenWriter & writer)290 inline void FacePlane_exportTokens( const FacePlane& facePlane, TokenWriter& writer ){
291 // write planepts
292 for ( std::size_t i = 0; i < 3; i++ )
293 {
294 writer.writeToken( "(" );
295 for ( std::size_t j = 0; j < 3; j++ )
296 {
297 writer.writeFloat( Face::m_quantise( facePlane.planePoints()[i][j] ) );
298 }
299 writer.writeToken( ")" );
300 }
301 }
302
FaceTexdef_BP_exportTokens(const FaceTexdef & faceTexdef,TokenWriter & writer)303 inline void FaceTexdef_BP_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
304 // write alternate texdef
305 writer.writeToken( "(" );
306 {
307 writer.writeToken( "(" );
308 for ( std::size_t i = 0; i < 3; i++ )
309 {
310 writer.writeFloat( faceTexdef.m_projection.m_brushprimit_texdef.coords[0][i] );
311 }
312 writer.writeToken( ")" );
313 }
314 {
315 writer.writeToken( "(" );
316 for ( std::size_t i = 0; i < 3; i++ )
317 {
318 writer.writeFloat( faceTexdef.m_projection.m_brushprimit_texdef.coords[1][i] );
319 }
320 writer.writeToken( ")" );
321 }
322 writer.writeToken( ")" );
323 }
324
FaceTexdef_exportTokens(const FaceTexdef & faceTexdef,TokenWriter & writer)325 inline void FaceTexdef_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
326 ASSERT_MESSAGE( texdef_sane( faceTexdef.m_projection.m_texdef ), "FaceTexdef_exportTokens: bad texdef" );
327 // write texdef
328 writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[0] );
329 writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[1] );
330 writer.writeFloat( faceTexdef.m_projection.m_texdef.rotate );
331 writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[0] );
332 writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[1] );
333 }
334
FaceTexdef_HalfLife_exportTokens(const FaceTexdef & faceTexdef,TokenWriter & writer)335 inline void FaceTexdef_HalfLife_exportTokens( const FaceTexdef& faceTexdef, TokenWriter& writer ){
336 ASSERT_MESSAGE( texdef_sane( faceTexdef.m_projection.m_texdef ), "FaceTexdef_exportTokens: bad texdef" );
337 // write texdef
338 writer.writeToken( "[" );
339 writer.writeFloat( faceTexdef.m_projection.m_basis_s.x() );
340 writer.writeFloat( faceTexdef.m_projection.m_basis_s.y() );
341 writer.writeFloat( faceTexdef.m_projection.m_basis_s.z() );
342 writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[0] );
343 writer.writeToken( "]" );
344 writer.writeToken( "[" );
345 writer.writeFloat( faceTexdef.m_projection.m_basis_t.x() );
346 writer.writeFloat( faceTexdef.m_projection.m_basis_t.y() );
347 writer.writeFloat( faceTexdef.m_projection.m_basis_t.z() );
348 writer.writeFloat( faceTexdef.m_projection.m_texdef.shift[1] );
349 writer.writeToken( "]" );
350 writer.writeFloat( -faceTexdef.m_projection.m_texdef.rotate );
351 writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[0] );
352 writer.writeFloat( faceTexdef.m_projection.m_texdef.scale[1] );
353 }
354
FaceShader_ContentsFlagsValue_exportTokens(const FaceShader & faceShader,TokenWriter & writer)355 inline void FaceShader_ContentsFlagsValue_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
356 // write surface flags
357 writer.writeInteger( faceShader.m_flags.m_contentFlags );
358 writer.writeInteger( faceShader.m_flags.m_surfaceFlags );
359 writer.writeInteger( faceShader.m_flags.m_value );
360 }
361
FaceShader_exportTokens(const FaceShader & faceShader,TokenWriter & writer)362 inline void FaceShader_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
363 // write shader name
364 if ( string_empty( shader_get_textureName( faceShader.getShader() ) ) ) {
365 writer.writeToken( "NULL" );
366 }
367 else
368 {
369 writer.writeToken( shader_get_textureName( faceShader.getShader() ) );
370 }
371 }
372
FaceShader_Doom3_exportTokens(const FaceShader & faceShader,TokenWriter & writer)373 inline void FaceShader_Doom3_exportTokens( const FaceShader& faceShader, TokenWriter& writer ){
374 // write shader name
375 if ( string_empty( shader_get_textureName( faceShader.getShader() ) ) ) {
376 writer.writeString( "_emptyname" );
377 }
378 else
379 {
380 writer.writeString( faceShader.getShader() );
381 }
382 }
383
384 class Doom3FaceTokenExporter
385 {
386 const Face& m_face;
387 public:
Doom3FaceTokenExporter(const Face & face)388 Doom3FaceTokenExporter( const Face& face ) : m_face( face ){
389 }
exportTokens(TokenWriter & writer)390 void exportTokens( TokenWriter& writer ) const {
391 FacePlane_Doom3_exportTokens( m_face.getPlane(), writer );
392 FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
393 FaceShader_Doom3_exportTokens( m_face.getShader(), writer );
394 FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
395 writer.nextLine();
396 }
397 };
398
399 class Quake4FaceTokenExporter
400 {
401 const Face& m_face;
402 public:
Quake4FaceTokenExporter(const Face & face)403 Quake4FaceTokenExporter( const Face& face ) : m_face( face ){
404 }
exportTokens(TokenWriter & writer)405 void exportTokens( TokenWriter& writer ) const {
406 FacePlane_Doom3_exportTokens( m_face.getPlane(), writer );
407 FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
408 FaceShader_Doom3_exportTokens( m_face.getShader(), writer );
409 writer.nextLine();
410 }
411 };
412
413 class Quake2FaceTokenExporter
414 {
415 const Face& m_face;
416 public:
Quake2FaceTokenExporter(const Face & face)417 Quake2FaceTokenExporter( const Face& face ) : m_face( face ){
418 }
exportTokens(TokenWriter & writer)419 void exportTokens( TokenWriter& writer ) const {
420 FacePlane_exportTokens( m_face.getPlane(), writer );
421 FaceShader_exportTokens( m_face.getShader(), writer );
422 FaceTexdef_exportTokens( m_face.getTexdef(), writer );
423 if ( m_face.getShader().m_flags.m_specified || m_face.isDetail() ) {
424 FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
425 }
426 writer.nextLine();
427 }
428 };
429
430 class Quake3FaceTokenExporter
431 {
432 const Face& m_face;
433 public:
Quake3FaceTokenExporter(const Face & face)434 Quake3FaceTokenExporter( const Face& face ) : m_face( face ){
435 }
exportTokens(TokenWriter & writer)436 void exportTokens( TokenWriter& writer ) const {
437 FacePlane_exportTokens( m_face.getPlane(), writer );
438 FaceShader_exportTokens( m_face.getShader(), writer );
439 FaceTexdef_exportTokens( m_face.getTexdef(), writer );
440 FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
441 writer.nextLine();
442 }
443 };
444
445 class Quake3BPFaceTokenExporter
446 {
447 const Face& m_face;
448 public:
Quake3BPFaceTokenExporter(const Face & face)449 Quake3BPFaceTokenExporter( const Face& face ) : m_face( face ){
450 }
exportTokens(TokenWriter & writer)451 void exportTokens( TokenWriter& writer ) const {
452 FacePlane_exportTokens( m_face.getPlane(), writer );
453 FaceTexdef_BP_exportTokens( m_face.getTexdef(), writer );
454 FaceShader_exportTokens( m_face.getShader(), writer );
455 FaceShader_ContentsFlagsValue_exportTokens( m_face.getShader(), writer );
456 writer.nextLine();
457 }
458 };
459
460 class QuakeFaceTokenExporter
461 {
462 const Face& m_face;
463 public:
QuakeFaceTokenExporter(const Face & face)464 QuakeFaceTokenExporter( const Face& face ) : m_face( face ){
465 }
exportTokens(TokenWriter & writer)466 void exportTokens( TokenWriter& writer ) const {
467 FacePlane_exportTokens( m_face.getPlane(), writer );
468 FaceShader_exportTokens( m_face.getShader(), writer );
469 FaceTexdef_exportTokens( m_face.getTexdef(), writer );
470 writer.nextLine();
471 }
472 };
473
474 class HalfLifeFaceTokenExporter
475 {
476 const Face& m_face;
477 public:
HalfLifeFaceTokenExporter(const Face & face)478 HalfLifeFaceTokenExporter( const Face& face ) : m_face( face ){
479 }
exportTokens(TokenWriter & writer)480 void exportTokens( TokenWriter& writer ) const {
481 FacePlane_exportTokens( m_face.getPlane(), writer );
482 FaceShader_exportTokens( m_face.getShader(), writer );
483 FaceTexdef_HalfLife_exportTokens( m_face.getTexdef(), writer );
484 writer.nextLine();
485 }
486 };
487
488
489 class BrushTokenImporter : public MapImporter
490 {
491 Brush& m_brush;
492
493 public:
BrushTokenImporter(Brush & brush)494 BrushTokenImporter( Brush& brush ) : m_brush( brush ){
495 }
importTokens(Tokeniser & tokeniser)496 bool importTokens( Tokeniser& tokeniser ){
497 if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
498 tokeniser.nextLine();
499 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "{" ) );
500 }
501 while ( 1 )
502 {
503 // check for end of brush
504 tokeniser.nextLine();
505 const char* token = tokeniser.getToken();
506 if ( string_equal( token, "}" ) ) {
507 break;
508 }
509
510 tokeniser.ungetToken();
511
512 m_brush.push_back( FaceSmartPointer( new Face( &m_brush ) ) );
513
514 //!todo BP support
515 tokeniser.nextLine();
516
517 Face& face = *m_brush.back();
518
519 switch ( Brush::m_type )
520 {
521 case eBrushTypeDoom3:
522 {
523 Doom3FaceTokenImporter importer( face );
524 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
525 }
526 break;
527 case eBrushTypeQuake4:
528 {
529 Quake4FaceTokenImporter importer( face );
530 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
531 }
532 break;
533 case eBrushTypeQuake2:
534 {
535 Quake2FaceTokenImporter importer( face );
536 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
537 }
538 break;
539 case eBrushTypeQuake3:
540 {
541 Quake3FaceTokenImporter importer( face );
542 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
543 }
544 break;
545 case eBrushTypeQuake3BP:
546 {
547 Quake3BPFaceTokenImporter importer( face );
548 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
549 }
550 break;
551 case eBrushTypeQuake:
552 {
553 QuakeFaceTokenImporter importer( face );
554 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
555 }
556 break;
557 case eBrushTypeHalfLife:
558 {
559 HalfLifeFaceTokenImporter importer( face );
560 RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
561 }
562 break;
563 }
564 face.planeChanged();
565 }
566 if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
567 tokeniser.nextLine();
568 RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "}" ) );
569 }
570
571 m_brush.planeChanged();
572 m_brush.shaderChanged();
573
574 return true;
575 }
576 };
577
578
579 class BrushTokenExporter : public MapExporter
580 {
581 const Brush& m_brush;
582
583 public:
BrushTokenExporter(const Brush & brush)584 BrushTokenExporter( const Brush& brush ) : m_brush( brush ){
585 }
exportTokens(TokenWriter & writer)586 void exportTokens( TokenWriter& writer ) const {
587 m_brush.evaluateBRep(); // ensure b-rep is up-to-date, so that non-contributing faces can be identified.
588
589 if ( !m_brush.hasContributingFaces() ) {
590 return;
591 }
592
593 writer.writeToken( "{" );
594 writer.nextLine();
595
596 if ( Brush::m_type == eBrushTypeQuake3BP ) {
597 writer.writeToken( "brushDef" );
598 writer.nextLine();
599 writer.writeToken( "{" );
600 writer.nextLine();
601 }
602
603 if ( Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
604 writer.writeToken( "brushDef3" );
605 writer.nextLine();
606 writer.writeToken( "{" );
607 writer.nextLine();
608 }
609
610 for ( Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i )
611 {
612 const Face& face = *( *i );
613
614 if ( face.contributes() ) {
615 switch ( Brush::m_type )
616 {
617 case eBrushTypeDoom3:
618 {
619 Doom3FaceTokenExporter exporter( face );
620 exporter.exportTokens( writer );
621 }
622 break;
623 case eBrushTypeQuake4:
624 {
625 Quake4FaceTokenExporter exporter( face );
626 exporter.exportTokens( writer );
627 }
628 break;
629 case eBrushTypeQuake2:
630 {
631 Quake2FaceTokenExporter exporter( face );
632 exporter.exportTokens( writer );
633 }
634 break;
635 case eBrushTypeQuake3:
636 {
637 Quake3FaceTokenExporter exporter( face );
638 exporter.exportTokens( writer );
639 }
640 break;
641 case eBrushTypeQuake3BP:
642 {
643 Quake3BPFaceTokenExporter exporter( face );
644 exporter.exportTokens( writer );
645 }
646 break;
647 case eBrushTypeQuake:
648 {
649 QuakeFaceTokenExporter exporter( face );
650 exporter.exportTokens( writer );
651 }
652 break;
653 case eBrushTypeHalfLife:
654 {
655 HalfLifeFaceTokenExporter exporter( face );
656 exporter.exportTokens( writer );
657 }
658 break;
659 }
660 }
661 }
662
663 if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
664 writer.writeToken( "}" );
665 writer.nextLine();
666 }
667
668 writer.writeToken( "}" );
669 writer.nextLine();
670 }
671 };
672
673
674 #endif
675