1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195 |
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
- // Copyright (C) 2015 Faust Logic, Inc.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- #include "afx/arcaneFX.h"
- #include "math/mathIO.h"
- #include "afx/ce/afxComponentEffect.h"
- #include "afx/afxResidueMgr.h"
- #include "afx/afxChoreographer.h"
- #include "afx/afxConstraint.h"
- #include "afx/xm/afxXfmMod.h"
- #include "afx/afxEffectWrapper.h"
- #include "afx/util/afxAnimCurve.h"
- #include "afx/util/afxEase.h"
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // afxEffectWrapperData
- IMPLEMENT_CO_DATABLOCK_V1(afxEffectBaseData);
- ConsoleDocClass( afxEffectBaseData,
- "@brief A datablock baseclass for afxEffectWrapperData and afxEffectGroupData.\n\n"
- "Not intended to be used directly, afxEffectBaseData exists to provide base member "
- "variables and generic functionality for the derived classes afxEffectWrapperData and "
- "afxEffectGroupData.\n\n"
- "@see afxEffectWrapperData\n\n"
- "@see afxEffectGroupData\n\n"
- "@ingroup afxEffects\n"
- "@ingroup AFX\n"
- "@ingroup Datablocks\n"
- );
- IMPLEMENT_CO_DATABLOCK_V1(afxEffectWrapperData);
- ConsoleDocClass( afxEffectWrapperData,
- "@brief A datablock that describes an Effect Wrapper.\n\n"
- "Conceptually an effect wrapper encloses a building-block effect and acts "
- "as a handle for adding the effect to a choreographer. Effect wrapper fields "
- "primarily deal with effect timing, constraints, and conditional effect execution.\n\n"
- "@see afxEffectBaseData\n\n"
- "@see afxEffectGroupData\n\n"
- "@ingroup afxEffects\n"
- "@ingroup AFX\n"
- "@ingroup Datablocks\n"
- );
- afxEffectWrapperData::afxEffectWrapperData()
- {
- effect_name = ST_NULLSTRING;
- effect_data = 0;
- effect_desc = 0;
- data_ID = 0;
- use_as_cons_obj = false;
- use_ghost_as_cons_obj = false;
- // constraint data
- cons_spec = ST_NULLSTRING;
- pos_cons_spec = ST_NULLSTRING;
- orient_cons_spec = ST_NULLSTRING;
- aim_cons_spec = StringTable->insert("camera");
- life_cons_spec = ST_NULLSTRING;
- // conditional execution flags
- effect_enabled = true;
- ranking_range.set(0,255);
- lod_range.set(0,255);
- life_conds = 0;
- for (S32 i = 0; i < MAX_CONDITION_STATES; i++)
- {
- exec_cond_on_bits[i] = 0;
- exec_cond_off_bits[i] = 0;
- exec_cond_bitmasks[i] = 0;
- }
- ewd_timing.lifetime = -1;
- user_fade_out_time = 0.0;
- is_looping = false;
- n_loops = 0;
- loop_gap_time = 0.0f;
- ignore_time_factor = false;
- propagate_time_factor = false;
- // residue settings
- // scaling factors
- rate_factor = 1.0f;
- scale_factor = 1.0f;
- dMemset(xfm_modifiers, 0, sizeof(xfm_modifiers));
- forced_bbox.minExtents.set(1,1,1);
- forced_bbox.maxExtents.set(-1,-1,-1);
- update_forced_bbox = false;
- // marked true if datablock ids need to
- // be converted into pointers
- do_id_convert = false;
- sort_priority = 0;
- direction.set(0,1,0);
- speed = 0.0f;
- mass = 1.0f;
- borrow_altitudes = false;
- vis_keys_spec = ST_NULLSTRING;
- vis_keys = 0;
- group_index = -1;
- inherit_timing = 0;
- }
- afxEffectWrapperData::afxEffectWrapperData(const afxEffectWrapperData& other, bool temp_clone) : afxEffectBaseData(other, temp_clone)
- {
- effect_name = other.effect_name;
- effect_data = other.effect_data;
- effect_desc = other.effect_desc;
- data_ID = other.data_ID;
- use_as_cons_obj = other.use_as_cons_obj;
- use_ghost_as_cons_obj = other.use_ghost_as_cons_obj;
- cons_spec = other.cons_spec;
- pos_cons_spec = other.pos_cons_spec;
- orient_cons_spec = other.orient_cons_spec;
- aim_cons_spec = other.aim_cons_spec;
- life_cons_spec = other.life_cons_spec;
- cons_def = other.cons_def;
- pos_cons_def = other.pos_cons_def;
- orient_cons_def = other.orient_cons_def;
- aim_cons_def = other.aim_cons_def;
- life_cons_def = other.life_cons_def;
- effect_enabled = other.effect_enabled;
- ranking_range = other.ranking_range;
- lod_range = other.lod_range;
- life_conds = other.life_conds;
- dMemcpy(exec_cond_on_bits, other.exec_cond_on_bits, sizeof(exec_cond_on_bits));
- dMemcpy(exec_cond_off_bits, other.exec_cond_off_bits, sizeof(exec_cond_off_bits));
- dMemcpy(exec_cond_bitmasks, other.exec_cond_bitmasks, sizeof(exec_cond_bitmasks));
- ewd_timing = other.ewd_timing;
- user_fade_out_time = other.user_fade_out_time;
- is_looping = other.is_looping;
- n_loops = other.n_loops;
- loop_gap_time = other.loop_gap_time;
- ignore_time_factor = other.ignore_time_factor;
- propagate_time_factor = other.propagate_time_factor;
- rate_factor = other.rate_factor;
- scale_factor = other.scale_factor;
- dMemcpy(xfm_modifiers, other.xfm_modifiers, sizeof(xfm_modifiers));
- forced_bbox = other.forced_bbox;
- update_forced_bbox = other.update_forced_bbox;
- do_id_convert = other.do_id_convert;
- sort_priority = other.sort_priority;
- direction = other.direction;
- speed = other.speed;
- mass = other.mass;
- borrow_altitudes = other.borrow_altitudes;
- vis_keys_spec = other.vis_keys_spec;
- vis_keys = other.vis_keys;
- if (other.vis_keys)
- {
- vis_keys = new afxAnimCurve();
- for (S32 i = 0; i < other.vis_keys->numKeys(); i++)
- {
- F32 when = other.vis_keys->getKeyTime(i);
- F32 what = other.vis_keys->getKeyValue(i);
- vis_keys->addKey(when, what);
- }
- }
- else
- vis_keys = 0;
- group_index = other.group_index;
- inherit_timing = other.inherit_timing;
- }
- afxEffectWrapperData::~afxEffectWrapperData()
- {
- if (vis_keys)
- delete vis_keys;
- }
- #define myOffset(field) Offset(field, afxEffectWrapperData)
- void afxEffectWrapperData::initPersistFields()
- {
- docsURL;
- // the wrapped effect
- addField("effect", TYPEID<SimDataBlock>(), myOffset(effect_data),
- "...");
- addField("effectName", TypeString, myOffset(effect_name),
- "...");
- // constraints
- addField("constraint", TypeString, myOffset(cons_spec),
- "...");
- addField("posConstraint", TypeString, myOffset(pos_cons_spec),
- "...");
- addField("posConstraint2", TypeString, myOffset(aim_cons_spec),
- "...");
- addField("orientConstraint", TypeString, myOffset(orient_cons_spec),
- "...");
- addField("lifeConstraint", TypeString, myOffset(life_cons_spec),
- "...");
- //
- addField("isConstraintSrc", TypeBool, myOffset(use_as_cons_obj),
- "...");
- addField("ghostIsConstraintSrc", TypeBool, myOffset(use_ghost_as_cons_obj),
- "...");
- addField("delay", TypeF32, myOffset(ewd_timing.delay),
- "...");
- addField("lifetime", TypeF32, myOffset(ewd_timing.lifetime),
- "...");
- addField("fadeInTime", TypeF32, myOffset(ewd_timing.fade_in_time),
- "...");
- addField("residueLifetime", TypeF32, myOffset(ewd_timing.residue_lifetime),
- "...");
- addField("fadeInEase", TypePoint2F, myOffset(ewd_timing.fadein_ease),
- "...");
- addField("fadeOutEase", TypePoint2F, myOffset(ewd_timing.fadeout_ease),
- "...");
- addField("lifetimeBias", TypeF32, myOffset(ewd_timing.life_bias),
- "...");
- addField("fadeOutTime", TypeF32, myOffset(user_fade_out_time),
- "...");
- addField("rateFactor", TypeF32, myOffset(rate_factor),
- "...");
- addField("scaleFactor", TypeF32, myOffset(scale_factor),
- "...");
- addField("isLooping", TypeBool, myOffset(is_looping),
- "...");
- addField("loopCount", TypeS32, myOffset(n_loops),
- "...");
- addField("loopGapTime", TypeF32, myOffset(loop_gap_time),
- "...");
- addField("ignoreTimeFactor", TypeBool, myOffset(ignore_time_factor),
- "...");
- addField("propagateTimeFactor", TypeBool, myOffset(propagate_time_factor),
- "...");
- addField("effectEnabled", TypeBool, myOffset(effect_enabled),
- "...");
- addField("rankingRange", TypeByteRange, myOffset(ranking_range),
- "...");
- addField("levelOfDetailRange", TypeByteRange, myOffset(lod_range),
- "...");
- addField("lifeConditions", TypeS32, myOffset(life_conds),
- "...");
- addField("execConditions", TypeS32, myOffset(exec_cond_on_bits), MAX_CONDITION_STATES,
- "...");
- addField("execOffConditions", TypeS32, myOffset(exec_cond_off_bits), MAX_CONDITION_STATES,
- "...");
- addField("xfmModifiers", TYPEID<afxXM_BaseData>(), myOffset(xfm_modifiers), MAX_XFM_MODIFIERS,
- "...");
- addField("forcedBBox", TypeBox3F, myOffset(forced_bbox),
- "...");
- addField("updateForcedBBox", TypeBool, myOffset(update_forced_bbox),
- "...");
- addField("sortPriority", TypeS8, myOffset(sort_priority),
- "...");
- addField("direction", TypePoint3F, myOffset(direction),
- "...");
- addField("speed", TypeF32, myOffset(speed),
- "...");
- addField("mass", TypeF32, myOffset(mass),
- "...");
- addField("borrowAltitudes", TypeBool, myOffset(borrow_altitudes),
- "...");
- addField("visibilityKeys", TypeString, myOffset(vis_keys_spec),
- "...");
- addField("groupIndex", TypeS32, myOffset(group_index),
- "...");
- addField("inheritGroupTiming", TypeS32, myOffset(inherit_timing),
- "...");
- Parent::initPersistFields();
- // disallow some field substitutions
- disableFieldSubstitutions("effect");
- onlyKeepClearSubstitutions("xfmModifiers"); // subs resolving to "~~", or "~0" are OK
- // Conditional Execution Flags
- Con::setIntVariable("$afx::DISABLED", DISABLED);
- Con::setIntVariable("$afx::ENABLED", ENABLED);
- Con::setIntVariable("$afx::FAILING", FAILING);
- Con::setIntVariable("$afx::DEAD", DEAD);
- Con::setIntVariable("$afx::ALIVE", ALIVE);
- Con::setIntVariable("$afx::DYING", DYING);
- }
- bool afxEffectWrapperData::onAdd()
- {
- if (Parent::onAdd() == false)
- return false;
- if (!effect_data)
- {
- if (!Sim::findObject((SimObjectId)data_ID, effect_data))
- {
- Con::errorf("afxEffectWrapperData::onAdd() -- bad datablockId: 0x%x", data_ID);
- return false;
- }
- }
- if (effect_data)
- {
- if (!afxEffectAdapterDesc::identifyEffect(this))
- {
- Con::errorf("afxEffectWrapperData::onAdd() -- unknown effect type.");
- return false;
- }
- }
- parse_cons_specs();
- parse_vis_keys();
- // figure out if fade-out is for effect of residue
- if (ewd_timing.residue_lifetime > 0)
- {
- ewd_timing.residue_fadetime = user_fade_out_time;
- ewd_timing.fade_out_time = 0.0f;
- }
- else
- {
- ewd_timing.residue_fadetime = 0.0f;
- ewd_timing.fade_out_time = user_fade_out_time;
- }
- // adjust fade-in time
- if (ewd_timing.lifetime >= 0)
- {
- ewd_timing.fade_in_time = getMin(ewd_timing.lifetime, ewd_timing.fade_in_time);
- }
- // adjust exec-conditions
- for (S32 i = 0; i < MAX_CONDITION_STATES; i++)
- exec_cond_bitmasks[i] = exec_cond_on_bits[i] | exec_cond_off_bits[i];
- return true;
- }
- void afxEffectWrapperData::packData(BitStream* stream)
- {
- Parent::packData(stream);
- writeDatablockID(stream, effect_data, mPacked);
- stream->writeString(effect_name);
- stream->writeString(cons_spec);
- stream->writeString(pos_cons_spec);
- stream->writeString(orient_cons_spec);
- stream->writeString(aim_cons_spec);
- stream->writeString(life_cons_spec);
- //
- stream->write(use_as_cons_obj);
- //stream->write(use_ghost_as_cons_obj);
- stream->writeFlag(effect_enabled);
- stream->write(ranking_range.low);
- stream->write(ranking_range.high);
- stream->write(lod_range.low);
- stream->write(lod_range.high);
- for (S32 i = 0; i < MAX_CONDITION_STATES; i++)
- {
- stream->write(exec_cond_on_bits[i]);
- stream->write(exec_cond_off_bits[i]);
- }
- stream->write(life_conds);
- stream->write(ewd_timing.delay);
- stream->write(ewd_timing.lifetime);
- stream->write(ewd_timing.fade_in_time);
- stream->write(user_fade_out_time);
- stream->write(is_looping);
- stream->write(n_loops);
- stream->write(loop_gap_time);
- stream->write(ignore_time_factor);
- stream->write(propagate_time_factor);
- stream->write(ewd_timing.residue_lifetime);
- stream->write(rate_factor);
- stream->write(scale_factor);
- // modifiers
- pack_mods(stream, xfm_modifiers, mPacked);
- mathWrite(*stream, forced_bbox);
- stream->write(update_forced_bbox);
- stream->write(sort_priority);
- mathWrite(*stream, direction);
- stream->write(speed);
- stream->write(mass);
- stream->write(borrow_altitudes);
- if (stream->writeFlag(vis_keys_spec != ST_NULLSTRING))
- stream->writeLongString(1023, vis_keys_spec);
- if (stream->writeFlag(group_index != -1))
- stream->write(group_index);
- stream->writeInt(inherit_timing, TIMING_BITS);
- }
- void afxEffectWrapperData::unpackData(BitStream* stream)
- {
- Parent::unpackData(stream);
- data_ID = readDatablockID(stream);
- effect_name = stream->readSTString();
- cons_spec = stream->readSTString();
- pos_cons_spec = stream->readSTString();
- orient_cons_spec = stream->readSTString();
- aim_cons_spec = stream->readSTString();
- life_cons_spec = stream->readSTString();
- //
- stream->read(&use_as_cons_obj);
- //stream->read(&use_ghost_as_cons_obj);
- effect_enabled = stream->readFlag();
- stream->read(&ranking_range.low);
- stream->read(&ranking_range.high);
- stream->read(&lod_range.low);
- stream->read(&lod_range.high);
- for (S32 i = 0; i < MAX_CONDITION_STATES; i++)
- {
- stream->read(&exec_cond_on_bits[i]);
- stream->read(&exec_cond_off_bits[i]);
- }
- stream->read(&life_conds);
- stream->read(&ewd_timing.delay);
- stream->read(&ewd_timing.lifetime);
- stream->read(&ewd_timing.fade_in_time);
- stream->read(&user_fade_out_time);
- stream->read(&is_looping);
- stream->read(&n_loops);
- stream->read(&loop_gap_time);
- stream->read(&ignore_time_factor);
- stream->read(&propagate_time_factor);
- stream->read(&ewd_timing.residue_lifetime);
- stream->read(&rate_factor);
- stream->read(&scale_factor);
- // modifiers
- do_id_convert = true;
- unpack_mods(stream, xfm_modifiers);
- mathRead(*stream, &forced_bbox);
- stream->read(&update_forced_bbox);
- stream->read(&sort_priority);
- mathRead(*stream, &direction);
- stream->read(&speed);
- stream->read(&mass);
- stream->read(&borrow_altitudes);
- if (stream->readFlag())
- {
- char buf[1024];
- stream->readLongString(1023, buf);
- vis_keys_spec = StringTable->insert(buf);
- }
- else
- vis_keys_spec = ST_NULLSTRING;
- if (stream->readFlag())
- stream->read(&group_index);
- else
- group_index = -1;
- inherit_timing = stream->readInt(TIMING_BITS);
- }
- /* static*/
- S32 num_modifiers(afxXM_BaseData* mods[])
- {
- S32 n_mods = 0;
- for (int i = 0; i < afxEffectDefs::MAX_XFM_MODIFIERS; i++)
- {
- if (mods[i])
- {
- if (i != n_mods)
- {
- mods[n_mods] = mods[i];
- mods[i] = 0;
- }
- n_mods++;
- }
- }
- return n_mods;
- }
- void afxEffectWrapperData::parse_cons_specs()
- {
- // parse the constraint specifications
- bool runs_on_s = runsOnServer();
- bool runs_on_c = runsOnClient();
- cons_def.parseSpec(cons_spec, runs_on_s, runs_on_c);
- pos_cons_def.parseSpec(pos_cons_spec, runs_on_s, runs_on_c);
- orient_cons_def.parseSpec(orient_cons_spec, runs_on_s, runs_on_c);
- aim_cons_def.parseSpec(aim_cons_spec, runs_on_s, runs_on_c);
- life_cons_def.parseSpec(life_cons_spec, runs_on_s, runs_on_c);
- if (cons_def.isDefined())
- {
- pos_cons_def = cons_def;
- if (!orient_cons_def.isDefined())
- orient_cons_def = cons_def;
- }
- }
- void afxEffectWrapperData::parse_vis_keys()
- {
- if (vis_keys_spec != ST_NULLSTRING)
- {
- if (vis_keys)
- delete vis_keys;
- vis_keys = new afxAnimCurve();
- char* keys_buffer = dStrdup(vis_keys_spec);
- char* key_token = dStrtok(keys_buffer, " \t");
- while (key_token != NULL)
- {
- char* colon = dStrchr(key_token, ':');
- if (colon)
- {
- *colon = '\0';
- F32 when = dAtof(key_token);
- F32 what = dAtof(colon+1);
- vis_keys->addKey(when, what);
- }
- key_token = dStrtok(NULL, " \t");
- }
- dFree(keys_buffer);
- vis_keys->sort();
- }
- }
- void afxEffectWrapperData::gather_cons_defs(Vector<afxConstraintDef>& defs)
- {
- if (pos_cons_def.isDefined())
- defs.push_back(pos_cons_def);
- if (orient_cons_def.isDefined())
- defs.push_back(orient_cons_def);
- if (aim_cons_def.isDefined())
- defs.push_back(aim_cons_def);
- if (life_cons_def.isDefined())
- defs.push_back(life_cons_def);
- afxComponentEffectData* ce_data = dynamic_cast<afxComponentEffectData*>(effect_data);
- if (ce_data)
- ce_data->gather_cons_defs(defs);
- }
- void afxEffectWrapperData::pack_mods(BitStream* stream, afxXM_BaseData* mods[], bool packed)
- {
- S32 n_mods = num_modifiers(mods);
- stream->writeInt(n_mods, 6);
- for (int i = 0; i < n_mods; i++)
- writeDatablockID(stream, mods[i], packed);
- }
- void afxEffectWrapperData::unpack_mods(BitStream* stream, afxXM_BaseData* mods[])
- {
- S32 n_mods = stream->readInt(6);
- for (int i = 0; i < n_mods; i++)
- mods[i] = (afxXM_BaseData*)(uintptr_t)readDatablockID(stream);
- }
- bool afxEffectWrapperData::preload(bool server, String &errorStr)
- {
- if (!Parent::preload(server, errorStr))
- return false;
-
- // Resolve objects transmitted from server
- if (!server)
- {
- if (do_id_convert)
- {
- for (int i = 0; i < MAX_XFM_MODIFIERS; i++)
- {
- SimObjectId db_id = SimObjectId((uintptr_t)xfm_modifiers[i]);
- if (db_id != 0)
- {
- // try to convert id to pointer
- if (!Sim::findObject(db_id, xfm_modifiers[i]))
- {
- Con::errorf("afxEffectWrapperData::preload() -- bad datablockId: 0x%x (xfm_modifiers[%d])",
- db_id, i);
- }
- }
- do_id_convert = false;
- }
- }
- }
-
- return true;
- }
- void afxEffectWrapperData::onPerformSubstitutions()
- {
- Parent::onPerformSubstitutions();
- parse_cons_specs();
- parse_vis_keys();
- if (ewd_timing.residue_lifetime > 0)
- {
- ewd_timing.residue_fadetime = user_fade_out_time;
- ewd_timing.fade_out_time = 0.0f;
- }
- else
- {
- ewd_timing.residue_fadetime = 0.0f;
- ewd_timing.fade_out_time = user_fade_out_time;
- }
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // afxEffectWrapper
- IMPLEMENT_CONOBJECT(afxEffectWrapper);
- ConsoleDocClass( afxEffectWrapper,
- "@brief An Effect Wrapper as defined by an afxEffectWrapperData datablock.\n\n"
- "Conceptually an effect wrapper encloses a building-block effect and acts "
- "as a handle for adding the effect to a choreographer. Effect wrapper fields "
- "primarily deal with effect timing, constraints, and conditional effect execution.\n\n"
- "Not intended to be used directly, afxEffectWrapper is an internal baseclass used to "
- "implement effect-specific adapter classes.\n\n"
- "@ingroup afxEffects\n"
- "@ingroup AFX\n"
- );
- afxEffectWrapper::afxEffectWrapper()
- {
- mChoreographer = 0;
- mDatablock = 0;
- mCons_mgr = 0;
- mCond_alive = true;
- mElapsed = 0;
- mLife_end = 0;
- mLife_elapsed = 0;
- mStopped = false;
- mNum_updates = 0;
- mFade_value = 1.0f;
- mLast_fade_value = 0.0f;
- mFade_in_end = 0.0;
- mFade_out_start = 0.0f;
- mIn_scope = true;
- mIs_aborted = false;
- mDo_fade_inout = false;
- mDo_fades = false;
- mFull_lifetime = 0;
- mTime_factor = 1.0f;
- mProp_time_factor = 1.0f;
- mLive_scale_factor = 1.0f;
- mLive_fade_factor = 1.0f;
- mTerrain_altitude = -1.0f;
- mInterior_altitude = -1.0f;
- mGroup_index = 0;
- dMemset(mXfm_modifiers, 0, sizeof(mXfm_modifiers));
- }
- afxEffectWrapper::~afxEffectWrapper()
- {
- for (S32 i = 0; i < MAX_XFM_MODIFIERS; i++)
- if (mXfm_modifiers[i])
- delete mXfm_modifiers[i];
- if (mDatablock && mDatablock->effect_name != ST_NULLSTRING)
- {
- mChoreographer->removeNamedEffect(this);
- if (mDatablock->use_as_cons_obj && !mEffect_cons_id.undefined())
- mCons_mgr->setReferenceEffect(mEffect_cons_id, 0);
- }
- if (mDatablock && mDatablock->isTempClone())
- delete mDatablock;
- mDatablock = 0;
- }
- #undef myOffset
- #define myOffset(field) Offset(field, afxEffectWrapper)
- void afxEffectWrapper::initPersistFields()
- {
- docsURL;
- addField("liveScaleFactor", TypeF32, myOffset(mLive_scale_factor),
- "...");
- addField("liveFadeFactor", TypeF32, myOffset(mLive_fade_factor),
- "...");
- Parent::initPersistFields();
- }
- void afxEffectWrapper::ew_init(afxChoreographer* choreographer,
- afxEffectWrapperData* datablock,
- afxConstraintMgr* cons_mgr,
- F32 time_factor)
- {
- AssertFatal(choreographer != NULL, "Choreographer is missing.");
- AssertFatal(datablock != NULL, "Datablock is missing.");
- AssertFatal(cons_mgr != NULL, "Constraint manager is missing.");
- mChoreographer = choreographer;
- mDatablock = datablock;
- mCons_mgr = cons_mgr;
- ea_set_datablock(datablock->effect_data);
- mEW_timing = datablock->ewd_timing;
- if (mEW_timing.life_bias != 1.0f)
- {
- if (mEW_timing.lifetime > 0)
- mEW_timing.lifetime *= mEW_timing.life_bias;
- mEW_timing.fade_in_time *= mEW_timing.life_bias;
- mEW_timing.fade_out_time *= mEW_timing.life_bias;
- }
- mPos_cons_id = cons_mgr->getConstraintId(datablock->pos_cons_def);
- mOrient_cons_id = cons_mgr->getConstraintId(datablock->orient_cons_def);
- mAim_cons_id = cons_mgr->getConstraintId(datablock->aim_cons_def);
- mLife_cons_id = cons_mgr->getConstraintId(datablock->life_cons_def);
- mTime_factor = (datablock->ignore_time_factor) ? 1.0f : time_factor;
- if (datablock->propagate_time_factor)
- mProp_time_factor = time_factor;
- if (datablock->runsHere(choreographer->isServerObject()))
- {
- for (int i = 0; i < MAX_XFM_MODIFIERS && datablock->xfm_modifiers[i] != 0; i++)
- {
- mXfm_modifiers[i] = datablock->xfm_modifiers[i]->create(this, choreographer->isServerObject());
- AssertFatal(mXfm_modifiers[i] != 0, avar("Error, creation failed for xfm_modifiers[%d] of %s.", i, datablock->getName()));
- if (mXfm_modifiers[i] == 0)
- Con::errorf("Error, creation failed for xfm_modifiers[%d] of %s.", i, datablock->getName());
- }
- }
- if (datablock->effect_name != ST_NULLSTRING)
- {
- assignName(datablock->effect_name);
- choreographer->addNamedEffect(this);
- if (datablock->use_as_cons_obj)
- {
- mEffect_cons_id = cons_mgr->setReferenceEffect(datablock->effect_name, this);
- if (mEffect_cons_id.undefined() && datablock->isTempClone() && datablock->runsHere(choreographer->isServerObject()))
- mEffect_cons_id = cons_mgr->createReferenceEffect(datablock->effect_name, this);
- }
- }
- }
- void afxEffectWrapper::prestart()
- {
- // modify timing values by time_factor
- if (mEW_timing.lifetime > 0)
- mEW_timing.lifetime *= mTime_factor;
- mEW_timing.delay *= mTime_factor;
- mEW_timing.fade_in_time *= mTime_factor;
- mEW_timing.fade_out_time *= mTime_factor;
- if (mEW_timing.lifetime < 0)
- {
- mFull_lifetime = INFINITE_LIFETIME;
- mLife_end = INFINITE_LIFETIME;
- }
- else
- {
- mFull_lifetime = mEW_timing.lifetime + mEW_timing.fade_out_time;
- mLife_end = mEW_timing.delay + mEW_timing.lifetime;
- }
- if ((mEW_timing.fade_in_time + mEW_timing.fade_out_time) > 0.0f)
- {
- mFade_in_end = mEW_timing.delay + mEW_timing.fade_in_time;
- if (mFull_lifetime == INFINITE_LIFETIME)
- mFade_out_start = INFINITE_LIFETIME;
- else
- mFade_out_start = mEW_timing.delay + mEW_timing.lifetime;
- mDo_fade_inout = true;
- }
- if (!mDo_fade_inout && mDatablock->vis_keys != NULL && mDatablock->vis_keys->numKeys() > 0)
- {
- //do_fades = true;
- mFade_out_start = mEW_timing.delay + mEW_timing.lifetime;
- }
- }
- bool afxEffectWrapper::start(F32 timestamp)
- {
- if (!ea_is_enabled())
- {
- Con::warnf("afxEffectWrapper::start() -- effect type of %s is currently disabled.", mDatablock->getName());
- return false;
- }
- afxConstraint* life_constraint = getLifeConstraint();
- if (life_constraint)
- mCond_alive = life_constraint->getLivingState();
- mElapsed = timestamp;
- for (S32 i = 0; i < MAX_XFM_MODIFIERS; i++)
- {
- if (!mXfm_modifiers[i])
- break;
- else
- mXfm_modifiers[i]->start(timestamp);
- }
- if (!ea_start())
- {
- // subclass should print error message if applicable, so no message here.
- return false;
- }
- update(0.0f);
- return !isAborted();
- }
- bool afxEffectWrapper::test_life_conds()
- {
- afxConstraint* life_constraint = getLifeConstraint();
- if (!life_constraint || mDatablock->life_conds == 0)
- return true;
- S32 now_state = life_constraint->getDamageState();
- if ((mDatablock->life_conds & DEAD) != 0 && now_state == ShapeBase::Disabled)
- return true;
- if ((mDatablock->life_conds & ALIVE) != 0 && now_state == ShapeBase::Enabled)
- return true;
- if ((mDatablock->life_conds & DYING) != 0)
- return (mCond_alive && now_state == ShapeBase::Disabled);
- return false;
- }
- bool afxEffectWrapper::update(F32 dt)
- {
- mElapsed += dt;
- // life_elapsed won't exceed full_lifetime
- mLife_elapsed = getMin(mElapsed - mEW_timing.delay, mFull_lifetime);
- // update() returns early if elapsed is outside of active timing range
- // (delay <= elapsed <= delay+lifetime)
- // note: execution is always allowed beyond this point at least once,
- // even if elapsed exceeds the lifetime.
- if (mElapsed < mEW_timing.delay)
- {
- setScopeStatus(false);
- return false;
- }
-
- if (!mDatablock->requiresStop(mEW_timing) && mEW_timing.lifetime < 0)
- {
- F32 afterlife = mElapsed - mEW_timing.delay;
- if (afterlife > 1.0f || ((afterlife > 0.0f) && (mNum_updates > 0)))
- {
- setScopeStatus(mEW_timing.residue_lifetime > 0.0f);
- return false;
- }
- }
- else
- {
- F32 afterlife = mElapsed - (mFull_lifetime + mEW_timing.delay);
- if (afterlife > 1.0f || ((afterlife > 0.0f) && (mNum_updates > 0)))
- {
- setScopeStatus(mEW_timing.residue_lifetime > 0.0f);
- return false;
- }
- }
- // first time here, test if required conditions for effect are met
- if (mNum_updates == 0)
- {
- if (!test_life_conds())
- {
- mElapsed = mFull_lifetime + mEW_timing.delay;
- setScopeStatus(false);
- mNum_updates++;
- return false;
- }
- }
- setScopeStatus(true);
- mNum_updates++;
- // calculate current fade value if enabled
- if (mDo_fade_inout)
- {
- if (mEW_timing.fade_in_time > 0 && mElapsed <= mFade_in_end)
- {
- F32 t = mClampF((mElapsed - mEW_timing.delay)/ mEW_timing.fade_in_time, 0.0f, 1.0f);
- mFade_value = afxEase::t(t, mEW_timing.fadein_ease.x, mEW_timing.fadein_ease.y);
- mDo_fades = true;
- }
- else if (mElapsed > mFade_out_start)
- {
- if (mEW_timing.fade_out_time == 0)
- mFade_value = 0.0f;
- else
- {
- F32 t = mClampF(1.0f-(mElapsed - mFade_out_start)/ mEW_timing.fade_out_time, 0.0f, 1.0f);
- mFade_value = afxEase::t(t, mEW_timing.fadeout_ease.x, mEW_timing.fadeout_ease.y);
- }
- mDo_fades = true;
- }
- else
- {
- mFade_value = 1.0f;
- mDo_fades = false;
- }
- }
- else
- {
- mFade_value = 1.0;
- mDo_fades = false;
- }
- if (mDatablock->vis_keys && mDatablock->vis_keys->numKeys() > 0)
- {
- F32 vis = mDatablock->vis_keys->evaluate(mElapsed - mEW_timing.delay);
- mFade_value *= mClampF(vis, 0.0f, 1.0f);
- mDo_fades = (mFade_value < 1.0f);
- }
- // DEAL WITH CONSTRAINTS
- afxXM_Params params;
- Point3F& CONS_POS = params.pos;
- MatrixF& CONS_XFM = params.ori;
- Point3F& CONS_AIM = params.pos2;
- Point3F& CONS_SCALE = params.scale;
- LinearColorF& CONS_COLOR = params.color;
- afxConstraint* pos_constraint = getPosConstraint();
- if (pos_constraint)
- {
- bool valid = pos_constraint->getPosition(CONS_POS, mDatablock->pos_cons_def.mHistory_time);
- if (!valid)
- getUnconstrainedPosition(CONS_POS);
- setScopeStatus(valid);
- if (valid && mDatablock->borrow_altitudes)
- {
- F32 terr_alt, inter_alt;
- if (pos_constraint->getAltitudes(terr_alt, inter_alt))
- {
- mTerrain_altitude = terr_alt;
- mInterior_altitude = inter_alt;
- }
- }
- }
- else
- {
- getUnconstrainedPosition(CONS_POS);
- setScopeStatus(false);
- }
- afxConstraint* orient_constraint = getOrientConstraint();
- if (orient_constraint)
- {
- orient_constraint->getTransform(CONS_XFM, mDatablock->pos_cons_def.mHistory_time);
- }
- else
- {
- getUnconstrainedTransform(CONS_XFM);
- }
- afxConstraint* aim_constraint = getAimConstraint();
- if (aim_constraint)
- aim_constraint->getPosition(CONS_AIM, mDatablock->pos_cons_def.mHistory_time);
- else
- CONS_AIM.zero();
- CONS_SCALE.set(mDatablock->scale_factor, mDatablock->scale_factor, mDatablock->scale_factor);
- /*
- if (datablock->isPositional() && CONS_POS.isZero() && in_scope)
- Con::errorf("#EFFECT AT ORIGIN [%s] time=%g", datablock->getName(), dt);
- */
- getBaseColor(CONS_COLOR);
- params.vis = mFade_value;
- // apply modifiers
- for (int i = 0; i < MAX_XFM_MODIFIERS; i++)
- {
- if (!mXfm_modifiers[i])
- break;
- else
- mXfm_modifiers[i]->updateParams(dt, mLife_elapsed, params);
- }
- // final pos/orient is determined
- mUpdated_xfm = CONS_XFM;
- mUpdated_pos = CONS_POS;
- mUpdated_aim = CONS_AIM;
- mUpdated_xfm.setPosition(mUpdated_pos);
- mUpdated_scale = CONS_SCALE;
- mUpdated_color = CONS_COLOR;
- if (params.vis > 1.0f)
- mFade_value = 1.0f;
- else
- mFade_value = params.vis;
- if (mLast_fade_value != mFade_value)
- {
- mDo_fades = true;
- mLast_fade_value = mFade_value;
- }
- else
- {
- mDo_fades = (mFade_value < 1.0f);
- }
- if (!ea_update(dt))
- {
- mIs_aborted = true;
- Con::errorf("afxEffectWrapper::update() -- effect %s ended unexpectedly.", mDatablock->getName());
- }
- return true;
- }
- void afxEffectWrapper::stop()
- {
- if (!mDatablock->requiresStop(mEW_timing))
- return;
- mStopped = true;
- // this resets full_lifetime so it starts to shrink or fade
- if (mFull_lifetime == INFINITE_LIFETIME)
- {
- mFull_lifetime = (mElapsed - mEW_timing.delay) + afterStopTime();
- mLife_end = mElapsed;
- if (mEW_timing.fade_out_time > 0)
- mFade_out_start = mElapsed;
- }
- }
- void afxEffectWrapper::cleanup(bool was_stopped)
- {
- ea_finish(was_stopped);
- if (!mEffect_cons_id.undefined())
- {
- mCons_mgr->setReferenceEffect(mEffect_cons_id, 0);
- mEffect_cons_id = afxConstraintID();
- }
- }
- void afxEffectWrapper::setScopeStatus(bool in_scope)
- {
- if (mIn_scope != in_scope)
- {
- mIn_scope = in_scope;
- ea_set_scope_status(in_scope);
- }
- }
- bool afxEffectWrapper::isDone()
- {
- if (!mDatablock->is_looping)
- return (mElapsed >= (mLife_end + mEW_timing.fade_out_time));
- return false;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // static
- afxEffectWrapper* afxEffectWrapper::ew_create(afxChoreographer* choreographer,
- afxEffectWrapperData* datablock,
- afxConstraintMgr* cons_mgr,
- F32 time_factor,
- S32 group_index)
- {
- afxEffectWrapper* adapter = datablock->effect_desc->create();
- if (adapter)
- {
- adapter->mGroup_index = (datablock->group_index != -1) ? datablock->group_index : group_index;
- adapter->ew_init(choreographer, datablock, cons_mgr, time_factor);
- }
- return adapter;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- Vector<afxEffectAdapterDesc*>* afxEffectAdapterDesc::adapters = 0;
- afxEffectAdapterDesc::afxEffectAdapterDesc()
- {
- if (!adapters)
- adapters = new Vector<afxEffectAdapterDesc*>;
- adapters->push_back(this);
- }
- bool afxEffectAdapterDesc::identifyEffect(afxEffectWrapperData* ew)
- {
- if (!ew || !ew->effect_data)
- {
- Con::errorf("afxEffectAdapterDesc::identifyEffect() -- effect datablock was not specified.");
- return false;
- }
- if (!adapters)
- {
- Con::errorf("afxEffectAdapterDesc::identifyEffect() -- adapter registration list has not been allocated.");
- return false;
- }
- if (adapters->size() == 0)
- {
- Con::errorf("afxEffectAdapterDesc::identifyEffect() -- no effect adapters have been registered.");
- return false;
- }
- for (S32 i = 0; i < adapters->size(); i++)
- {
- if ((*adapters)[i]->testEffectType(ew->effect_data))
- {
- ew->effect_desc = (*adapters)[i];
- (*adapters)[i]->prepEffect(ew);
- return true;
- }
- }
- Con::errorf("afxEffectAdapterDesc::identifyEffect() -- effect %s has an undefined type. -- %d",
- ew->effect_data->getName(), adapters->size());
- return false;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|