afxEffectVector.cpp
Engine/source/afx/afxEffectVector.cpp
Detailed Description
1 2 3//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 4// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames 5// Copyright (C) 2015 Faust Logic, Inc. 6// 7// Permission is hereby granted, free of charge, to any person obtaining a copy 8// of this software and associated documentation files (the "Software"), to 9// deal in the Software without restriction, including without limitation the 10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11// sell copies of the Software, and to permit persons to whom the Software is 12// furnished to do so, subject to the following conditions: 13// 14// The above copyright notice and this permission notice shall be included in 15// all copies or substantial portions of the Software. 16// 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23// IN THE SOFTWARE. 24// 25//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 26 27#include "afx/arcaneFX.h" 28 29#include "afxChoreographer.h" 30#include "afxEffectVector.h" 31#include "afxConstraint.h" 32#include "afxEffectWrapper.h" 33#include "afxEffectGroup.h" 34 35//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 36 37void afxEffectVector::filter_client_server() 38{ 39 if (empty()) 40 return; 41 42 for (S32 i = 0; i < mFX_v->size(); i++) 43 { 44 if ((*mFX_v)[i]->mDatablock->runsHere(mOn_server)) 45 mFX_v2->push_back((*mFX_v)[i]); 46 else 47 { 48 delete (*mFX_v)[i]; 49 (*mFX_v)[i] = 0; 50 } 51 } 52 53 swap_vecs(); 54 55 mFX_v2->clear(); 56} 57 58void afxEffectVector::calc_fx_dur_and_afterlife() 59{ 60 mTotal_fx_dur = 0.0f; 61 mAfter_life = 0.0f; 62 63 if (empty()) 64 return; 65 66 for (S32 i = 0; i < mFX_v->size(); i++) 67 { 68 afxEffectWrapper* ew = (*mFX_v)[i]; 69 if (ew) 70 { 71 F32 ew_dur; 72 if (ew->mEW_timing.lifetime < 0) 73 { 74 if (mPhrase_dur > ew->mEW_timing.delay) 75 ew_dur = mPhrase_dur + ew->afterStopTime(); 76 else 77 ew_dur = ew->mEW_timing.delay + ew->afterStopTime(); 78 } 79 else 80 ew_dur = ew->mEW_timing.delay + ew->mEW_timing.lifetime + ew->mEW_timing.fade_out_time; 81 82 if (ew_dur > mTotal_fx_dur) 83 mTotal_fx_dur = ew_dur; 84 85 F32 after = ew->afterStopTime(); 86 if (after > mAfter_life) 87 mAfter_life = after; 88 } 89 } 90} 91 92//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// 93 94afxEffectVector::afxEffectVector() 95{ 96 mFX_v = 0; 97 mFX_v2 = 0; 98 mActive = false; 99 mOn_server = false; 100 mTotal_fx_dur = 0; 101 mAfter_life = 0; 102 mPhrase_dur = 0; 103} 104 105afxEffectVector::~afxEffectVector() 106{ 107 stop(true); 108 delete mFX_v; 109 delete mFX_v2; 110} 111 112void afxEffectVector::effects_init(afxChoreographer* chor, afxEffectList& effects, bool will_stop, F32 time_factor, 113 S32 group_index, const afxGroupTimingData* group_timing) 114{ 115 afxConstraintMgr* cons_mgr = chor->getConstraintMgr(); 116 117 for (S32 i = 0; i < effects.size(); i++) 118 { 119 if (dynamic_cast<afxEffectGroupData*>(effects[i])) 120 { 121 afxEffectGroupData* eg = (afxEffectGroupData*)effects[i]; 122 if (eg->getSubstitutionCount() > 0) 123 { 124 // clone the datablock and perform substitutions 125 afxEffectGroupData* orig_db = eg; 126 eg = new afxEffectGroupData(*orig_db, true); 127 orig_db->performSubstitutions(eg, chor, group_index); 128 } 129 130 if (eg->group_enabled) 131 { 132 if (eg->assign_idx) 133 { 134 for (S32 j = 0; j < eg->group_count; j++) 135 effects_init(chor, eg->fx_list, will_stop, time_factor, j+eg->idx_offset, &eg->timing); 136 } 137 else 138 { 139 for (S32 j = 0; j < eg->group_count; j++) 140 effects_init(chor, eg->fx_list, will_stop, time_factor, group_index, &eg->timing); 141 } 142 } 143 144 if (eg->isTempClone()) 145 delete eg; 146 } 147 else if (dynamic_cast<afxEffectWrapperData*>(effects[i])) 148 { 149 afxEffectWrapperData* ewd = (afxEffectWrapperData*)effects[i]; 150 151 if (ewd->getSubstitutionCount() > 0) 152 { 153 // clone the ewd and perform substitutions 154 afxEffectWrapperData* orig_db = ewd; 155 ewd = new afxEffectWrapperData(*orig_db, true); 156 orig_db->performSubstitutions(ewd, chor, group_index); 157 } 158 159 if (ewd->effect_enabled) 160 { 161 static afxEffectTimingData inherited_timing; 162 bool use_inherited_timing = false; 163 if (ewd->inherit_timing != 0) 164 { 165 if (group_timing) 166 { 167 inherited_timing = ewd->ewd_timing; 168 if ((ewd->inherit_timing & afxEffectDefs::TIMING_DELAY) != 0) 169 inherited_timing.delay = group_timing->delay; 170 if ((ewd->inherit_timing & afxEffectDefs::TIMING_LIFETIME) != 0) 171 inherited_timing.lifetime = group_timing->lifetime; 172 if ((ewd->inherit_timing & afxEffectDefs::TIMING_FADE_IN) != 0) 173 inherited_timing.fade_in_time = group_timing->fade_in_time; 174 if ((ewd->inherit_timing & afxEffectDefs::TIMING_FADE_OUT) != 0) 175 inherited_timing.fade_out_time = group_timing->fade_out_time; 176 } 177 else 178 { 179 Con::warnf("afxEffectVector::effects_init() -- %s::inheritGroupTiming is non-zero but wrapper is not in a group."); 180 } 181 } 182 183 const afxEffectTimingData& timing = (use_inherited_timing) ? inherited_timing : ewd->ewd_timing; 184 185 if ( (will_stop || !ewd->requiresStop(timing)) && 186 (chor->testRanking(ewd->ranking_range.low, ewd->ranking_range.high)) && 187 (chor->testLevelOfDetail(ewd->lod_range.low, ewd->lod_range.high)) && 188 (ewd->testExecConditions(chor->getExecConditions())) 189 ) 190 { 191 afxEffectWrapper* effect; 192 effect = afxEffectWrapper::ew_create(chor, ewd, cons_mgr, time_factor, group_index); 193 if (effect) 194 mFX_v->push_back(effect); 195 } 196 } 197 else 198 { 199 if (ewd->isTempClone()) 200 delete ewd; 201 } 202 203 } 204 } 205} 206 207void afxEffectVector::ev_init(afxChoreographer* chor, afxEffectList& effects, bool on_server, 208 bool will_stop, F32 time_factor, F32 phrase_dur, S32 group_index) 209{ 210 mOn_server = on_server; 211 mPhrase_dur = phrase_dur; 212 213 mFX_v = new Vector<afxEffectWrapper*>; 214 215 effects_init(chor, effects, will_stop, time_factor, group_index); 216 217 mFX_v2 = new Vector<afxEffectWrapper*>(mFX_v->size()); 218} 219 220void afxEffectVector::start(F32 timestamp) 221{ 222 if (empty()) 223 return; 224 225 // At this point both client and server effects are in the list. 226 // Timing adjustments are made during prestart(). 227 for (S32 i = 0; i < mFX_v->size(); i++) 228 (*mFX_v)[i]->prestart(); 229 230 // duration and afterlife values are pre-calculated here 231 calc_fx_dur_and_afterlife(); 232 233 // now we filter out client-only or server-only effects that 234 // don't belong here, 235 filter_client_server(); 236 237 mActive = true; 238 239 for (S32 j = 0; j < mFX_v->size(); j++) 240 { 241 if ((*mFX_v)[j]->start(timestamp)) 242 mFX_v2->push_back((*mFX_v)[j]); 243 else 244 { 245 delete (*mFX_v)[j]; 246 (*mFX_v)[j] = 0; 247 } 248 } 249 250 swap_vecs(); 251 mFX_v2->clear(); 252} 253 254void afxEffectVector::update(F32 dt) 255{ 256 if (empty()) 257 { 258 mActive = false; 259 return; 260 } 261 262 for (int i = 0; i < mFX_v->size(); i++) 263 { 264 (*mFX_v)[i]->update(dt); 265 266 if ((*mFX_v)[i]->isDone() || (*mFX_v)[i]->isAborted()) 267 { 268 // effect has ended, cleanup and delete 269 (*mFX_v)[i]->cleanup(); 270 delete (*mFX_v)[i]; 271 (*mFX_v)[i] = 0; 272 } 273 else 274 { 275 // effect is still going, so keep it around 276 mFX_v2->push_back((*mFX_v)[i]); 277 } 278 } 279 280 swap_vecs(); 281 282 mFX_v2->clear(); 283 284 if (empty()) 285 { 286 mActive = false; 287 delete mFX_v; mFX_v =0; 288 delete mFX_v2; mFX_v2 = 0; 289 } 290} 291 292void afxEffectVector::stop(bool force_cleanup) 293{ 294 if (empty()) 295 { 296 mActive = false; 297 return; 298 } 299 300 for (int i = 0; i < mFX_v->size(); i++) 301 { 302 (*mFX_v)[i]->stop(); 303 304 if (force_cleanup || (*mFX_v)[i]->deleteWhenStopped()) 305 { 306 // effect is over when stopped, cleanup and delete 307 (*mFX_v)[i]->cleanup(); 308 delete (*mFX_v)[i]; 309 (*mFX_v)[i] = 0; 310 } 311 else 312 { 313 // effect needs to fadeout or something, so keep it around 314 mFX_v2->push_back((*mFX_v)[i]); 315 } 316 } 317 318 swap_vecs(); 319 320 mFX_v2->clear(); 321 322 if (empty()) 323 { 324 mActive = false; 325 delete mFX_v; mFX_v =0; 326 delete mFX_v2; mFX_v2 = 0; 327 } 328} 329 330void afxEffectVector::interrupt() 331{ 332 if (empty()) 333 { 334 mActive = false; 335 return; 336 } 337 338 for (int i = 0; i < mFX_v->size(); i++) 339 { 340 (*mFX_v)[i]->stop(); 341 (*mFX_v)[i]->cleanup(); 342 delete (*mFX_v)[i]; 343 (*mFX_v)[i] = 0; 344 } 345 346 swap_vecs(); 347 348 mFX_v2->clear(); 349 350 if (empty()) 351 { 352 mActive = false; 353 delete mFX_v; mFX_v =0; 354 delete mFX_v2; mFX_v2 = 0; 355 } 356} 357 358//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 359 360 361