123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086 |
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // 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 "console/engineAPI.h"
- #include "T3D/gameBase/gameConnection.h"
- #include "math/mathIO.h"
- #include "console/compiler.h"
- #include "afx/afxConstraint.h"
- #include "afx/afxChoreographer.h"
- #include "afx/afxEffectWrapper.h"
- #include "afx/util/afxParticlePool.h"
- #include "afx/forces/afxForceSet.h"
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- IMPLEMENT_CO_DATABLOCK_V1(afxChoreographerData);
- ConsoleDocClass( afxChoreographerData,
- "@brief Datablock base class used by choreographers.\n\n"
- "@ingroup afxChoreographers\n"
- "@ingroup AFX\n"
- "@ingroup Datablocks\n"
- );
- afxChoreographerData::afxChoreographerData()
- {
- exec_on_new_clients = false;
- echo_packet_usage = 100;
- client_script_file = ST_NULLSTRING;
- client_init_func = ST_NULLSTRING;
- }
- afxChoreographerData::afxChoreographerData(const afxChoreographerData& other, bool temp_clone) : GameBaseData(other, temp_clone)
- {
- exec_on_new_clients = other.exec_on_new_clients;
- echo_packet_usage = other.echo_packet_usage;
- client_script_file = other.client_script_file;
- client_init_func = other.client_init_func;
- }
- #define myOffset(field) Offset(field, afxChoreographerData)
- void afxChoreographerData::initPersistFields()
- {
- docsURL;
- addField("execOnNewClients", TypeBool, myOffset(exec_on_new_clients),
- "...");
- addField("echoPacketUsage", TypeS8, myOffset(echo_packet_usage),
- "...");
- addField("clientScriptFile", TypeFilename, myOffset(client_script_file),
- "...");
- addField("clientInitFunction", TypeString, myOffset(client_init_func),
- "...");
- Parent::initPersistFields();
- }
- void afxChoreographerData::packData(BitStream* stream)
- {
- Parent::packData(stream);
- stream->write(exec_on_new_clients);
- stream->write(echo_packet_usage);
- stream->writeString(client_script_file);
- stream->writeString(client_init_func);
- }
- void afxChoreographerData::unpackData(BitStream* stream)
- {
- Parent::unpackData(stream);
- stream->read(&exec_on_new_clients);
- stream->read(&echo_packet_usage);
- client_script_file = stream->readSTString();
- client_init_func = stream->readSTString();
- }
- bool afxChoreographerData::preload(bool server, String &errorStr)
- {
- if (!Parent::preload(server, errorStr))
- return false;
- if (!server && client_script_file != ST_NULLSTRING)
- {
- Compiler::gSyntaxError = false;
- Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0);
- if (Compiler::gSyntaxError)
- {
- Con::errorf("afxChoreographerData: failed to exec clientScriptFile \"%s\" -- syntax error", client_script_file);
- Compiler::gSyntaxError = false;
- }
- }
- return true;
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- IMPLEMENT_CO_DATABLOCK_V1(afxChoreographer);
- ConsoleDocClass( afxChoreographer,
- "@brief Base class used by choreographers.\n\n"
- "@ingroup afxChoreographers\n"
- "@ingroup AFX\n"
- );
- afxChoreographer::afxChoreographer()
- {
- datablock = 0; // datablock initializer (union these?)
- exeblock = 0; // object to use in executef callouts
- // create the constraint manager
- constraint_mgr = new afxConstraintMgr();
- ranking = 0;
- lod = 0;
- exec_conds_mask = 0;
- choreographer_id = 0;
- mExtra = 0;
- started_with_newop = false;
- postpone_activation = false;
- remapped_cons_sent = false; // CONSTRAINT REMAPPING
- dyn_cons_defs = &dc_defs_a;
- dyn_cons_defs2 = &dc_defs_b;
- proc_after_obj = 0;
- trigger_mask = 0;
- force_set_mgr = 0;
- mOrderGUID = 0x0FFFFFFF;
- }
- afxChoreographer::~afxChoreographer()
- {
- explicit_clients.clear();
- for (S32 i = 0; i < dyn_cons_defs->size(); i++)
- {
- if ((*dyn_cons_defs)[i].cons_type == POINT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.point != NULL)
- delete (*dyn_cons_defs)[i].cons_obj.point;
- else if ((*dyn_cons_defs)[i].cons_type == TRANSFORM_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.xfm != NULL)
- delete (*dyn_cons_defs)[i].cons_obj.xfm;
- }
- constraint_mgr->clearAllScopeableObjs();
- delete constraint_mgr;
- delete force_set_mgr;
- }
- void afxChoreographer::initPersistFields()
- {
- docsURL;
- // conditionals
- addField("extra", TYPEID<SimObject>(), Offset(mExtra, afxChoreographer),
- "...");
- addField("postponeActivation", TypeBool, Offset(postpone_activation, afxChoreographer),
- "...");
- Parent::initPersistFields();
- }
- bool afxChoreographer::onAdd()
- {
- if (!Parent::onAdd())
- return(false);
- if (isServerObject())
- choreographer_id = arcaneFX::registerChoreographer(this);
- else
- {
- if (proc_after_obj)
- {
- processAfter(proc_after_obj);
- proc_after_obj = 0;
- }
- force_set_mgr = new afxForceSetMgr();
- if (datablock && datablock->client_init_func != ST_NULLSTRING)
- Con::executef(datablock->client_init_func, getIdString());
- }
- return(true);
- }
- void afxChoreographer::onRemove()
- {
- for (S32 i = 0; i < particle_pools.size(); i++)
- if (particle_pools[i])
- particle_pools[i]->setChoreographer(0);
- particle_pools.clear();
- if (isServerObject())
- arcaneFX::unregisterChoreographer(this);
- else
- arcaneFX::unregisterClientChoreographer(this);
- choreographer_id = 0;
- Parent::onRemove();
- }
- void afxChoreographer::onDeleteNotify(SimObject* obj)
- {
- if (dynamic_cast<SceneObject*>(obj))
- {
- SceneObject* scn_obj = (SceneObject*)(obj);
- for (S32 i = 0; i < dyn_cons_defs->size(); i++)
- if ((*dyn_cons_defs)[i].cons_type != OBJECT_CONSTRAINT || (*dyn_cons_defs)[i].cons_obj.object != scn_obj)
- dyn_cons_defs2->push_back((*dyn_cons_defs)[i]);
- Vector<dynConstraintDef>* tmp = dyn_cons_defs;
- dyn_cons_defs = dyn_cons_defs2;
- dyn_cons_defs2 = tmp;
- dyn_cons_defs2->clear();
- if (isServerObject() && scn_obj->isScopeable())
- constraint_mgr->removeScopeableObject(scn_obj);
- }
- else if (dynamic_cast<NetConnection*>(obj))
- {
- removeExplicitClient((NetConnection*)obj);
- }
- Parent::onDeleteNotify(obj);
- }
- bool afxChoreographer::onNewDataBlock(GameBaseData* dptr, bool reload)
- {
- datablock = dynamic_cast<afxChoreographerData*>(dptr);
- if (!datablock || !Parent::onNewDataBlock(dptr, reload))
- return false;
- exeblock = datablock;
- return true;
- }
- void afxChoreographer::pack_constraint_info(NetConnection* conn, BitStream* stream)
- {
- stream->write(dyn_cons_defs->size());
- for (S32 i = 0; i < dyn_cons_defs->size(); i++)
- {
- if ((*dyn_cons_defs)[i].cons_type == OBJECT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.object != NULL)
- {
- stream->writeString((*dyn_cons_defs)[i].cons_name);
- stream->write((*dyn_cons_defs)[i].cons_type);
- SceneObject* object = (*dyn_cons_defs)[i].cons_obj.object;
- S32 ghost_idx = conn->getGhostIndex(object);
- if (stream->writeFlag(ghost_idx != -1))
- {
- stream->writeRangedU32(U32(ghost_idx), 0, NetConnection::MaxGhostCount);
- }
- else
- {
- if (stream->writeFlag(object->getScopeId() > 0))
- {
- stream->writeInt(object->getScopeId(), NetObject::SCOPE_ID_BITS);
- stream->writeFlag(dynamic_cast<ShapeBase*>(object) != NULL);
- }
- }
- }
- else if ((*dyn_cons_defs)[i].cons_type == POINT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.point != NULL)
- {
- stream->writeString((*dyn_cons_defs)[i].cons_name);
- stream->write((*dyn_cons_defs)[i].cons_type);
- mathWrite(*stream, *(*dyn_cons_defs)[i].cons_obj.point);
- }
- else if ((*dyn_cons_defs)[i].cons_type == TRANSFORM_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.xfm != NULL)
- {
- stream->writeString((*dyn_cons_defs)[i].cons_name);
- stream->write((*dyn_cons_defs)[i].cons_type);
- mathWrite(*stream, *(*dyn_cons_defs)[i].cons_obj.xfm);
- }
- }
-
- constraint_mgr->packConstraintNames(conn, stream);
- }
- void afxChoreographer::unpack_constraint_info(NetConnection* conn, BitStream* stream)
- {
- S32 n_defs;
- stream->read(&n_defs);
- dyn_cons_defs->clear();
- for (S32 i = 0; i < n_defs; i++)
- {
- StringTableEntry cons_name = stream->readSTString();
- U8 cons_type; stream->read(&cons_type);
- if (cons_type == OBJECT_CONSTRAINT)
- {
- SceneObject* scn_obj = NULL;
- if (stream->readFlag())
- {
- S32 ghost_idx = stream->readRangedU32(0, NetConnection::MaxGhostCount);
- scn_obj = dynamic_cast<SceneObject*>(conn->resolveGhost(ghost_idx));
- if (scn_obj)
- {
- addObjectConstraint(scn_obj, cons_name);
- }
- else
- Con::errorf("CANNOT RESOLVE GHOST %d %s", ghost_idx, cons_name);
- }
- else
- {
- if (stream->readFlag())
- {
- mScope_id = stream->readInt(NetObject::SCOPE_ID_BITS);
- bool is_shape = stream->readFlag();
- addObjectConstraint(mScope_id, cons_name, is_shape);
- }
- }
- }
- else if (cons_type == POINT_CONSTRAINT)
- {
- Point3F point;
- mathRead(*stream, &point);
- addPointConstraint(point, cons_name);
- }
- else if (cons_type == TRANSFORM_CONSTRAINT)
- {
- MatrixF xfm;
- mathRead(*stream, &xfm);
- addTransformConstraint(xfm, cons_name);
- }
- }
-
- constraint_mgr->unpackConstraintNames(stream);
- }
- void afxChoreographer::setup_dynamic_constraints()
- {
- for (S32 i = 0; i < dyn_cons_defs->size(); i++)
- {
- switch ((*dyn_cons_defs)[i].cons_type)
- {
- case OBJECT_CONSTRAINT:
- constraint_mgr->setReferenceObject((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.object);
- break;
- case POINT_CONSTRAINT:
- constraint_mgr->setReferencePoint((*dyn_cons_defs)[i].cons_name, *(*dyn_cons_defs)[i].cons_obj.point);
- break;
- case TRANSFORM_CONSTRAINT:
- constraint_mgr->setReferenceTransform((*dyn_cons_defs)[i].cons_name, *(*dyn_cons_defs)[i].cons_obj.xfm);
- break;
- case OBJECT_CONSTRAINT_SANS_OBJ:
- constraint_mgr->setReferenceObjectByScopeId((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.scope_id, false);
- break;
- case OBJECT_CONSTRAINT_SANS_SHAPE:
- constraint_mgr->setReferenceObjectByScopeId((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.scope_id, true);
- break;
- }
- }
- }
- afxChoreographer::dynConstraintDef* afxChoreographer::find_cons_def_by_name(const char* cons_name)
- {
- StringTableEntry cons_name_ste = StringTable->insert(cons_name);
- for (S32 i = 0; i < dyn_cons_defs->size(); i++)
- {
- if ((*dyn_cons_defs)[i].cons_name == cons_name_ste)
- return &((*dyn_cons_defs)[i]);
- }
- return 0;
- }
- void afxChoreographer::check_packet_usage(NetConnection* conn, BitStream* stream, S32 mark_stream_pos, const char* msg_tag)
- {
- S32 packed_size = stream->getCurPos() - mark_stream_pos;
- S32 current_headroom = stream->getMaxWriteBitNum()-(stream->getStreamSize()<<3);
- S32 max_headroom = stream->getMaxWriteBitNum()-(conn->getMaxRatePacketSize()<<3);
- if (packed_size > max_headroom)
- {
- Con::errorf("%s [%s] WARNING -- packed-bits (%d) > limit (%d) for max PacketSize settings. [%s]",
- msg_tag, datablock->getName(), packed_size, max_headroom, "PACKET OVERRUN POSSIBLE");
- Con::errorf("getMaxRatePacketSize()=%d getCurRatePacketSize()=%d", conn->getMaxRatePacketSize(), conn->getCurRatePacketSize());
- }
- // JTF Note: this current_headroom > 0 check is odd and occurs when object is created real early
- // in the startup, such as when the dead orc gets fatal damage and we try to post a text effect.
- else if (packed_size > current_headroom && current_headroom > 0)
- {
- Con::errorf("%s [%s] WARNING -- packed-bits (%d) > limit (%d) for current PacketSize settings. [%s]",
- msg_tag, datablock->getName(), packed_size, current_headroom, "PACKET OVERRUN POSSIBLE");
- }
- else
- {
- F32 percentage = 100.0f*((F32)packed_size/(F32)max_headroom);
- if (percentage >= datablock->echo_packet_usage)
- {
- Con::warnf("%s [%s] -- packed-bits (%d) < limit (%d). [%.1f%% full]", msg_tag, datablock->getName(),
- packed_size, max_headroom, percentage);
- }
- }
- }
- SceneObject* afxChoreographer::get_camera(Point3F* cam_pos) const
- {
- GameConnection* conn = GameConnection::getConnectionToServer();
- if (!conn)
- {
- if (cam_pos)
- cam_pos->zero();
- return 0;
- }
- SceneObject* cam_obj = conn->getCameraObject();
- if (cam_pos)
- {
- if (cam_obj)
- {
- MatrixF cam_mtx;
- conn->getControlCameraTransform(0, &cam_mtx);
- cam_mtx.getColumn(3, cam_pos);
- }
- else
- cam_pos->zero();
- }
- return cam_obj;
- }
- U32 afxChoreographer::packUpdate(NetConnection* conn, U32 mask, BitStream* stream)
- {
- U32 retMask = Parent::packUpdate(conn, mask, stream);
-
- if (stream->writeFlag(mask & InitialUpdateMask)) //-- INITIAL UPDATE ?
- {
- stream->write(ranking);
- stream->write(lod);
- stream->write(exec_conds_mask);
- stream->write(choreographer_id);
- // write dynamic fields beginning with arcaneFX::sParameterFieldPrefix
- SimFieldDictionaryIterator itr(getFieldDictionary());
- SimFieldDictionary::Entry* entry;
- U32 prefix_len = dStrlen(arcaneFX::sParameterFieldPrefix);
- if (prefix_len > 0)
- {
- while ((entry = *itr) != NULL)
- {
- if (dStrncmp(entry->slotName, arcaneFX::sParameterFieldPrefix, prefix_len) == 0)
- {
- stream->writeFlag(true);
- stream->writeString(entry->slotName);
- stream->writeLongString(1023, entry->value);
- }
- ++itr;
- }
- }
- stream->writeFlag(false);
- }
- if (stream->writeFlag(mask & TriggerMask))
- {
- stream->write(trigger_mask);
- }
- // CONSTRAINT REMAPPING <<
- if (stream->writeFlag((mask & RemapConstraintMask) && !remapped_cons_defs.empty()))
- {
- remapped_cons_sent = true;
- //Con::errorf("PACKING CONS REMAP %d conn:%d", remapped_cons_defs.size(), (U32) conn);
- stream->write(remapped_cons_defs.size());
- for (S32 i = 0; i < remapped_cons_defs.size(); i++)
- {
- if (remapped_cons_defs[i]->cons_type == OBJECT_CONSTRAINT && remapped_cons_defs[i]->cons_obj.object != NULL)
- {
- //Con::errorf("PACKING CONS REMAP: name %s", remapped_cons_defs[i]->cons_name);
- stream->writeString(remapped_cons_defs[i]->cons_name);
- //Con::errorf("PACKING CONS REMAP: type %d", remapped_cons_defs[i]->cons_type);
- stream->write(remapped_cons_defs[i]->cons_type);
- SceneObject* object = remapped_cons_defs[i]->cons_obj.object;
- S32 ghost_idx = conn->getGhostIndex(object);
- //Con::errorf("PACKING CONS REMAP: ghost %d", ghost_idx);
- if (stream->writeFlag(ghost_idx != -1))
- {
- stream->writeRangedU32(U32(ghost_idx), 0, NetConnection::MaxGhostCount);
- }
- else
- {
- if (stream->writeFlag(object->getScopeId() > 0))
- {
- stream->writeInt(object->getScopeId(), NetObject::SCOPE_ID_BITS);
- stream->writeFlag(dynamic_cast<ShapeBase*>(object) != NULL);
- }
- }
- }
- else if (remapped_cons_defs[i]->cons_type == POINT_CONSTRAINT && remapped_cons_defs[i]->cons_obj.point != NULL)
- {
- stream->writeString(remapped_cons_defs[i]->cons_name);
- stream->write(remapped_cons_defs[i]->cons_type);
- mathWrite(*stream, *remapped_cons_defs[i]->cons_obj.point);
- }
- else if (remapped_cons_defs[i]->cons_type == TRANSFORM_CONSTRAINT && remapped_cons_defs[i]->cons_obj.xfm != NULL)
- {
- stream->writeString(remapped_cons_defs[i]->cons_name);
- stream->write(remapped_cons_defs[i]->cons_type);
- mathWrite(*stream, *remapped_cons_defs[i]->cons_obj.xfm);
- }
- }
- }
- // CONSTRAINT REMAPPING >>
- AssertISV(stream->isValid(), "afxChoreographer::packUpdate(): write failure occurred, possibly caused by packet-size overrun.");
- return retMask;
- }
- void afxChoreographer::unpackUpdate(NetConnection * conn, BitStream * stream)
- {
- Parent::unpackUpdate(conn, stream);
-
- // InitialUpdate Only
- if (stream->readFlag())
- {
- stream->read(&ranking);
- stream->read(&lod);
- stream->read(&exec_conds_mask);
- stream->read(&choreographer_id);
- // read dynamic fields
- while(stream->readFlag())
- {
- char slotName[256];
- char value[1024];
- stream->readString(slotName);
- stream->readLongString(1023, value);
- setDataField(StringTable->insert(slotName), 0, value);
- }
- arcaneFX::registerClientChoreographer(this);
- }
- if (stream->readFlag()) // TriggerMask
- {
- stream->read(&trigger_mask);
- }
- // CONSTRAINT REMAPPING <<
- if (stream->readFlag()) // RemapConstraintMask
- {
- S32 n_defs;
- stream->read(&n_defs);
- for (S32 i = 0; i < n_defs; i++)
- {
- StringTableEntry cons_name = stream->readSTString();
- U8 cons_type; stream->read(&cons_type);
- if (cons_type == OBJECT_CONSTRAINT)
- {
- SceneObject* scn_obj = NULL;
- if (stream->readFlag())
- {
- S32 ghost_idx = stream->readRangedU32(0, NetConnection::MaxGhostCount);
- scn_obj = dynamic_cast<SceneObject*>(conn->resolveGhost(ghost_idx));
- if (scn_obj)
- {
- remapObjectConstraint(scn_obj, cons_name);
- }
- else
- Con::errorf("CANNOT RESOLVE GHOST %d %s", ghost_idx, cons_name);
- }
- else
- {
- if (stream->readFlag())
- {
- U16 scope_id = stream->readInt(NetObject::SCOPE_ID_BITS);
- bool is_shape = stream->readFlag();
- remapObjectConstraint(scope_id, cons_name, is_shape);
- }
- }
- }
- else if (cons_type == POINT_CONSTRAINT)
- {
- Point3F point;
- mathRead(*stream, &point);
- remapPointConstraint(point, cons_name);
- }
- else if (cons_type == TRANSFORM_CONSTRAINT)
- {
- MatrixF xfm;
- mathRead(*stream, &xfm);
- remapTransformConstraint(xfm, cons_name);
- }
- }
- }
- // CONSTRAINT REMAPPING >>
- }
- void afxChoreographer::executeScriptEvent(const char* method, afxConstraint* cons,
- const MatrixF& xfm, const char* data)
- {
- SceneObject* cons_obj = (cons) ? cons->getSceneObject() : NULL;
- char *arg_buf = Con::getArgBuffer(256);
- Point3F pos;
- xfm.getColumn(3,&pos);
- AngAxisF aa(xfm);
- dSprintf(arg_buf,256,"%g %g %g %g %g %g %g",
- pos.x, pos.y, pos.z,
- aa.axis.x, aa.axis.y, aa.axis.z, aa.angle);
- // CALL SCRIPT afxChoreographerData::method(%choreographer, %constraint, %transform, %data)
- Con::executef(exeblock, method,
- getIdString(),
- (cons_obj) ? cons_obj->getIdString() : "",
- arg_buf,
- data);
- }
- void afxChoreographer::addObjectConstraint(SceneObject* object, const char* cons_name)
- {
- if (!object || !cons_name)
- return;
- dynConstraintDef dyn_def;
- dyn_def.cons_name = StringTable->insert(cons_name);
- dyn_def.cons_type = OBJECT_CONSTRAINT;
- dyn_def.cons_obj.object = object;
- dyn_cons_defs->push_back(dyn_def);
- #if defined(AFX_CAP_SCOPE_TRACKING)
- if (isServerObject() && object->isScopeable())
- constraint_mgr->addScopeableObject(object);
- #endif
- constraint_mgr->defineConstraint(OBJECT_CONSTRAINT, dyn_def.cons_name);
- deleteNotify(object);
- }
- void afxChoreographer::addObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape)
- {
- if (!cons_name)
- return;
- dynConstraintDef dyn_def;
- dyn_def.cons_name = StringTable->insert(cons_name);
- dyn_def.cons_type = (is_shape) ? OBJECT_CONSTRAINT_SANS_SHAPE : OBJECT_CONSTRAINT_SANS_OBJ;
- dyn_def.cons_obj.scope_id = scope_id;
- dyn_cons_defs->push_back(dyn_def);
- constraint_mgr->defineConstraint(OBJECT_CONSTRAINT, dyn_def.cons_name);
- }
- void afxChoreographer::addPointConstraint(Point3F& point, const char* cons_name)
- {
- dynConstraintDef dyn_def;
- dyn_def.cons_name = StringTable->insert(cons_name);
- dyn_def.cons_type = POINT_CONSTRAINT;
- dyn_def.cons_obj.point = new Point3F(point);
- dyn_cons_defs->push_back(dyn_def);
- constraint_mgr->defineConstraint(POINT_CONSTRAINT, dyn_def.cons_name);
- }
- void afxChoreographer::addTransformConstraint(MatrixF& xfm, const char* cons_name)
- {
- dynConstraintDef dyn_def;
- dyn_def.cons_name = StringTable->insert(cons_name);
- dyn_def.cons_type = TRANSFORM_CONSTRAINT;
- dyn_def.cons_obj.xfm = new MatrixF(xfm);
- dyn_cons_defs->push_back(dyn_def);
- constraint_mgr->defineConstraint(TRANSFORM_CONSTRAINT, dyn_def.cons_name);
- }
- // CONSTRAINT REMAPPING <<
- static inline U32 resolve_cons_spec(const char* source_spec, Point3F& pos, MatrixF& xfm, SceneObject** scn_obj)
- {
- AngAxisF aa;
- S32 args_n = dSscanf(source_spec, "%g %g %g %g %g %g %g",
- &pos.x, &pos.y, &pos.z,
- &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle);
- // TRANSFORM CONSTRAINT SRC
- if (args_n == 7)
- {
- aa.setMatrix(&xfm);
- xfm.setColumn(3,pos);
- return afxEffectDefs::TRANSFORM_CONSTRAINT;
- }
- // POINT CONSTRAINT SRC
- if (args_n == 3)
- {
- return afxEffectDefs::POINT_CONSTRAINT;
- }
- SimObject* cons_sim_obj = Sim::findObject(source_spec);
- *scn_obj = dynamic_cast<SceneObject*>(cons_sim_obj);
- if (*scn_obj)
- {
- return afxEffectDefs::OBJECT_CONSTRAINT;
- }
- return afxEffectDefs::UNDEFINED_CONSTRAINT_TYPE;
- }
- // CONSTRAINT REMAPPING >>
- bool afxChoreographer::addConstraint(const char* source_spec, const char* cons_name)
- {
- VectorF pos;
- MatrixF xfm;
- SceneObject* scn_obj;
- switch (resolve_cons_spec(source_spec, pos, xfm, &scn_obj))
- {
- case TRANSFORM_CONSTRAINT:
- addTransformConstraint(xfm, cons_name);
- return true;
- case POINT_CONSTRAINT:
- addPointConstraint(pos, cons_name);
- return true;
- case OBJECT_CONSTRAINT:
- addObjectConstraint(scn_obj, cons_name);
- return true;
- }
- return false;
- }
- void afxChoreographer::addNamedEffect(afxEffectWrapper* ew)
- {
- named_effects.addObject(ew);
- }
- void afxChoreographer::removeNamedEffect(afxEffectWrapper* ew)
- {
- named_effects.removeObject(ew);
- }
- afxEffectWrapper* afxChoreographer::findNamedEffect(StringTableEntry name)
- {
- return (afxEffectWrapper*) named_effects.findObject(name);
- }
- void afxChoreographer::setGhostConstraintObject(SceneObject* obj, StringTableEntry cons_name)
- {
- if (constraint_mgr)
- constraint_mgr->setReferenceObject(cons_name, obj);
- }
- void afxChoreographer::restoreScopedObject(SceneObject* obj)
- {
- constraint_mgr->restoreScopedObject(obj, this);
- constraint_mgr->adjustProcessOrdering(this);
- }
- void afxChoreographer::addExplicitClient(NetConnection* conn)
- {
- if (!conn)
- return;
- for (S32 i = 0; i < explicit_clients.size(); i++)
- {
- if (explicit_clients[i] == conn)
- return;
- }
- explicit_clients.push_back(conn);
- deleteNotify(conn);
- }
- void afxChoreographer::removeExplicitClient(NetConnection* conn)
- {
- if (!conn)
- return;
- for (S32 i = 0; i < explicit_clients.size(); i++)
- {
- if (explicit_clients[i] == conn)
- {
- clearNotify(conn);
- explicit_clients.erase_fast(i);
- return;
- }
- }
- }
- void afxChoreographer::postProcessAfterObject(GameBase* obj)
- {
- proc_after_obj = obj;
- }
- void afxChoreographer::setTriggerMask(U32 mask)
- {
- if (mask != trigger_mask)
- {
- trigger_mask = mask;
- setMaskBits(TriggerMask);
- }
- }
- afxParticlePool* afxChoreographer::findParticlePool(afxParticlePoolData* key_block, U32 key_index)
- {
- for (S32 i = 0; i < particle_pools.size(); i++)
- if (particle_pools[i] && particle_pools[i]->hasMatchingKeyBlock(key_block, key_index))
- return particle_pools[i];
- return 0;
- }
- void afxChoreographer::registerParticlePool(afxParticlePool* pool)
- {
- particle_pools.push_back(pool);
- }
- void afxChoreographer::unregisterParticlePool(afxParticlePool* pool)
- {
- for (S32 i = 0; i < particle_pools.size(); i++)
- if (particle_pools[i] == pool)
- {
- particle_pools.erase_fast(i);
- return;
- }
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- DefineEngineMethod( afxChoreographer, setRanking, void, ( U32 ranking ),,
- "Set a ranking value (0-255) for the choreographer.\n" )
- {
- object->setRanking((U8)ranking);
- }
- DefineEngineMethod( afxChoreographer, setLevelOfDetail, void, ( U32 lod ),,
- "Set a level-of-detail value (0-255) for the choreographer.\n" )
- {
- object->setLevelOfDetail((U8)lod);
- }
- DefineEngineMethod( afxChoreographer, setExecConditions, void, ( U32 mask ),,
- "Set a bitmask to specifiy the state of exec-conditions.\n" )
- {
- object->setExecConditions(afxChoreographer::USER_EXEC_CONDS_MASK & mask);
- }
- DefineEngineMethod( afxChoreographer, addConstraint, void, ( const char* source, const char* name),,
- "Add a dynamic constraint consistiing of a source and name. The source can be a SceneObject, a 3-valued position, or a 7-valued transform.\n" )
- {
- if (!object->addConstraint(source, name))
- Con::errorf("afxChoreographer::addConstraint() -- failed to resolve constraint source [%s].", source);
- }
- DefineEngineMethod( afxChoreographer, addExplicitClient, void, ( NetConnection* client ),,
- "Add an explicit client.\n" )
- {
- if (!client)
- {
- Con::errorf(ConsoleLogEntry::General, "afxChoreographer::addExplicitClient: Failed to resolve client connection");
- return;
- }
- object->addExplicitClient(client);
- }
- DefineEngineMethod( afxChoreographer, setTriggerBit, void, ( U32 bit_num ),,
- "Set a bit of the trigger-mask.\n" )
- {
- U32 set_bit = 1 << bit_num;
- object->setTriggerMask(set_bit | object->getTriggerMask());
- }
- DefineEngineMethod( afxChoreographer, clearTriggerBit, void, ( U32 bit_num ),,
- "Unset a bit of the trigger-mask.\n" )
- {
- U32 clear_bit = 1 << bit_num;
- object->setTriggerMask(~clear_bit & object->getTriggerMask());
- }
- DefineEngineMethod( afxChoreographer, testTriggerBit, bool, ( U32 bit_num ),,
- "Test state of a trigger-mask bit.\n" )
- {
- U32 test_bit = 1 << bit_num;
- return ((test_bit & object->getTriggerMask()) != 0);
- }
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // CONSTRAINT REMAPPING <<
- void afxChoreographer::remapObjectConstraint(SceneObject* object, const char* cons_name)
- {
- if (!object || !cons_name)
- return;
- // must be a constraint-def with a matching name in the list
- dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name);
- if (!dyn_def)
- {
- Con::errorf("afxChoreographer::remapObjectConstraint() -- failed to find constraint name [%s].", cons_name);
- return;
- }
- // constraint-def must have matching name constraint-type
- if (dyn_def->cons_type != OBJECT_CONSTRAINT)
- {
- Con::errorf("afxChoreographer::remapObjectConstraint() -- remapped contraint type does not match existing constraint type.");
- return;
- }
- // nothing to do if new object is same as old
- if (dyn_def->cons_obj.object == object)
- {
- #ifdef TORQUE_DEBUG
- Con::warnf("afxChoreographer::remapObjectConstraint() -- remapped contraint object is same as existing object.");
- #endif
- return;
- }
- dyn_def->cons_obj.object = object;
- deleteNotify(object);
- constraint_mgr->setReferenceObject(StringTable->insert(cons_name), object);
- #if defined(AFX_CAP_SCOPE_TRACKING)
- if (isServerObject() && object->isScopeable())
- constraint_mgr->addScopeableObject(object);
- #endif
- if (isServerObject())
- {
- if (remapped_cons_sent)
- {
- remapped_cons_defs.clear();
- remapped_cons_sent = false;
- }
- remapped_cons_defs.push_back(dyn_def);
- setMaskBits(RemapConstraintMask);
- }
- }
- void afxChoreographer::remapObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape)
- {
- if (!cons_name)
- return;
- // must be a constraint-def with a matching name in the list
- dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name);
- if (!dyn_def)
- {
- Con::errorf("afxChoreographer::remapObjectConstraint() -- failed to find constraint name [%s].", cons_name);
- return;
- }
- // constraint-def must have matching name constraint-type
- if (dyn_def->cons_type != OBJECT_CONSTRAINT)
- {
- Con::errorf("afxChoreographer::remapObjectConstraint() -- remapped contraint type does not match existing constraint type.");
- return;
- }
- constraint_mgr->setReferenceObjectByScopeId(StringTable->insert(cons_name), scope_id, is_shape);
- }
- void afxChoreographer::remapPointConstraint(Point3F& point, const char* cons_name)
- {
- // must be a constraint-def with a matching name in the list
- dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name);
- if (!dyn_def)
- {
- Con::errorf("afxChoreographer::remapPointConstraint() -- failed to find constraint name [%s].", cons_name);
- return;
- }
- // constraint-def must have matching name constraint-type
- if (dyn_def->cons_type != POINT_CONSTRAINT)
- {
- Con::errorf("afxChoreographer::remapPointConstraint() -- remapped contraint type does not match existing constraint type.");
- return;
- }
- *dyn_def->cons_obj.point = point;
- constraint_mgr->setReferencePoint(StringTable->insert(cons_name), point);
- if (isServerObject())
- {
- if (remapped_cons_sent)
- {
- remapped_cons_defs.clear();
- remapped_cons_sent = false;
- }
- remapped_cons_defs.push_back(dyn_def);
- setMaskBits(RemapConstraintMask);
- }
- }
- void afxChoreographer::remapTransformConstraint(MatrixF& xfm, const char* cons_name)
- {
- // must be a constraint-def with a matching name in the list
- dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name);
- if (!dyn_def)
- {
- Con::errorf("afxChoreographer::remapTransformConstraint() -- failed to find constraint name [%s].", cons_name);
- return;
- }
- // constraint-def must have matching name constraint-type
- if (dyn_def->cons_type != POINT_CONSTRAINT)
- {
- Con::errorf("afxChoreographer::remapTransformConstraint() -- remapped contraint type does not match existing constraint type.");
- return;
- }
- *dyn_def->cons_obj.xfm = xfm;
- constraint_mgr->setReferenceTransform(StringTable->insert(cons_name), xfm);
- if (isServerObject())
- {
- if (remapped_cons_sent)
- {
- remapped_cons_defs.clear();
- remapped_cons_sent = false;
- }
- remapped_cons_defs.push_back(dyn_def);
- setMaskBits(RemapConstraintMask);
- }
- }
- bool afxChoreographer::remapConstraint(const char* source_spec, const char* cons_name)
- {
- SceneObject* scn_obj;
- Point3F pos;
- MatrixF xfm;
- switch (resolve_cons_spec(source_spec, pos, xfm, &scn_obj))
- {
- case TRANSFORM_CONSTRAINT:
- //addTransformConstraint(xfm, cons_name);
- return true;
- case POINT_CONSTRAINT:
- //addPointConstraint(pos, cons_name);
- return true;
- case OBJECT_CONSTRAINT:
- remapObjectConstraint(scn_obj, cons_name);
- return true;
- }
- return false;
- }
- DefineEngineMethod( afxChoreographer, remapConstraint, void, ( const char* source, const char* name),,
- "Remap a dynamic constraint to use a new source. The source can be a SceneObject, a 3-valued position, or a 7-valued transform. but must match type of existing source.\n" )
- {
- if (!object->remapConstraint(source, name))
- Con::errorf("afxChoreographer::remapConstraint() -- failed to resolve constraint source [%s].", source);
- }
- // CONSTRAINT REMAPPING >>
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|