afxEffectWrapper.cpp
Engine/source/afx/afxEffectWrapper.cpp
Public Functions
ConsoleDocClass(afxEffectBaseData , "@brief A datablock baseclass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData.\n\n</a>" "Not intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used directly, <a href="/coding/class/classafxeffectbasedata/">afxEffectBaseData</a> exists <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> provide base member " "variables and generic functionality <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the derived classes <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> and " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectWrapperData\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
ConsoleDocClass(afxEffectWrapper , "@brief An Effect Wrapper as defined by an <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock.\n\n</a>" "Conceptually an effect wrapper encloses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> building-block effect and acts " "as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> adding the effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> choreographer. Effect wrapper fields " "primarily deal with effect timing, constraints , and conditional effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">execution.\n\n</a>" "Not intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used directly, <a href="/coding/class/classafxeffectwrapper/">afxEffectWrapper</a> is an internal baseclass used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "implement effect-specific adapter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxEffectWrapperData , "@brief A datablock that describes an Effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Wrapper.\n\n</a>" "Conceptually an effect wrapper encloses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> building-block effect and acts " "as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> adding the effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> choreographer. Effect wrapper fields " "primarily deal with effect timing, constraints , and conditional effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">execution.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectBaseData\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
num_modifiers(afxXM_BaseData * mods)
Detailed Description
Public Defines
myOffset(field) (field, )
myOffset(field) (field, )
Public Functions
ConsoleDocClass(afxEffectBaseData , "@brief A datablock baseclass <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData.\n\n</a>" "Not intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used directly, <a href="/coding/class/classafxeffectbasedata/">afxEffectBaseData</a> exists <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> provide base member " "variables and generic functionality <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the derived classes <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> and " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectWrapperData\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
ConsoleDocClass(afxEffectWrapper , "@brief An Effect Wrapper as defined by an <a href="/coding/class/classafxeffectwrapperdata/">afxEffectWrapperData</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock.\n\n</a>" "Conceptually an effect wrapper encloses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> building-block effect and acts " "as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> adding the effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> choreographer. Effect wrapper fields " "primarily deal with effect timing, constraints , and conditional effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">execution.\n\n</a>" "Not intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used directly, <a href="/coding/class/classafxeffectwrapper/">afxEffectWrapper</a> is an internal baseclass used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "implement effect-specific adapter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">classes.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxEffectWrapperData , "@brief A datablock that describes an Effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Wrapper.\n\n</a>" "Conceptually an effect wrapper encloses <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> building-block effect and acts " "as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> handle <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> adding the effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> choreographer. Effect wrapper fields " "primarily deal with effect timing, constraints , and conditional effect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">execution.\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectBaseData\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffectGroupData\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxEffects\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
IMPLEMENT_CO_DATABLOCK_V1(afxEffectBaseData )
IMPLEMENT_CO_DATABLOCK_V1(afxEffectWrapperData )
IMPLEMENT_CONOBJECT(afxEffectWrapper )
num_modifiers(afxXM_BaseData * mods)
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 "math/mathIO.h" 30 31#include "afx/ce/afxComponentEffect.h" 32#include "afx/afxResidueMgr.h" 33#include "afx/afxChoreographer.h" 34#include "afx/afxConstraint.h" 35#include "afx/xm/afxXfmMod.h" 36#include "afx/afxEffectWrapper.h" 37#include "afx/util/afxAnimCurve.h" 38#include "afx/util/afxEase.h" 39 40//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 41// afxEffectWrapperData 42 43IMPLEMENT_CO_DATABLOCK_V1(afxEffectBaseData); 44 45ConsoleDocClass( afxEffectBaseData, 46 "@brief A datablock baseclass for afxEffectWrapperData and afxEffectGroupData.\n\n" 47 48 "Not intended to be used directly, afxEffectBaseData exists to provide base member " 49 "variables and generic functionality for the derived classes afxEffectWrapperData and " 50 "afxEffectGroupData.\n\n" 51 52 "@see afxEffectWrapperData\n\n" 53 "@see afxEffectGroupData\n\n" 54 55 "@ingroup afxEffects\n" 56 "@ingroup AFX\n" 57 "@ingroup Datablocks\n" 58); 59 60IMPLEMENT_CO_DATABLOCK_V1(afxEffectWrapperData); 61 62ConsoleDocClass( afxEffectWrapperData, 63 "@brief A datablock that describes an Effect Wrapper.\n\n" 64 65 "Conceptually an effect wrapper encloses a building-block effect and acts " 66 "as a handle for adding the effect to a choreographer. Effect wrapper fields " 67 "primarily deal with effect timing, constraints, and conditional effect execution.\n\n" 68 69 "@see afxEffectBaseData\n\n" 70 "@see afxEffectGroupData\n\n" 71 72 "@ingroup afxEffects\n" 73 "@ingroup AFX\n" 74 "@ingroup Datablocks\n" 75); 76 77afxEffectWrapperData::afxEffectWrapperData() 78{ 79 effect_name = ST_NULLSTRING; 80 effect_data = 0; 81 effect_desc = 0; 82 data_ID = 0; 83 use_as_cons_obj = false; 84 use_ghost_as_cons_obj = false; 85 86 // constraint data 87 cons_spec = ST_NULLSTRING; 88 pos_cons_spec = ST_NULLSTRING; 89 orient_cons_spec = ST_NULLSTRING; 90 aim_cons_spec = StringTable->insert("camera"); 91 life_cons_spec = ST_NULLSTRING; 92 93 // conditional execution flags 94 effect_enabled = true; 95 ranking_range.set(0,255); 96 lod_range.set(0,255); 97 life_conds = 0; 98 for (S32 i = 0; i < MAX_CONDITION_STATES; i++) 99 { 100 exec_cond_on_bits[i] = 0; 101 exec_cond_off_bits[i] = 0; 102 exec_cond_bitmasks[i] = 0; 103 } 104 105 ewd_timing.lifetime = -1; 106 107 user_fade_out_time = 0.0; 108 109 is_looping = false; 110 n_loops = 0; 111 loop_gap_time = 0.0f; 112 113 ignore_time_factor = false; 114 propagate_time_factor = false; 115 116 // residue settings 117 118 // scaling factors 119 rate_factor = 1.0f; 120 scale_factor = 1.0f; 121 122 dMemset(xfm_modifiers, 0, sizeof(xfm_modifiers)); 123 124 forced_bbox.minExtents.set(1,1,1); 125 forced_bbox.maxExtents.set(-1,-1,-1); 126 127 update_forced_bbox = false; 128 129 // marked true if datablock ids need to 130 // be converted into pointers 131 do_id_convert = false; 132 133 sort_priority = 0; 134 direction.set(0,1,0); 135 speed = 0.0f; 136 mass = 1.0f; 137 138 borrow_altitudes = false; 139 vis_keys_spec = ST_NULLSTRING; 140 vis_keys = 0; 141 142 group_index = -1; 143 inherit_timing = 0; 144} 145 146afxEffectWrapperData::afxEffectWrapperData(const afxEffectWrapperData& other, bool temp_clone) : afxEffectBaseData(other, temp_clone) 147{ 148 effect_name = other.effect_name; 149 effect_data = other.effect_data; 150 effect_desc = other.effect_desc; 151 data_ID = other.data_ID; 152 use_as_cons_obj = other.use_as_cons_obj; 153 use_ghost_as_cons_obj = other.use_ghost_as_cons_obj; 154 cons_spec = other.cons_spec; 155 pos_cons_spec = other.pos_cons_spec; 156 orient_cons_spec = other.orient_cons_spec; 157 aim_cons_spec = other.aim_cons_spec; 158 life_cons_spec = other.life_cons_spec; 159 cons_def = other.cons_def; 160 pos_cons_def = other.pos_cons_def; 161 orient_cons_def = other.orient_cons_def; 162 aim_cons_def = other.aim_cons_def; 163 life_cons_def = other.life_cons_def; 164 effect_enabled = other.effect_enabled; 165 ranking_range = other.ranking_range; 166 lod_range = other.lod_range; 167 life_conds = other.life_conds; 168 dMemcpy(exec_cond_on_bits, other.exec_cond_on_bits, sizeof(exec_cond_on_bits)); 169 dMemcpy(exec_cond_off_bits, other.exec_cond_off_bits, sizeof(exec_cond_off_bits)); 170 dMemcpy(exec_cond_bitmasks, other.exec_cond_bitmasks, sizeof(exec_cond_bitmasks)); 171 ewd_timing = other.ewd_timing; 172 user_fade_out_time = other.user_fade_out_time; 173 is_looping = other.is_looping; 174 n_loops = other.n_loops; 175 loop_gap_time = other.loop_gap_time; 176 ignore_time_factor = other.ignore_time_factor; 177 propagate_time_factor = other.propagate_time_factor; 178 rate_factor = other.rate_factor; 179 scale_factor = other.scale_factor; 180 dMemcpy(xfm_modifiers, other.xfm_modifiers, sizeof(xfm_modifiers)); 181 forced_bbox = other.forced_bbox; 182 update_forced_bbox = other.update_forced_bbox; 183 do_id_convert = other.do_id_convert; 184 sort_priority = other.sort_priority; 185 direction = other.direction; 186 speed = other.speed; 187 mass = other.mass; 188 borrow_altitudes = other.borrow_altitudes; 189 vis_keys_spec = other.vis_keys_spec; 190 vis_keys = other.vis_keys; 191 if (other.vis_keys) 192 { 193 vis_keys = new afxAnimCurve(); 194 for (S32 i = 0; i < other.vis_keys->numKeys(); i++) 195 { 196 F32 when = other.vis_keys->getKeyTime(i); 197 F32 what = other.vis_keys->getKeyValue(i); 198 vis_keys->addKey(when, what); 199 } 200 } 201 else 202 vis_keys = 0; 203 group_index = other.group_index; 204 inherit_timing = other.inherit_timing; 205} 206 207afxEffectWrapperData::~afxEffectWrapperData() 208{ 209 if (vis_keys) 210 delete vis_keys; 211} 212 213#define myOffset(field) Offset(field, afxEffectWrapperData) 214 215void afxEffectWrapperData::initPersistFields() 216{ 217 // the wrapped effect 218 addField("effect", TYPEID<SimDataBlock>(), myOffset(effect_data), 219 "..."); 220 addField("effectName", TypeString, myOffset(effect_name), 221 "..."); 222 223 // constraints 224 addField("constraint", TypeString, myOffset(cons_spec), 225 "..."); 226 addField("posConstraint", TypeString, myOffset(pos_cons_spec), 227 "..."); 228 addField("posConstraint2", TypeString, myOffset(aim_cons_spec), 229 "..."); 230 addField("orientConstraint", TypeString, myOffset(orient_cons_spec), 231 "..."); 232 addField("lifeConstraint", TypeString, myOffset(life_cons_spec), 233 "..."); 234 // 235 addField("isConstraintSrc", TypeBool, myOffset(use_as_cons_obj), 236 "..."); 237 addField("ghostIsConstraintSrc", TypeBool, myOffset(use_ghost_as_cons_obj), 238 "..."); 239 240 addField("delay", TypeF32, myOffset(ewd_timing.delay), 241 "..."); 242 addField("lifetime", TypeF32, myOffset(ewd_timing.lifetime), 243 "..."); 244 addField("fadeInTime", TypeF32, myOffset(ewd_timing.fade_in_time), 245 "..."); 246 addField("residueLifetime", TypeF32, myOffset(ewd_timing.residue_lifetime), 247 "..."); 248 addField("fadeInEase", TypePoint2F, myOffset(ewd_timing.fadein_ease), 249 "..."); 250 addField("fadeOutEase", TypePoint2F, myOffset(ewd_timing.fadeout_ease), 251 "..."); 252 addField("lifetimeBias", TypeF32, myOffset(ewd_timing.life_bias), 253 "..."); 254 addField("fadeOutTime", TypeF32, myOffset(user_fade_out_time), 255 "..."); 256 257 addField("rateFactor", TypeF32, myOffset(rate_factor), 258 "..."); 259 addField("scaleFactor", TypeF32, myOffset(scale_factor), 260 "..."); 261 262 addField("isLooping", TypeBool, myOffset(is_looping), 263 "..."); 264 addField("loopCount", TypeS32, myOffset(n_loops), 265 "..."); 266 addField("loopGapTime", TypeF32, myOffset(loop_gap_time), 267 "..."); 268 269 addField("ignoreTimeFactor", TypeBool, myOffset(ignore_time_factor), 270 "..."); 271 addField("propagateTimeFactor", TypeBool, myOffset(propagate_time_factor), 272 "..."); 273 274 addField("effectEnabled", TypeBool, myOffset(effect_enabled), 275 "..."); 276 addField("rankingRange", TypeByteRange, myOffset(ranking_range), 277 "..."); 278 addField("levelOfDetailRange", TypeByteRange, myOffset(lod_range), 279 "..."); 280 addField("lifeConditions", TypeS32, myOffset(life_conds), 281 "..."); 282 addField("execConditions", TypeS32, myOffset(exec_cond_on_bits), MAX_CONDITION_STATES, 283 "..."); 284 addField("execOffConditions", TypeS32, myOffset(exec_cond_off_bits), MAX_CONDITION_STATES, 285 "..."); 286 287 addField("xfmModifiers", TYPEID<afxXM_BaseData>(), myOffset(xfm_modifiers), MAX_XFM_MODIFIERS, 288 "..."); 289 290 addField("forcedBBox", TypeBox3F, myOffset(forced_bbox), 291 "..."); 292 addField("updateForcedBBox", TypeBool, myOffset(update_forced_bbox), 293 "..."); 294 295 addField("sortPriority", TypeS8, myOffset(sort_priority), 296 "..."); 297 addField("direction", TypePoint3F, myOffset(direction), 298 "..."); 299 addField("speed", TypeF32, myOffset(speed), 300 "..."); 301 addField("mass", TypeF32, myOffset(mass), 302 "..."); 303 304 addField("borrowAltitudes", TypeBool, myOffset(borrow_altitudes), 305 "..."); 306 addField("visibilityKeys", TypeString, myOffset(vis_keys_spec), 307 "..."); 308 309 addField("groupIndex", TypeS32, myOffset(group_index), 310 "..."); 311 addField("inheritGroupTiming", TypeS32, myOffset(inherit_timing), 312 "..."); 313 314 Parent::initPersistFields(); 315 316 // disallow some field substitutions 317 disableFieldSubstitutions("effect"); 318 onlyKeepClearSubstitutions("xfmModifiers"); // subs resolving to "~~", or "~0" are OK 319 320 // Conditional Execution Flags 321 Con::setIntVariable("$afx::DISABLED", DISABLED); 322 Con::setIntVariable("$afx::ENABLED", ENABLED); 323 Con::setIntVariable("$afx::FAILING", FAILING); 324 Con::setIntVariable("$afx::DEAD", DEAD); 325 Con::setIntVariable("$afx::ALIVE", ALIVE); 326 Con::setIntVariable("$afx::DYING", DYING); 327} 328 329bool afxEffectWrapperData::onAdd() 330{ 331 if (Parent::onAdd() == false) 332 return false; 333 334 if (!effect_data) 335 { 336 if (!Sim::findObject((SimObjectId)data_ID, effect_data)) 337 { 338 Con::errorf("afxEffectWrapperData::onAdd() -- bad datablockId: 0x%x", data_ID); 339 return false; 340 } 341 } 342 343 if (effect_data) 344 { 345 if (!afxEffectAdapterDesc::identifyEffect(this)) 346 { 347 Con::errorf("afxEffectWrapperData::onAdd() -- unknown effect type."); 348 return false; 349 } 350 } 351 352 parse_cons_specs(); 353 parse_vis_keys(); 354 355 // figure out if fade-out is for effect of residue 356 if (ewd_timing.residue_lifetime > 0) 357 { 358 ewd_timing.residue_fadetime = user_fade_out_time; 359 ewd_timing.fade_out_time = 0.0f; 360 } 361 else 362 { 363 ewd_timing.residue_fadetime = 0.0f; 364 ewd_timing.fade_out_time = user_fade_out_time; 365 } 366 367 // adjust fade-in time 368 if (ewd_timing.lifetime >= 0) 369 { 370 ewd_timing.fade_in_time = getMin(ewd_timing.lifetime, ewd_timing.fade_in_time); 371 } 372 373 // adjust exec-conditions 374 for (S32 i = 0; i < MAX_CONDITION_STATES; i++) 375 exec_cond_bitmasks[i] = exec_cond_on_bits[i] | exec_cond_off_bits[i]; 376 377 return true; 378} 379 380void afxEffectWrapperData::packData(BitStream* stream) 381{ 382 Parent::packData(stream); 383 384 writeDatablockID(stream, effect_data, mPacked); 385 386 stream->writeString(effect_name); 387 388 stream->writeString(cons_spec); 389 stream->writeString(pos_cons_spec); 390 stream->writeString(orient_cons_spec); 391 stream->writeString(aim_cons_spec); 392 stream->writeString(life_cons_spec); 393 // 394 stream->write(use_as_cons_obj); 395 //stream->write(use_ghost_as_cons_obj); 396 397 stream->writeFlag(effect_enabled); 398 stream->write(ranking_range.low); 399 stream->write(ranking_range.high); 400 stream->write(lod_range.low); 401 stream->write(lod_range.high); 402 403 for (S32 i = 0; i < MAX_CONDITION_STATES; i++) 404 { 405 stream->write(exec_cond_on_bits[i]); 406 stream->write(exec_cond_off_bits[i]); 407 } 408 stream->write(life_conds); 409 stream->write(ewd_timing.delay); 410 stream->write(ewd_timing.lifetime); 411 stream->write(ewd_timing.fade_in_time); 412 stream->write(user_fade_out_time); 413 stream->write(is_looping); 414 stream->write(n_loops); 415 stream->write(loop_gap_time); 416 stream->write(ignore_time_factor); 417 stream->write(propagate_time_factor); 418 stream->write(ewd_timing.residue_lifetime); 419 stream->write(rate_factor); 420 stream->write(scale_factor); 421 422 // modifiers 423 pack_mods(stream, xfm_modifiers, mPacked); 424 425 mathWrite(*stream, forced_bbox); 426 stream->write(update_forced_bbox); 427 428 stream->write(sort_priority); 429 mathWrite(*stream, direction); 430 stream->write(speed); 431 stream->write(mass); 432 433 stream->write(borrow_altitudes); 434 if (stream->writeFlag(vis_keys_spec != ST_NULLSTRING)) 435 stream->writeLongString(1023, vis_keys_spec); 436 437 if (stream->writeFlag(group_index != -1)) 438 stream->write(group_index); 439 440 stream->writeInt(inherit_timing, TIMING_BITS); 441} 442 443void afxEffectWrapperData::unpackData(BitStream* stream) 444{ 445 Parent::unpackData(stream); 446 447 data_ID = readDatablockID(stream); 448 449 effect_name = stream->readSTString(); 450 451 cons_spec = stream->readSTString(); 452 pos_cons_spec = stream->readSTString(); 453 orient_cons_spec = stream->readSTString(); 454 aim_cons_spec = stream->readSTString(); 455 life_cons_spec = stream->readSTString(); 456 // 457 stream->read(&use_as_cons_obj); 458 //stream->read(&use_ghost_as_cons_obj); 459 460 effect_enabled = stream->readFlag(); 461 stream->read(&ranking_range.low); 462 stream->read(&ranking_range.high); 463 stream->read(&lod_range.low); 464 stream->read(&lod_range.high); 465 466 for (S32 i = 0; i < MAX_CONDITION_STATES; i++) 467 { 468 stream->read(&exec_cond_on_bits[i]); 469 stream->read(&exec_cond_off_bits[i]); 470 } 471 stream->read(&life_conds); 472 stream->read(&ewd_timing.delay); 473 stream->read(&ewd_timing.lifetime); 474 stream->read(&ewd_timing.fade_in_time); 475 stream->read(&user_fade_out_time); 476 stream->read(&is_looping); 477 stream->read(&n_loops); 478 stream->read(&loop_gap_time); 479 stream->read(&ignore_time_factor); 480 stream->read(&propagate_time_factor); 481 stream->read(&ewd_timing.residue_lifetime); 482 stream->read(&rate_factor); 483 stream->read(&scale_factor); 484 485 // modifiers 486 do_id_convert = true; 487 unpack_mods(stream, xfm_modifiers); 488 489 mathRead(*stream, &forced_bbox); 490 stream->read(&update_forced_bbox); 491 492 stream->read(&sort_priority); 493 mathRead(*stream, &direction); 494 stream->read(&speed); 495 stream->read(&mass); 496 497 stream->read(&borrow_altitudes); 498 if (stream->readFlag()) 499 { 500 char buf[1024]; 501 stream->readLongString(1023, buf); 502 vis_keys_spec = StringTable->insert(buf); 503 } 504 else 505 vis_keys_spec = ST_NULLSTRING; 506 507 if (stream->readFlag()) 508 stream->read(&group_index); 509 else 510 group_index = -1; 511 512 inherit_timing = stream->readInt(TIMING_BITS); 513} 514 515/* static*/ 516S32 num_modifiers(afxXM_BaseData* mods[]) 517{ 518 S32 n_mods = 0; 519 for (int i = 0; i < afxEffectDefs::MAX_XFM_MODIFIERS; i++) 520 { 521 if (mods[i]) 522 { 523 if (i != n_mods) 524 { 525 mods[n_mods] = mods[i]; 526 mods[i] = 0; 527 } 528 n_mods++; 529 } 530 } 531 532 return n_mods; 533} 534 535void afxEffectWrapperData::parse_cons_specs() 536{ 537 // parse the constraint specifications 538 bool runs_on_s = runsOnServer(); 539 bool runs_on_c = runsOnClient(); 540 cons_def.parseSpec(cons_spec, runs_on_s, runs_on_c); 541 pos_cons_def.parseSpec(pos_cons_spec, runs_on_s, runs_on_c); 542 orient_cons_def.parseSpec(orient_cons_spec, runs_on_s, runs_on_c); 543 aim_cons_def.parseSpec(aim_cons_spec, runs_on_s, runs_on_c); 544 life_cons_def.parseSpec(life_cons_spec, runs_on_s, runs_on_c); 545 if (cons_def.isDefined()) 546 { 547 pos_cons_def = cons_def; 548 if (!orient_cons_def.isDefined()) 549 orient_cons_def = cons_def; 550 } 551} 552 553void afxEffectWrapperData::parse_vis_keys() 554{ 555 if (vis_keys_spec != ST_NULLSTRING) 556 { 557 if (vis_keys) 558 delete vis_keys; 559 vis_keys = new afxAnimCurve(); 560 561 char* keys_buffer = dStrdup(vis_keys_spec); 562 563 char* key_token = dStrtok(keys_buffer, " \t"); 564 while (key_token != NULL) 565 { 566 char* colon = dStrchr(key_token, ':'); 567 if (colon) 568 { 569 *colon = '\0'; 570 571 F32 when = dAtof(key_token); 572 F32 what = dAtof(colon+1); 573 574 vis_keys->addKey(when, what); 575 } 576 key_token = dStrtok(NULL, " \t"); 577 } 578 579 dFree(keys_buffer); 580 vis_keys->sort(); 581 } 582} 583 584void afxEffectWrapperData::gather_cons_defs(Vector<afxConstraintDef>& defs) 585{ 586 if (pos_cons_def.isDefined()) 587 defs.push_back(pos_cons_def); 588 if (orient_cons_def.isDefined()) 589 defs.push_back(orient_cons_def); 590 if (aim_cons_def.isDefined()) 591 defs.push_back(aim_cons_def); 592 if (life_cons_def.isDefined()) 593 defs.push_back(life_cons_def); 594 595 afxComponentEffectData* ce_data = dynamic_cast<afxComponentEffectData*>(effect_data); 596 if (ce_data) 597 ce_data->gather_cons_defs(defs); 598} 599 600void afxEffectWrapperData::pack_mods(BitStream* stream, afxXM_BaseData* mods[], bool packed) 601{ 602 S32 n_mods = num_modifiers(mods); 603 stream->writeInt(n_mods, 6); 604 for (int i = 0; i < n_mods; i++) 605 writeDatablockID(stream, mods[i], packed); 606} 607 608void afxEffectWrapperData::unpack_mods(BitStream* stream, afxXM_BaseData* mods[]) 609{ 610 S32 n_mods = stream->readInt(6); 611 for (int i = 0; i < n_mods; i++) 612 mods[i] = (afxXM_BaseData*)(uintptr_t)readDatablockID(stream); 613} 614 615bool afxEffectWrapperData::preload(bool server, String &errorStr) 616{ 617 if (!Parent::preload(server, errorStr)) 618 return false; 619 620 // Resolve objects transmitted from server 621 if (!server) 622 { 623 if (do_id_convert) 624 { 625 for (int i = 0; i < MAX_XFM_MODIFIERS; i++) 626 { 627 SimObjectId db_id = SimObjectId((uintptr_t)xfm_modifiers[i]); 628 if (db_id != 0) 629 { 630 // try to convert id to pointer 631 if (!Sim::findObject(db_id, xfm_modifiers[i])) 632 { 633 Con::errorf("afxEffectWrapperData::preload() -- bad datablockId: 0x%x (xfm_modifiers[%d])", 634 db_id, i); 635 } 636 } 637 do_id_convert = false; 638 } 639 } 640 } 641 642 return true; 643} 644 645void afxEffectWrapperData::onPerformSubstitutions() 646{ 647 Parent::onPerformSubstitutions(); 648 649 parse_cons_specs(); 650 parse_vis_keys(); 651 652 if (ewd_timing.residue_lifetime > 0) 653 { 654 ewd_timing.residue_fadetime = user_fade_out_time; 655 ewd_timing.fade_out_time = 0.0f; 656 } 657 else 658 { 659 ewd_timing.residue_fadetime = 0.0f; 660 ewd_timing.fade_out_time = user_fade_out_time; 661 } 662} 663 664//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 665// afxEffectWrapper 666 667IMPLEMENT_CONOBJECT(afxEffectWrapper); 668 669ConsoleDocClass( afxEffectWrapper, 670 "@brief An Effect Wrapper as defined by an afxEffectWrapperData datablock.\n\n" 671 672 "Conceptually an effect wrapper encloses a building-block effect and acts " 673 "as a handle for adding the effect to a choreographer. Effect wrapper fields " 674 "primarily deal with effect timing, constraints, and conditional effect execution.\n\n" 675 676 "Not intended to be used directly, afxEffectWrapper is an internal baseclass used to " 677 "implement effect-specific adapter classes.\n\n" 678 679 "@ingroup afxEffects\n" 680 "@ingroup AFX\n" 681); 682 683afxEffectWrapper::afxEffectWrapper() 684{ 685 mChoreographer = 0; 686 mDatablock = 0; 687 mCons_mgr = 0; 688 689 mCond_alive = true; 690 mElapsed = 0; 691 mLife_end = 0; 692 mLife_elapsed = 0; 693 mStopped = false; 694 mNum_updates = 0; 695 mFade_value = 1.0f; 696 mLast_fade_value = 0.0f; 697 mFade_in_end = 0.0; 698 mFade_out_start = 0.0f; 699 mIn_scope = true; 700 mIs_aborted = false; 701 mDo_fade_inout = false; 702 mDo_fades = false; 703 mFull_lifetime = 0; 704 705 mTime_factor = 1.0f; 706 mProp_time_factor = 1.0f; 707 708 mLive_scale_factor = 1.0f; 709 mLive_fade_factor = 1.0f; 710 mTerrain_altitude = -1.0f; 711 mInterior_altitude = -1.0f; 712 713 mGroup_index = 0; 714 715 dMemset(mXfm_modifiers, 0, sizeof(mXfm_modifiers)); 716} 717 718afxEffectWrapper::~afxEffectWrapper() 719{ 720 for (S32 i = 0; i < MAX_XFM_MODIFIERS; i++) 721 if (mXfm_modifiers[i]) 722 delete mXfm_modifiers[i]; 723 724 if (mDatablock && mDatablock->effect_name != ST_NULLSTRING) 725 { 726 mChoreographer->removeNamedEffect(this); 727 if (mDatablock->use_as_cons_obj && !mEffect_cons_id.undefined()) 728 mCons_mgr->setReferenceEffect(mEffect_cons_id, 0); 729 } 730 731 if (mDatablock && mDatablock->isTempClone()) 732 delete mDatablock; 733 mDatablock = 0; 734} 735 736#undef myOffset 737#define myOffset(field) Offset(field, afxEffectWrapper) 738 739void afxEffectWrapper::initPersistFields() 740{ 741 addField("liveScaleFactor", TypeF32, myOffset(mLive_scale_factor), 742 "..."); 743 addField("liveFadeFactor", TypeF32, myOffset(mLive_fade_factor), 744 "..."); 745 746 Parent::initPersistFields(); 747} 748 749void afxEffectWrapper::ew_init(afxChoreographer* choreographer, 750 afxEffectWrapperData* datablock, 751 afxConstraintMgr* cons_mgr, 752 F32 time_factor) 753{ 754 AssertFatal(choreographer != NULL, "Choreographer is missing."); 755 AssertFatal(datablock != NULL, "Datablock is missing."); 756 AssertFatal(cons_mgr != NULL, "Constraint manager is missing."); 757 758 mChoreographer = choreographer; 759 mDatablock = datablock; 760 mCons_mgr = cons_mgr; 761 ea_set_datablock(datablock->effect_data); 762 763 mEW_timing = datablock->ewd_timing; 764 if (mEW_timing.life_bias != 1.0f) 765 { 766 if (mEW_timing.lifetime > 0) 767 mEW_timing.lifetime *= mEW_timing.life_bias; 768 mEW_timing.fade_in_time *= mEW_timing.life_bias; 769 mEW_timing.fade_out_time *= mEW_timing.life_bias; 770 } 771 772 mPos_cons_id = cons_mgr->getConstraintId(datablock->pos_cons_def); 773 mOrient_cons_id = cons_mgr->getConstraintId(datablock->orient_cons_def); 774 mAim_cons_id = cons_mgr->getConstraintId(datablock->aim_cons_def); 775 mLife_cons_id = cons_mgr->getConstraintId(datablock->life_cons_def); 776 777 mTime_factor = (datablock->ignore_time_factor) ? 1.0f : time_factor; 778 779 if (datablock->propagate_time_factor) 780 mProp_time_factor = time_factor; 781 782 if (datablock->runsHere(choreographer->isServerObject())) 783 { 784 for (int i = 0; i < MAX_XFM_MODIFIERS && datablock->xfm_modifiers[i] != 0; i++) 785 { 786 mXfm_modifiers[i] = datablock->xfm_modifiers[i]->create(this, choreographer->isServerObject()); 787 AssertFatal(mXfm_modifiers[i] != 0, avar("Error, creation failed for xfm_modifiers[%d] of %s.", i, datablock->getName())); 788 if (mXfm_modifiers[i] == 0) 789 Con::errorf("Error, creation failed for xfm_modifiers[%d] of %s.", i, datablock->getName()); 790 } 791 } 792 793 if (datablock->effect_name != ST_NULLSTRING) 794 { 795 assignName(datablock->effect_name); 796 choreographer->addNamedEffect(this); 797 if (datablock->use_as_cons_obj) 798 { 799 mEffect_cons_id = cons_mgr->setReferenceEffect(datablock->effect_name, this); 800 if (mEffect_cons_id.undefined() && datablock->isTempClone() && datablock->runsHere(choreographer->isServerObject())) 801 mEffect_cons_id = cons_mgr->createReferenceEffect(datablock->effect_name, this); 802 } 803 } 804} 805 806void afxEffectWrapper::prestart() 807{ 808 // modify timing values by time_factor 809 if (mEW_timing.lifetime > 0) 810 mEW_timing.lifetime *= mTime_factor; 811 mEW_timing.delay *= mTime_factor; 812 mEW_timing.fade_in_time *= mTime_factor; 813 mEW_timing.fade_out_time *= mTime_factor; 814 815 if (mEW_timing.lifetime < 0) 816 { 817 mFull_lifetime = INFINITE_LIFETIME; 818 mLife_end = INFINITE_LIFETIME; 819 } 820 else 821 { 822 mFull_lifetime = mEW_timing.lifetime + mEW_timing.fade_out_time; 823 mLife_end = mEW_timing.delay + mEW_timing.lifetime; 824 } 825 826 if ((mEW_timing.fade_in_time + mEW_timing.fade_out_time) > 0.0f) 827 { 828 mFade_in_end = mEW_timing.delay + mEW_timing.fade_in_time; 829 if (mFull_lifetime == INFINITE_LIFETIME) 830 mFade_out_start = INFINITE_LIFETIME; 831 else 832 mFade_out_start = mEW_timing.delay + mEW_timing.lifetime; 833 mDo_fade_inout = true; 834 } 835 836 if (!mDo_fade_inout && mDatablock->vis_keys != NULL && mDatablock->vis_keys->numKeys() > 0) 837 { 838 //do_fades = true; 839 mFade_out_start = mEW_timing.delay + mEW_timing.lifetime; 840 } 841} 842 843bool afxEffectWrapper::start(F32 timestamp) 844{ 845 if (!ea_is_enabled()) 846 { 847 Con::warnf("afxEffectWrapper::start() -- effect type of %s is currently disabled.", mDatablock->getName()); 848 return false; 849 } 850 851 afxConstraint* life_constraint = getLifeConstraint(); 852 if (life_constraint) 853 mCond_alive = life_constraint->getLivingState(); 854 855 mElapsed = timestamp; 856 857 for (S32 i = 0; i < MAX_XFM_MODIFIERS; i++) 858 { 859 if (!mXfm_modifiers[i]) 860 break; 861 else 862 mXfm_modifiers[i]->start(timestamp); 863 } 864 865 if (!ea_start()) 866 { 867 // subclass should print error message if applicable, so no message here. 868 return false; 869 } 870 871 update(0.0f); 872 return !isAborted(); 873} 874 875bool afxEffectWrapper::test_life_conds() 876{ 877 afxConstraint* life_constraint = getLifeConstraint(); 878 if (!life_constraint || mDatablock->life_conds == 0) 879 return true; 880 881 S32 now_state = life_constraint->getDamageState(); 882 if ((mDatablock->life_conds & DEAD) != 0 && now_state == ShapeBase::Disabled) 883 return true; 884 if ((mDatablock->life_conds & ALIVE) != 0 && now_state == ShapeBase::Enabled) 885 return true; 886 if ((mDatablock->life_conds & DYING) != 0) 887 return (mCond_alive && now_state == ShapeBase::Disabled); 888 889 return false; 890} 891 892bool afxEffectWrapper::update(F32 dt) 893{ 894 mElapsed += dt; 895 896 // life_elapsed won't exceed full_lifetime 897 mLife_elapsed = getMin(mElapsed - mEW_timing.delay, mFull_lifetime); 898 899 // update() returns early if elapsed is outside of active timing range 900 // (delay <= elapsed <= delay+lifetime) 901 // note: execution is always allowed beyond this point at least once, 902 // even if elapsed exceeds the lifetime. 903 if (mElapsed < mEW_timing.delay) 904 { 905 setScopeStatus(false); 906 return false; 907 } 908 909 if (!mDatablock->requiresStop(mEW_timing) && mEW_timing.lifetime < 0) 910 { 911 F32 afterlife = mElapsed - mEW_timing.delay; 912 if (afterlife > 1.0f || ((afterlife > 0.0f) && (mNum_updates > 0))) 913 { 914 setScopeStatus(mEW_timing.residue_lifetime > 0.0f); 915 return false; 916 } 917 } 918 else 919 { 920 F32 afterlife = mElapsed - (mFull_lifetime + mEW_timing.delay); 921 if (afterlife > 1.0f || ((afterlife > 0.0f) && (mNum_updates > 0))) 922 { 923 setScopeStatus(mEW_timing.residue_lifetime > 0.0f); 924 return false; 925 } 926 } 927 928 // first time here, test if required conditions for effect are met 929 if (mNum_updates == 0) 930 { 931 if (!test_life_conds()) 932 { 933 mElapsed = mFull_lifetime + mEW_timing.delay; 934 setScopeStatus(false); 935 mNum_updates++; 936 return false; 937 } 938 } 939 940 setScopeStatus(true); 941 mNum_updates++; 942 943 944 // calculate current fade value if enabled 945 if (mDo_fade_inout) 946 { 947 if (mEW_timing.fade_in_time > 0 && mElapsed <= mFade_in_end) 948 { 949 F32 t = mClampF((mElapsed - mEW_timing.delay)/ mEW_timing.fade_in_time, 0.0f, 1.0f); 950 mFade_value = afxEase::t(t, mEW_timing.fadein_ease.x, mEW_timing.fadein_ease.y); 951 mDo_fades = true; 952 } 953 else if (mElapsed > mFade_out_start) 954 { 955 if (mEW_timing.fade_out_time == 0) 956 mFade_value = 0.0f; 957 else 958 { 959 F32 t = mClampF(1.0f-(mElapsed - mFade_out_start)/ mEW_timing.fade_out_time, 0.0f, 1.0f); 960 mFade_value = afxEase::t(t, mEW_timing.fadeout_ease.x, mEW_timing.fadeout_ease.y); 961 } 962 mDo_fades = true; 963 } 964 else 965 { 966 mFade_value = 1.0f; 967 mDo_fades = false; 968 } 969 } 970 else 971 { 972 mFade_value = 1.0; 973 mDo_fades = false; 974 } 975 976 if (mDatablock->vis_keys && mDatablock->vis_keys->numKeys() > 0) 977 { 978 F32 vis = mDatablock->vis_keys->evaluate(mElapsed - mEW_timing.delay); 979 mFade_value *= mClampF(vis, 0.0f, 1.0f); 980 mDo_fades = (mFade_value < 1.0f); 981 } 982 983 // DEAL WITH CONSTRAINTS 984 afxXM_Params params; 985 Point3F& CONS_POS = params.pos; 986 MatrixF& CONS_XFM = params.ori; 987 Point3F& CONS_AIM = params.pos2; 988 Point3F& CONS_SCALE = params.scale; 989 LinearColorF& CONS_COLOR = params.color; 990 991 afxConstraint* pos_constraint = getPosConstraint(); 992 if (pos_constraint) 993 { 994 bool valid = pos_constraint->getPosition(CONS_POS, mDatablock->pos_cons_def.mHistory_time); 995 if (!valid) 996 getUnconstrainedPosition(CONS_POS); 997 setScopeStatus(valid); 998 if (valid && mDatablock->borrow_altitudes) 999 { 1000 F32 terr_alt, inter_alt; 1001 if (pos_constraint->getAltitudes(terr_alt, inter_alt)) 1002 { 1003 mTerrain_altitude = terr_alt; 1004 mInterior_altitude = inter_alt; 1005 } 1006 } 1007 } 1008 else 1009 { 1010 getUnconstrainedPosition(CONS_POS); 1011 setScopeStatus(false); 1012 } 1013 1014 afxConstraint* orient_constraint = getOrientConstraint(); 1015 if (orient_constraint) 1016 { 1017 orient_constraint->getTransform(CONS_XFM, mDatablock->pos_cons_def.mHistory_time); 1018 } 1019 else 1020 { 1021 getUnconstrainedTransform(CONS_XFM); 1022 } 1023 1024 afxConstraint* aim_constraint = getAimConstraint(); 1025 if (aim_constraint) 1026 aim_constraint->getPosition(CONS_AIM, mDatablock->pos_cons_def.mHistory_time); 1027 else 1028 CONS_AIM.zero(); 1029 1030 CONS_SCALE.set(mDatablock->scale_factor, mDatablock->scale_factor, mDatablock->scale_factor); 1031 1032 /* 1033 if (datablock->isPositional() && CONS_POS.isZero() && in_scope) 1034 Con::errorf("#EFFECT AT ORIGIN [%s] time=%g", datablock->getName(), dt); 1035 */ 1036 1037 getBaseColor(CONS_COLOR); 1038 1039 params.vis = mFade_value; 1040 1041 // apply modifiers 1042 for (int i = 0; i < MAX_XFM_MODIFIERS; i++) 1043 { 1044 if (!mXfm_modifiers[i]) 1045 break; 1046 else 1047 mXfm_modifiers[i]->updateParams(dt, mLife_elapsed, params); 1048 } 1049 1050 // final pos/orient is determined 1051 mUpdated_xfm = CONS_XFM; 1052 mUpdated_pos = CONS_POS; 1053 mUpdated_aim = CONS_AIM; 1054 mUpdated_xfm.setPosition(mUpdated_pos); 1055 mUpdated_scale = CONS_SCALE; 1056 mUpdated_color = CONS_COLOR; 1057 1058 if (params.vis > 1.0f) 1059 mFade_value = 1.0f; 1060 else 1061 mFade_value = params.vis; 1062 1063 if (mLast_fade_value != mFade_value) 1064 { 1065 mDo_fades = true; 1066 mLast_fade_value = mFade_value; 1067 } 1068 else 1069 { 1070 mDo_fades = (mFade_value < 1.0f); 1071 } 1072 1073 if (!ea_update(dt)) 1074 { 1075 mIs_aborted = true; 1076 Con::errorf("afxEffectWrapper::update() -- effect %s ended unexpectedly.", mDatablock->getName()); 1077 } 1078 1079 return true; 1080} 1081 1082void afxEffectWrapper::stop() 1083{ 1084 if (!mDatablock->requiresStop(mEW_timing)) 1085 return; 1086 1087 mStopped = true; 1088 1089 // this resets full_lifetime so it starts to shrink or fade 1090 if (mFull_lifetime == INFINITE_LIFETIME) 1091 { 1092 mFull_lifetime = (mElapsed - mEW_timing.delay) + afterStopTime(); 1093 mLife_end = mElapsed; 1094 if (mEW_timing.fade_out_time > 0) 1095 mFade_out_start = mElapsed; 1096 } 1097} 1098 1099void afxEffectWrapper::cleanup(bool was_stopped) 1100{ 1101 ea_finish(was_stopped); 1102 if (!mEffect_cons_id.undefined()) 1103 { 1104 mCons_mgr->setReferenceEffect(mEffect_cons_id, 0); 1105 mEffect_cons_id = afxConstraintID(); 1106 } 1107} 1108 1109void afxEffectWrapper::setScopeStatus(bool in_scope) 1110{ 1111 if (mIn_scope != in_scope) 1112 { 1113 mIn_scope = in_scope; 1114 ea_set_scope_status(in_scope); 1115 } 1116} 1117 1118bool afxEffectWrapper::isDone() 1119{ 1120 if (!mDatablock->is_looping) 1121 return (mElapsed >= (mLife_end + mEW_timing.fade_out_time)); 1122 1123 return false; 1124} 1125 1126 1127//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1128 1129// static 1130afxEffectWrapper* afxEffectWrapper::ew_create(afxChoreographer* choreographer, 1131 afxEffectWrapperData* datablock, 1132 afxConstraintMgr* cons_mgr, 1133 F32 time_factor, 1134 S32 group_index) 1135{ 1136 afxEffectWrapper* adapter = datablock->effect_desc->create(); 1137 1138 if (adapter) 1139 { 1140 adapter->mGroup_index = (datablock->group_index != -1) ? datablock->group_index : group_index; 1141 adapter->ew_init(choreographer, datablock, cons_mgr, time_factor); 1142 } 1143 1144 return adapter; 1145} 1146 1147//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1148 1149Vector<afxEffectAdapterDesc*>* afxEffectAdapterDesc::adapters = 0; 1150 1151afxEffectAdapterDesc::afxEffectAdapterDesc() 1152{ 1153 if (!adapters) 1154 adapters = new Vector<afxEffectAdapterDesc*>; 1155 1156 adapters->push_back(this); 1157} 1158 1159bool afxEffectAdapterDesc::identifyEffect(afxEffectWrapperData* ew) 1160{ 1161 if (!ew || !ew->effect_data) 1162 { 1163 Con::errorf("afxEffectAdapterDesc::identifyEffect() -- effect datablock was not specified."); 1164 return false; 1165 } 1166 1167 if (!adapters) 1168 { 1169 Con::errorf("afxEffectAdapterDesc::identifyEffect() -- adapter registration list has not been allocated."); 1170 return false; 1171 } 1172 1173 if (adapters->size() == 0) 1174 { 1175 Con::errorf("afxEffectAdapterDesc::identifyEffect() -- no effect adapters have been registered."); 1176 return false; 1177 } 1178 1179 for (S32 i = 0; i < adapters->size(); i++) 1180 { 1181 if ((*adapters)[i]->testEffectType(ew->effect_data)) 1182 { 1183 ew->effect_desc = (*adapters)[i]; 1184 (*adapters)[i]->prepEffect(ew); 1185 return true; 1186 } 1187 } 1188 1189 Con::errorf("afxEffectAdapterDesc::identifyEffect() -- effect %s has an undefined type. -- %d", 1190 ew->effect_data->getName(), adapters->size()); 1191 return false; 1192} 1193 1194//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1195