afxEA_ZodiacPlane.cpp
Engine/source/afx/ea/afxEA_ZodiacPlane.cpp
Classes:
class
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 <typeinfo> 28#include "afx/arcaneFX.h" 29 30#include "math/mathUtils.h" 31 32#include "afx/afxEffectDefs.h" 33#include "afx/afxEffectWrapper.h" 34#include "afx/afxChoreographer.h" 35#include "afx/util/afxEase.h" 36#include "afx/afxResidueMgr.h" 37#include "afx/ce/afxZodiacPlane.h" 38 39//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 40// afxEA_ZodiacPlane 41 42class afxEA_ZodiacPlane : public afxEffectWrapper 43{ 44 typedef afxEffectWrapper Parent; 45 46 afxZodiacPlaneData* zode_data; 47 afxZodiacPlane* pzode; 48 49 F32 zode_angle_offset; 50 AngAxisF aa_rot; 51 52 F32 live_color_factor; 53 LinearColorF live_color; 54 55 F32 calc_facing_angle(); 56 void do_runtime_substitutions(); 57 58public: 59 /*C*/ afxEA_ZodiacPlane(); 60 /*D*/ ~afxEA_ZodiacPlane(); 61 62 virtual void ea_set_datablock(SimDataBlock*); 63 virtual bool ea_start(); 64 virtual bool ea_update(F32 dt); 65 virtual void ea_finish(bool was_stopped); 66 virtual void ea_set_scope_status(bool flag); 67 virtual void onDeleteNotify(SimObject*); 68 virtual void getUpdatedBoxCenter(Point3F& pos); 69 virtual void getBaseColor(LinearColorF& color) { color = zode_data->color; } 70}; 71 72F32 afxEA_ZodiacPlane::calc_facing_angle() 73{ 74 // get direction player is facing 75 VectorF shape_vec; 76 MatrixF shape_xfm; 77 78 afxConstraint* orient_constraint = getOrientConstraint(); 79 if (orient_constraint) 80 orient_constraint->getTransform(shape_xfm); 81 else 82 shape_xfm.identity(); 83 84 shape_xfm.getColumn(1, &shape_vec); 85 shape_vec.z = 0.0f; 86 shape_vec.normalize(); 87 88 F32 pitch, yaw; 89 MathUtils::getAnglesFromVector(shape_vec, yaw, pitch); 90 91 return mRadToDeg(yaw); 92} 93 94afxEA_ZodiacPlane::afxEA_ZodiacPlane() 95{ 96 zode_data = 0; 97 pzode = 0; 98 zode_angle_offset = 0; 99 live_color.set(1,1,1,1); 100 live_color_factor = 0.0f; 101} 102 103afxEA_ZodiacPlane::~afxEA_ZodiacPlane() 104{ 105 if (pzode) 106 pzode->deleteObject(); 107 if (zode_data && zode_data->isTempClone()) 108 delete zode_data; 109 zode_data = 0; 110} 111 112void afxEA_ZodiacPlane::ea_set_datablock(SimDataBlock* db) 113{ 114 zode_data = dynamic_cast<afxZodiacPlaneData*>(db); 115} 116 117bool afxEA_ZodiacPlane::ea_start() 118{ 119 if (!zode_data) 120 { 121 Con::errorf("afxEA_ZodiacPlane::ea_start() -- missing or incompatible datablock."); 122 return false; 123 } 124 125 do_runtime_substitutions(); 126 127 if (!zode_data->use_full_xfm) 128 zode_angle_offset = calc_facing_angle(); 129 130 switch (zode_data->face_dir) 131 { 132 case afxZodiacPlaneData::FACES_UP: 133 aa_rot.set(Point3F(0.0f,0.0f,1.0f),0.0f); 134 break; 135 case afxZodiacPlaneData::FACES_DOWN: 136 aa_rot.set(Point3F(0.0f,0.0f,-1.0f),0.0f); 137 break; 138 case afxZodiacPlaneData::FACES_FORWARD: 139 aa_rot.set(Point3F(0.0f,1.0f,0.0f),0.0f); 140 break; 141 case afxZodiacPlaneData::FACES_BACK: 142 aa_rot.set(Point3F(0.0f,-1.0f,0.0f),0.0f); 143 break; 144 case afxZodiacPlaneData::FACES_RIGHT: 145 aa_rot.set(Point3F(1.0f,0.0f,0.0f),0.0f); 146 break; 147 case afxZodiacPlaneData::FACES_LEFT: 148 aa_rot.set(Point3F(-1.0f,0.0f,0.0f),0.0f); 149 break; 150 } 151 152 return true; 153} 154 155bool afxEA_ZodiacPlane::ea_update(F32 dt) 156{ 157 if (!pzode) 158 { 159 // create and register effect 160 pzode = new afxZodiacPlane(); 161 pzode->onNewDataBlock(zode_data, false); 162 if (!pzode->registerObject()) 163 { 164 delete pzode; 165 pzode = 0; 166 Con::errorf("afxEA_ZodiacPlane::ea_update() -- effect failed to register."); 167 return false; 168 } 169 deleteNotify(pzode); 170 171 ///pzode->setSequenceRateFactor(datablock->rate_factor/prop_time_factor); 172 ///pzode->setSortPriority(datablock->sort_priority); 173 } 174 175 if (pzode) 176 { 177 //LinearColorF zode_color = zode_data->color; 178 LinearColorF zode_color = mUpdated_color; 179 180 if (live_color_factor > 0.0) 181 zode_color.interpolate(zode_color, live_color, live_color_factor); 182 183 if (mDo_fades) 184 { 185 if (zode_data->blend_flags == afxZodiacDefs::BLEND_SUBTRACTIVE) 186 zode_color *= mFade_value *mLive_fade_factor; 187 else 188 zode_color.alpha *= mFade_value * mLive_fade_factor; 189 } 190 191 // scale and grow zode 192 //F32 zode_radius = zode_data->radius_xy*updated_scale.x + life_elapsed*zode_data->growth_rate; 193 F32 zode_radius = zode_data->radius_xy + mLife_elapsed *zode_data->growth_rate; 194 195 // zode is growing 196 if (mLife_elapsed < zode_data->grow_in_time) 197 { 198 F32 t = mLife_elapsed /zode_data->grow_in_time; 199 zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.2f, 0.8f); 200 } 201 // zode is shrinking 202 else if (mFull_lifetime - mLife_elapsed < zode_data->shrink_out_time) 203 { 204 F32 t = (mFull_lifetime - mLife_elapsed)/zode_data->shrink_out_time; 205 zode_radius = afxEase::eq(t, 0.001f, zode_radius, 0.0f, 0.9f); 206 } 207 208 zode_radius *= mLive_scale_factor; 209 210 if (zode_data->respect_ori_cons && !zode_data->use_full_xfm) 211 { 212 VectorF shape_vec; 213 mUpdated_xfm.getColumn(1, &shape_vec); 214 shape_vec.normalize(); 215 216 F32 ang; 217 218 switch (zode_data->face_dir) 219 { 220 case afxZodiacPlaneData::FACES_FORWARD: 221 case afxZodiacPlaneData::FACES_BACK: 222 ang = mAtan2(shape_vec.x, shape_vec.z); 223 break; 224 case afxZodiacPlaneData::FACES_RIGHT: 225 case afxZodiacPlaneData::FACES_LEFT: 226 ang = mAtan2(shape_vec.y, shape_vec.z); 227 break; 228 case afxZodiacPlaneData::FACES_UP: 229 case afxZodiacPlaneData::FACES_DOWN: 230 default: 231 ang = mAtan2(shape_vec.x, shape_vec.y); 232 break; 233 } 234 235 if (ang < 0.0f) 236 ang += M_2PI_F; 237 238 switch (zode_data->face_dir) 239 { 240 case afxZodiacPlaneData::FACES_DOWN: 241 case afxZodiacPlaneData::FACES_BACK: 242 case afxZodiacPlaneData::FACES_LEFT: 243 ang = -ang; 244 break; 245 } 246 247 zode_angle_offset = mRadToDeg(ang); 248 } 249 250 F32 zode_angle = zode_data->calcRotationAngle(mLife_elapsed, mDatablock->rate_factor/ mProp_time_factor); 251 zode_angle = mFmod(zode_angle + zode_angle_offset, 360.0f); 252 aa_rot.angle = mDegToRad(zode_angle); 253 254 MatrixF spin_xfm; 255 aa_rot.setMatrix(&spin_xfm); 256 257 // set color, radius 258 pzode->setColor(zode_color); 259 pzode->setRadius(zode_radius); 260 if (zode_data->use_full_xfm) 261 { 262 mUpdated_xfm.mul(spin_xfm); 263 pzode->setTransform(mUpdated_xfm); 264 } 265 else 266 pzode->setTransform(spin_xfm); 267 pzode->setPosition(mUpdated_pos); 268 pzode->setScale(mUpdated_scale); 269 } 270 271 return true; 272} 273 274void afxEA_ZodiacPlane::ea_finish(bool was_stopped) 275{ 276 if (!pzode) 277 return; 278 279 pzode->deleteObject(); 280 pzode = 0; 281} 282 283void afxEA_ZodiacPlane::ea_set_scope_status(bool in_scope) 284{ 285 if (pzode) 286 pzode->setVisibility(in_scope); 287} 288 289void afxEA_ZodiacPlane::onDeleteNotify(SimObject* obj) 290{ 291 if (pzode == dynamic_cast<afxZodiacPlane*>(obj)) 292 pzode = 0; 293 294 Parent::onDeleteNotify(obj); 295} 296 297void afxEA_ZodiacPlane::getUpdatedBoxCenter(Point3F& pos) 298{ 299 if (pzode) 300 pos = pzode->getBoxCenter(); 301} 302 303void afxEA_ZodiacPlane::do_runtime_substitutions() 304{ 305 // only clone the datablock if there are substitutions 306 if (zode_data->getSubstitutionCount() > 0) 307 { 308 // clone the datablock and perform substitutions 309 afxZodiacPlaneData* orig_db = zode_data; 310 zode_data = new afxZodiacPlaneData(*orig_db, true); 311 orig_db->performSubstitutions(zode_data, mChoreographer, mGroup_index); 312 } 313} 314 315 316//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 317 318class afxEA_ZodiacPlaneDesc : public afxEffectAdapterDesc, public afxEffectDefs 319{ 320 static afxEA_ZodiacPlaneDesc desc; 321 322public: 323 virtual bool testEffectType(const SimDataBlock*) const; 324 virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const; 325 virtual bool runsOnServer(const afxEffectWrapperData*) const { return false; } 326 virtual bool runsOnClient(const afxEffectWrapperData*) const { return true; } 327 328 virtual afxEffectWrapper* create() const { return new afxEA_ZodiacPlane; } 329}; 330 331//~~~~~~~~~~~~~~~~~~~~// 332 333afxEA_ZodiacPlaneDesc afxEA_ZodiacPlaneDesc::desc; 334 335bool afxEA_ZodiacPlaneDesc::testEffectType(const SimDataBlock* db) const 336{ 337 return (typeid(afxZodiacPlaneData) == typeid(*db)); 338} 339 340bool afxEA_ZodiacPlaneDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const 341{ 342 return (timing.lifetime < 0); 343} 344 345//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 346