DeclFX.cpp (11375B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "../idlib/precompiled.h" 30 #pragma hdrstop 31 32 33 /* 34 ================= 35 idDeclFX::Size 36 ================= 37 */ 38 size_t idDeclFX::Size() const { 39 return sizeof( idDeclFX ); 40 } 41 42 /* 43 =============== 44 idDeclFX::Print 45 =============== 46 */ 47 void idDeclFX::Print() const { 48 const idDeclFX *list = this; 49 50 common->Printf("%d events\n", list->events.Num() ); 51 for( int i = 0; i < list->events.Num(); i++ ) { 52 switch( list->events[i].type ) { 53 case FX_LIGHT: 54 common->Printf("FX_LIGHT %s\n", list->events[i].data.c_str()); 55 break; 56 case FX_PARTICLE: 57 common->Printf("FX_PARTICLE %s\n", list->events[i].data.c_str()); 58 break; 59 case FX_MODEL: 60 common->Printf("FX_MODEL %s\n", list->events[i].data.c_str()); 61 break; 62 case FX_SOUND: 63 common->Printf("FX_SOUND %s\n", list->events[i].data.c_str()); 64 break; 65 case FX_DECAL: 66 common->Printf("FX_DECAL %s\n", list->events[i].data.c_str()); 67 break; 68 case FX_SHAKE: 69 common->Printf("FX_SHAKE %s\n", list->events[i].data.c_str()); 70 break; 71 case FX_ATTACHLIGHT: 72 common->Printf("FX_ATTACHLIGHT %s\n", list->events[i].data.c_str()); 73 break; 74 case FX_ATTACHENTITY: 75 common->Printf("FX_ATTACHENTITY %s\n", list->events[i].data.c_str()); 76 break; 77 case FX_LAUNCH: 78 common->Printf("FX_LAUNCH %s\n", list->events[i].data.c_str()); 79 break; 80 case FX_SHOCKWAVE: 81 common->Printf("FX_SHOCKWAVE %s\n", list->events[i].data.c_str()); 82 break; 83 } 84 } 85 } 86 87 /* 88 =============== 89 idDeclFX::List 90 =============== 91 */ 92 void idDeclFX::List() const { 93 common->Printf("%s, %d stages\n", GetName(), events.Num() ); 94 } 95 96 /* 97 ================ 98 idDeclFX::ParseSingleFXAction 99 ================ 100 */ 101 void idDeclFX::ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction ) { 102 idToken token; 103 104 FXAction.type = -1; 105 FXAction.sibling = -1; 106 107 FXAction.data = "<none>"; 108 FXAction.name = "<none>"; 109 FXAction.fire = "<none>"; 110 111 FXAction.delay = 0.0f; 112 FXAction.duration = 0.0f; 113 FXAction.restart = 0.0f; 114 FXAction.size = 0.0f; 115 FXAction.fadeInTime = 0.0f; 116 FXAction.fadeOutTime = 0.0f; 117 FXAction.shakeTime = 0.0f; 118 FXAction.shakeAmplitude = 0.0f; 119 FXAction.shakeDistance = 0.0f; 120 FXAction.shakeFalloff = false; 121 FXAction.shakeImpulse = 0.0f; 122 FXAction.shakeIgnoreMaster = false; 123 FXAction.lightRadius = 0.0f; 124 FXAction.rotate = 0.0f; 125 FXAction.random1 = 0.0f; 126 FXAction.random2 = 0.0f; 127 128 FXAction.lightColor = vec3_origin; 129 FXAction.offset = vec3_origin; 130 FXAction.axis = mat3_identity; 131 132 FXAction.bindParticles = false; 133 FXAction.explicitAxis = false; 134 FXAction.noshadows = false; 135 FXAction.particleTrackVelocity = false; 136 FXAction.trackOrigin = false; 137 FXAction.soundStarted = false; 138 139 while (1) { 140 if ( !src.ReadToken( &token ) ) { 141 break; 142 } 143 144 if ( !token.Icmp( "}" ) ) { 145 break; 146 } 147 148 if ( !token.Icmp( "shake" ) ) { 149 FXAction.type = FX_SHAKE; 150 FXAction.shakeTime = src.ParseFloat(); 151 src.ExpectTokenString(","); 152 FXAction.shakeAmplitude = src.ParseFloat(); 153 src.ExpectTokenString(","); 154 FXAction.shakeDistance = src.ParseFloat(); 155 src.ExpectTokenString(","); 156 FXAction.shakeFalloff = src.ParseBool(); 157 src.ExpectTokenString(","); 158 FXAction.shakeImpulse = src.ParseFloat(); 159 continue; 160 } 161 162 if ( !token.Icmp( "noshadows" ) ) { 163 FXAction.noshadows = true; 164 continue; 165 } 166 167 if ( !token.Icmp( "name" ) ) { 168 src.ReadToken( &token ); 169 FXAction.name = token; 170 continue; 171 } 172 173 if ( !token.Icmp( "fire") ) { 174 src.ReadToken( &token ); 175 FXAction.fire = token; 176 continue; 177 } 178 179 if ( !token.Icmp( "random" ) ) { 180 FXAction.random1 = src.ParseFloat(); 181 src.ExpectTokenString( "," ); 182 FXAction.random2 = src.ParseFloat(); 183 FXAction.delay = 0.0f; // check random 184 continue; 185 } 186 187 if ( !token.Icmp( "delay" ) ) { 188 FXAction.delay = src.ParseFloat(); 189 continue; 190 } 191 192 if ( !token.Icmp( "rotate" ) ) { 193 FXAction.rotate = src.ParseFloat(); 194 continue; 195 } 196 197 if ( !token.Icmp( "duration" ) ) { 198 FXAction.duration = src.ParseFloat(); 199 continue; 200 } 201 202 if ( !token.Icmp( "trackorigin" ) ) { 203 FXAction.trackOrigin = src.ParseBool(); 204 continue; 205 } 206 207 if (!token.Icmp("restart")) { 208 FXAction.restart = src.ParseFloat(); 209 continue; 210 } 211 212 if ( !token.Icmp( "fadeIn" ) ) { 213 FXAction.fadeInTime = src.ParseFloat(); 214 continue; 215 } 216 217 if ( !token.Icmp( "fadeOut" ) ) { 218 FXAction.fadeOutTime = src.ParseFloat(); 219 continue; 220 } 221 222 if ( !token.Icmp( "size" ) ) { 223 FXAction.size = src.ParseFloat(); 224 continue; 225 } 226 227 if ( !token.Icmp( "offset" ) ) { 228 FXAction.offset.x = src.ParseFloat(); 229 src.ExpectTokenString( "," ); 230 FXAction.offset.y = src.ParseFloat(); 231 src.ExpectTokenString( "," ); 232 FXAction.offset.z = src.ParseFloat(); 233 continue; 234 } 235 236 if ( !token.Icmp( "axis" ) ) { 237 idVec3 v; 238 v.x = src.ParseFloat(); 239 src.ExpectTokenString( "," ); 240 v.y = src.ParseFloat(); 241 src.ExpectTokenString( "," ); 242 v.z = src.ParseFloat(); 243 v.Normalize(); 244 FXAction.axis = v.ToMat3(); 245 FXAction.explicitAxis = true; 246 continue; 247 } 248 249 if ( !token.Icmp( "angle" ) ) { 250 idAngles a; 251 a[0] = src.ParseFloat(); 252 src.ExpectTokenString( "," ); 253 a[1] = src.ParseFloat(); 254 src.ExpectTokenString( "," ); 255 a[2] = src.ParseFloat(); 256 FXAction.axis = a.ToMat3(); 257 FXAction.explicitAxis = true; 258 continue; 259 } 260 261 if ( !token.Icmp( "uselight" ) ) { 262 src.ReadToken( &token ); 263 FXAction.data = token; 264 for( int i = 0; i < events.Num(); i++ ) { 265 if ( events[i].name.Icmp( FXAction.data ) == 0 ) { 266 FXAction.sibling = i; 267 FXAction.lightColor = events[i].lightColor; 268 FXAction.lightRadius = events[i].lightRadius; 269 } 270 } 271 FXAction.type = FX_LIGHT; 272 273 // precache the light material 274 declManager->FindMaterial( FXAction.data ); 275 continue; 276 } 277 278 if ( !token.Icmp( "attachlight" ) ) { 279 src.ReadToken( &token ); 280 FXAction.data = token; 281 FXAction.type = FX_ATTACHLIGHT; 282 283 // precache it 284 declManager->FindMaterial( FXAction.data ); 285 continue; 286 } 287 288 if ( !token.Icmp( "attachentity" ) ) { 289 src.ReadToken( &token ); 290 FXAction.data = token; 291 FXAction.type = FX_ATTACHENTITY; 292 293 // precache the model 294 renderModelManager->FindModel( FXAction.data ); 295 continue; 296 } 297 298 if ( !token.Icmp( "launch" ) ) { 299 src.ReadToken( &token ); 300 FXAction.data = token; 301 FXAction.type = FX_LAUNCH; 302 303 // precache the entity def 304 declManager->FindType( DECL_ENTITYDEF, FXAction.data ); 305 continue; 306 } 307 308 if ( !token.Icmp( "useModel" ) ) { 309 src.ReadToken( &token ); 310 FXAction.data = token; 311 for( int i = 0; i < events.Num(); i++ ) { 312 if ( events[i].name.Icmp( FXAction.data ) == 0 ) { 313 FXAction.sibling = i; 314 } 315 } 316 FXAction.type = FX_MODEL; 317 318 // precache the model 319 renderModelManager->FindModel( FXAction.data ); 320 continue; 321 } 322 323 if ( !token.Icmp( "light" ) ) { 324 src.ReadToken( &token ); 325 FXAction.data = token; 326 src.ExpectTokenString( "," ); 327 FXAction.lightColor[0] = src.ParseFloat(); 328 src.ExpectTokenString( "," ); 329 FXAction.lightColor[1] = src.ParseFloat(); 330 src.ExpectTokenString( "," ); 331 FXAction.lightColor[2] = src.ParseFloat(); 332 src.ExpectTokenString( "," ); 333 FXAction.lightRadius = src.ParseFloat(); 334 FXAction.type = FX_LIGHT; 335 336 // precache the light material 337 declManager->FindMaterial( FXAction.data ); 338 continue; 339 } 340 341 if ( !token.Icmp( "model" ) ) { 342 src.ReadToken( &token ); 343 FXAction.data = token; 344 FXAction.type = FX_MODEL; 345 346 // precache it 347 renderModelManager->FindModel( FXAction.data ); 348 continue; 349 } 350 351 if ( !token.Icmp( "particle" ) ) { // FIXME: now the same as model 352 src.ReadToken( &token ); 353 FXAction.data = token; 354 FXAction.type = FX_PARTICLE; 355 356 // precache it 357 renderModelManager->FindModel( FXAction.data ); 358 continue; 359 } 360 361 if ( !token.Icmp( "decal" ) ) { 362 src.ReadToken( &token ); 363 FXAction.data = token; 364 FXAction.type = FX_DECAL; 365 366 // precache it 367 declManager->FindMaterial( FXAction.data ); 368 continue; 369 } 370 371 if ( !token.Icmp( "particleTrackVelocity" ) ) { 372 FXAction.particleTrackVelocity = true; 373 continue; 374 } 375 376 if ( !token.Icmp( "sound" ) ) { 377 src.ReadToken( &token ); 378 FXAction.data = token; 379 FXAction.type = FX_SOUND; 380 381 // precache it 382 declManager->FindSound( FXAction.data ); 383 continue; 384 } 385 386 if ( !token.Icmp( "ignoreMaster" ) ) { 387 FXAction.shakeIgnoreMaster = true; 388 continue; 389 } 390 391 if ( !token.Icmp( "shockwave" ) ) { 392 src.ReadToken( &token ); 393 FXAction.data = token; 394 FXAction.type = FX_SHOCKWAVE; 395 396 // precache the entity def 397 declManager->FindType( DECL_ENTITYDEF, FXAction.data ); 398 continue; 399 } 400 401 src.Warning( "FX File: bad token" ); 402 continue; 403 } 404 } 405 406 /* 407 ================ 408 idDeclFX::Parse 409 ================ 410 */ 411 bool idDeclFX::Parse( const char *text, const int textLength, bool allowBinaryVersion ) { 412 idLexer src; 413 idToken token; 414 415 src.LoadMemory( text, textLength, GetFileName(), GetLineNum() ); 416 src.SetFlags( DECL_LEXER_FLAGS ); 417 src.SkipUntilString( "{" ); 418 419 // scan through, identifying each individual parameter 420 while( 1 ) { 421 422 if ( !src.ReadToken( &token ) ) { 423 break; 424 } 425 426 if ( token == "}" ) { 427 break; 428 } 429 430 if ( !token.Icmp( "bindto" ) ) { 431 src.ReadToken( &token ); 432 joint = token; 433 continue; 434 } 435 436 if ( !token.Icmp( "{" ) ) { 437 idFXSingleAction action; 438 ParseSingleFXAction( src, action ); 439 events.Append( action ); 440 continue; 441 } 442 } 443 444 if ( src.HadError() ) { 445 src.Warning( "FX decl '%s' had a parse error", GetName() ); 446 return false; 447 } 448 return true; 449 } 450 451 /* 452 =================== 453 idDeclFX::DefaultDefinition 454 =================== 455 */ 456 const char *idDeclFX::DefaultDefinition() const { 457 return 458 "{\n" 459 "\t" "{\n" 460 "\t\t" "duration\t5\n" 461 "\t\t" "model\t\t_default\n" 462 "\t" "}\n" 463 "}"; 464 } 465 466 /* 467 =================== 468 idDeclFX::FreeData 469 =================== 470 */ 471 void idDeclFX::FreeData() { 472 events.Clear(); 473 }