2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 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.
14 Doom 3 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.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
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.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
38 size_t idDeclFX::Size( void ) const {
39 return sizeof( idDeclFX );
47 void idDeclFX::Print( void ) const {
48 const idDeclFX *list = this;
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 ) {
54 common->Printf("FX_LIGHT %s\n", list->events[i].data.c_str());
57 common->Printf("FX_PARTICLE %s\n", list->events[i].data.c_str());
60 common->Printf("FX_MODEL %s\n", list->events[i].data.c_str());
63 common->Printf("FX_SOUND %s\n", list->events[i].data.c_str());
66 common->Printf("FX_DECAL %s\n", list->events[i].data.c_str());
69 common->Printf("FX_SHAKE %s\n", list->events[i].data.c_str());
72 common->Printf("FX_ATTACHLIGHT %s\n", list->events[i].data.c_str());
75 common->Printf("FX_ATTACHENTITY %s\n", list->events[i].data.c_str());
78 common->Printf("FX_LAUNCH %s\n", list->events[i].data.c_str());
81 common->Printf("FX_SHOCKWAVE %s\n", list->events[i].data.c_str());
92 void idDeclFX::List( void ) const {
93 common->Printf("%s, %d stages\n", GetName(), events.Num() );
98 idDeclFX::ParseSingleFXAction
101 void idDeclFX::ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction ) {
105 FXAction.sibling = -1;
107 FXAction.data = "<none>";
108 FXAction.name = "<none>";
109 FXAction.fire = "<none>";
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;
128 FXAction.lightColor = vec3_origin;
129 FXAction.offset = vec3_origin;
130 FXAction.axis = mat3_identity;
132 FXAction.bindParticles = false;
133 FXAction.explicitAxis = false;
134 FXAction.noshadows = false;
135 FXAction.particleTrackVelocity = false;
136 FXAction.trackOrigin = false;
137 FXAction.soundStarted = false;
140 if ( !src.ReadToken( &token ) ) {
144 if ( !token.Icmp( "}" ) ) {
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();
162 if ( !token.Icmp( "noshadows" ) ) {
163 FXAction.noshadows = true;
167 if ( !token.Icmp( "name" ) ) {
168 src.ReadToken( &token );
169 FXAction.name = token;
173 if ( !token.Icmp( "fire") ) {
174 src.ReadToken( &token );
175 FXAction.fire = token;
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
187 if ( !token.Icmp( "delay" ) ) {
188 FXAction.delay = src.ParseFloat();
192 if ( !token.Icmp( "rotate" ) ) {
193 FXAction.rotate = src.ParseFloat();
197 if ( !token.Icmp( "duration" ) ) {
198 FXAction.duration = src.ParseFloat();
202 if ( !token.Icmp( "trackorigin" ) ) {
203 FXAction.trackOrigin = src.ParseBool();
207 if (!token.Icmp("restart")) {
208 FXAction.restart = src.ParseFloat();
212 if ( !token.Icmp( "fadeIn" ) ) {
213 FXAction.fadeInTime = src.ParseFloat();
217 if ( !token.Icmp( "fadeOut" ) ) {
218 FXAction.fadeOutTime = src.ParseFloat();
222 if ( !token.Icmp( "size" ) ) {
223 FXAction.size = src.ParseFloat();
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();
236 if ( !token.Icmp( "axis" ) ) {
238 v.x = src.ParseFloat();
239 src.ExpectTokenString( "," );
240 v.y = src.ParseFloat();
241 src.ExpectTokenString( "," );
242 v.z = src.ParseFloat();
244 FXAction.axis = v.ToMat3();
245 FXAction.explicitAxis = true;
249 if ( !token.Icmp( "angle" ) ) {
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;
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;
271 FXAction.type = FX_LIGHT;
273 // precache the light material
274 declManager->FindMaterial( FXAction.data );
278 if ( !token.Icmp( "attachlight" ) ) {
279 src.ReadToken( &token );
280 FXAction.data = token;
281 FXAction.type = FX_ATTACHLIGHT;
284 declManager->FindMaterial( FXAction.data );
288 if ( !token.Icmp( "attachentity" ) ) {
289 src.ReadToken( &token );
290 FXAction.data = token;
291 FXAction.type = FX_ATTACHENTITY;
293 // precache the model
294 renderModelManager->FindModel( FXAction.data );
298 if ( !token.Icmp( "launch" ) ) {
299 src.ReadToken( &token );
300 FXAction.data = token;
301 FXAction.type = FX_LAUNCH;
303 // precache the entity def
304 declManager->FindType( DECL_ENTITYDEF, FXAction.data );
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;
316 FXAction.type = FX_MODEL;
318 // precache the model
319 renderModelManager->FindModel( FXAction.data );
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;
336 // precache the light material
337 declManager->FindMaterial( FXAction.data );
341 if ( !token.Icmp( "model" ) ) {
342 src.ReadToken( &token );
343 FXAction.data = token;
344 FXAction.type = FX_MODEL;
347 renderModelManager->FindModel( FXAction.data );
351 if ( !token.Icmp( "particle" ) ) { // FIXME: now the same as model
352 src.ReadToken( &token );
353 FXAction.data = token;
354 FXAction.type = FX_PARTICLE;
357 renderModelManager->FindModel( FXAction.data );
361 if ( !token.Icmp( "decal" ) ) {
362 src.ReadToken( &token );
363 FXAction.data = token;
364 FXAction.type = FX_DECAL;
367 declManager->FindMaterial( FXAction.data );
371 if ( !token.Icmp( "particleTrackVelocity" ) ) {
372 FXAction.particleTrackVelocity = true;
376 if ( !token.Icmp( "sound" ) ) {
377 src.ReadToken( &token );
378 FXAction.data = token;
379 FXAction.type = FX_SOUND;
382 declManager->FindSound( FXAction.data );
386 if ( !token.Icmp( "ignoreMaster" ) ) {
387 FXAction.shakeIgnoreMaster = true;
391 if ( !token.Icmp( "shockwave" ) ) {
392 src.ReadToken( &token );
393 FXAction.data = token;
394 FXAction.type = FX_SHOCKWAVE;
396 // precache the entity def
397 declManager->FindType( DECL_ENTITYDEF, FXAction.data );
401 src.Warning( "FX File: bad token" );
411 bool idDeclFX::Parse( const char *text, const int textLength ) {
415 src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
416 src.SetFlags( DECL_LEXER_FLAGS );
417 src.SkipUntilString( "{" );
419 // scan through, identifying each individual parameter
422 if ( !src.ReadToken( &token ) ) {
426 if ( token == "}" ) {
430 if ( !token.Icmp( "bindto" ) ) {
431 src.ReadToken( &token );
436 if ( !token.Icmp( "{" ) ) {
437 idFXSingleAction action;
438 ParseSingleFXAction( src, action );
439 events.Append( action );
444 if ( src.HadError() ) {
445 src.Warning( "FX decl '%s' had a parse error", GetName() );
453 idDeclFX::DefaultDefinition
456 const char *idDeclFX::DefaultDefinition( void ) const {
460 "\t\t" "duration\t5\n"
461 "\t\t" "model\t\t_default\n"
471 void idDeclFX::FreeData( void ) {