afxChoreographer.cpp
Engine/source/afx/afxChoreographer.cpp
Public Defines
define
myOffset(field) (field, )
Public Functions
ConsoleDocClass(afxChoreographer , "@brief Base class used by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographers.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxChoreographers\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxChoreographerData , "@brief Datablock base class used by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographers.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxChoreographers\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>" )
DefineEngineMethod(afxChoreographer , addConstraint , void , (const char *source, const char *name) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic constraint consistiing of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> and name. The <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> can be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SceneObject, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3-valued position, or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 7-valued <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transform.\n</a>" )
DefineEngineMethod(afxChoreographer , addExplicitClient , void , (NetConnection *client) , "Add an explicit <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" )
DefineEngineMethod(afxChoreographer , clearTriggerBit , void , (U32 bit_num) , "Unset <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bit of the trigger-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mask.\n</a>" )
DefineEngineMethod(afxChoreographer , remapConstraint , void , (const char *source, const char *name) , "Remap <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic constraint <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> source. The <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> can be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SceneObject, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3-valued position, or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 7-valued transform. but must match type of existing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">source.\n</a>" )
DefineEngineMethod(afxChoreographer , setExecConditions , void , (U32 mask) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bitmask <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specifiy the state of exec-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">conditions.\n</a>" )
DefineEngineMethod(afxChoreographer , setLevelOfDetail , void , (U32 lod) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> level-of-detail <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> (0-255) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographer.\n</a>" )
DefineEngineMethod(afxChoreographer , setRanking , void , (U32 ranking) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ranking <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> (0-255) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographer.\n</a>" )
DefineEngineMethod(afxChoreographer , setTriggerBit , void , (U32 bit_num) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bit of the trigger-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mask.\n</a>" )
DefineEngineMethod(afxChoreographer , testTriggerBit , bool , (U32 bit_num) , "Test state of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> trigger-mask <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bit.\n</a>" )
resolve_cons_spec(const char * source_spec, Point3F & pos, MatrixF & xfm, SceneObject ** scn_obj)
Detailed Description
Public Defines
myOffset(field) (field, )
Public Functions
ConsoleDocClass(afxChoreographer , "@brief Base class used by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographers.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxChoreographers\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxChoreographerData , "@brief Datablock base class used by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographers.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxChoreographers\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>" )
DefineEngineMethod(afxChoreographer , addConstraint , void , (const char *source, const char *name) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic constraint consistiing of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> and name. The <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> can be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SceneObject, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3-valued position, or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 7-valued <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transform.\n</a>" )
DefineEngineMethod(afxChoreographer , addExplicitClient , void , (NetConnection *client) , "Add an explicit <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" )
DefineEngineMethod(afxChoreographer , clearTriggerBit , void , (U32 bit_num) , "Unset <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bit of the trigger-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mask.\n</a>" )
DefineEngineMethod(afxChoreographer , remapConstraint , void , (const char *source, const char *name) , "Remap <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> dynamic constraint <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> source. The <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> can be <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> SceneObject, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3-valued position, or <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 7-valued transform. but must match type of existing <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">source.\n</a>" )
DefineEngineMethod(afxChoreographer , setExecConditions , void , (U32 mask) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bitmask <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> specifiy the state of exec-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">conditions.\n</a>" )
DefineEngineMethod(afxChoreographer , setLevelOfDetail , void , (U32 lod) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> level-of-detail <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> (0-255) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographer.\n</a>" )
DefineEngineMethod(afxChoreographer , setRanking , void , (U32 ranking) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ranking <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> (0-255) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">choreographer.\n</a>" )
DefineEngineMethod(afxChoreographer , setTriggerBit , void , (U32 bit_num) , "Set <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> bit of the trigger-<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mask.\n</a>" )
DefineEngineMethod(afxChoreographer , testTriggerBit , bool , (U32 bit_num) , "Test state of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> trigger-mask <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bit.\n</a>" )
IMPLEMENT_CO_DATABLOCK_V1(afxChoreographer )
IMPLEMENT_CO_DATABLOCK_V1(afxChoreographerData )
resolve_cons_spec(const char * source_spec, Point3F & pos, MatrixF & xfm, SceneObject ** scn_obj)
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 "console/engineAPI.h" 30#include "T3D/gameBase/gameConnection.h" 31#include "math/mathIO.h" 32#include "console/compiler.h" 33 34#include "afx/afxConstraint.h" 35#include "afx/afxChoreographer.h" 36#include "afx/afxEffectWrapper.h" 37#include "afx/util/afxParticlePool.h" 38#include "afx/forces/afxForceSet.h" 39 40//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 41 42IMPLEMENT_CO_DATABLOCK_V1(afxChoreographerData); 43 44ConsoleDocClass( afxChoreographerData, 45 "@brief Datablock base class used by choreographers.\n\n" 46 47 "@ingroup afxChoreographers\n" 48 "@ingroup AFX\n" 49 "@ingroup Datablocks\n" 50); 51 52afxChoreographerData::afxChoreographerData() 53{ 54 exec_on_new_clients = false; 55 echo_packet_usage = 100; 56 client_script_file = ST_NULLSTRING; 57 client_init_func = ST_NULLSTRING; 58} 59 60afxChoreographerData::afxChoreographerData(const afxChoreographerData& other, bool temp_clone) : GameBaseData(other, temp_clone) 61{ 62 exec_on_new_clients = other.exec_on_new_clients; 63 echo_packet_usage = other.echo_packet_usage; 64 client_script_file = other.client_script_file; 65 client_init_func = other.client_init_func; 66} 67 68#define myOffset(field) Offset(field, afxChoreographerData) 69 70void afxChoreographerData::initPersistFields() 71{ 72 addField("execOnNewClients", TypeBool, myOffset(exec_on_new_clients), 73 "..."); 74 addField("echoPacketUsage", TypeS8, myOffset(echo_packet_usage), 75 "..."); 76 addField("clientScriptFile", TypeFilename, myOffset(client_script_file), 77 "..."); 78 addField("clientInitFunction", TypeString, myOffset(client_init_func), 79 "..."); 80 81 Parent::initPersistFields(); 82} 83 84void afxChoreographerData::packData(BitStream* stream) 85{ 86 Parent::packData(stream); 87 88 stream->write(exec_on_new_clients); 89 stream->write(echo_packet_usage); 90 stream->writeString(client_script_file); 91 stream->writeString(client_init_func); 92} 93 94void afxChoreographerData::unpackData(BitStream* stream) 95{ 96 Parent::unpackData(stream); 97 98 stream->read(&exec_on_new_clients); 99 stream->read(&echo_packet_usage); 100 client_script_file = stream->readSTString(); 101 client_init_func = stream->readSTString(); 102} 103 104bool afxChoreographerData::preload(bool server, String &errorStr) 105{ 106 if (!Parent::preload(server, errorStr)) 107 return false; 108 109 if (!server && client_script_file != ST_NULLSTRING) 110 { 111 Compiler::gSyntaxError = false; 112 Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0); 113 if (Compiler::gSyntaxError) 114 { 115 Con::errorf("afxChoreographerData: failed to exec clientScriptFile \"%s\" -- syntax error", client_script_file); 116 Compiler::gSyntaxError = false; 117 } 118 } 119 120 return true; 121} 122 123//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 124 125IMPLEMENT_CO_DATABLOCK_V1(afxChoreographer); 126 127ConsoleDocClass( afxChoreographer, 128 "@brief Base class used by choreographers.\n\n" 129 130 "@ingroup afxChoreographers\n" 131 "@ingroup AFX\n" 132); 133 134afxChoreographer::afxChoreographer() 135{ 136 datablock = 0; // datablock initializer (union these?) 137 exeblock = 0; // object to use in executef callouts 138 139 // create the constraint manager 140 constraint_mgr = new afxConstraintMgr(); 141 142 ranking = 0; 143 lod = 0; 144 exec_conds_mask = 0; 145 choreographer_id = 0; 146 mExtra = 0; 147 started_with_newop = false; 148 postpone_activation = false; 149 remapped_cons_sent = false; // CONSTRAINT REMAPPING 150 151 dyn_cons_defs = &dc_defs_a; 152 dyn_cons_defs2 = &dc_defs_b; 153 154 proc_after_obj = 0; 155 trigger_mask = 0; 156 157 force_set_mgr = 0; 158 159 mOrderGUID = 0x0FFFFFFF; 160} 161 162afxChoreographer::~afxChoreographer() 163{ 164 explicit_clients.clear(); 165 166 for (S32 i = 0; i < dyn_cons_defs->size(); i++) 167 { 168 if ((*dyn_cons_defs)[i].cons_type == POINT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.point != NULL) 169 delete (*dyn_cons_defs)[i].cons_obj.point; 170 else if ((*dyn_cons_defs)[i].cons_type == TRANSFORM_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.xfm != NULL) 171 delete (*dyn_cons_defs)[i].cons_obj.xfm; 172 } 173 174 constraint_mgr->clearAllScopeableObjs(); 175 delete constraint_mgr; 176 177 delete force_set_mgr; 178} 179 180void afxChoreographer::initPersistFields() 181{ 182 // conditionals 183 addField("extra", TYPEID<SimObject>(), Offset(mExtra, afxChoreographer), 184 "..."); 185 addField("postponeActivation", TypeBool, Offset(postpone_activation, afxChoreographer), 186 "..."); 187 188 Parent::initPersistFields(); 189} 190 191bool afxChoreographer::onAdd() 192{ 193 if (!Parent::onAdd()) 194 return(false); 195 196 if (isServerObject()) 197 choreographer_id = arcaneFX::registerChoreographer(this); 198 else 199 { 200 if (proc_after_obj) 201 { 202 processAfter(proc_after_obj); 203 proc_after_obj = 0; 204 } 205 206 force_set_mgr = new afxForceSetMgr(); 207 208 if (datablock && datablock->client_init_func != ST_NULLSTRING) 209 Con::executef(datablock->client_init_func, getIdString()); 210 } 211 212 return(true); 213} 214 215void afxChoreographer::onRemove() 216{ 217 for (S32 i = 0; i < particle_pools.size(); i++) 218 if (particle_pools[i]) 219 particle_pools[i]->setChoreographer(0); 220 particle_pools.clear(); 221 222 if (isServerObject()) 223 arcaneFX::unregisterChoreographer(this); 224 else 225 arcaneFX::unregisterClientChoreographer(this); 226 227 choreographer_id = 0; 228 Parent::onRemove(); 229} 230 231void afxChoreographer::onDeleteNotify(SimObject* obj) 232{ 233 if (dynamic_cast<SceneObject*>(obj)) 234 { 235 SceneObject* scn_obj = (SceneObject*)(obj); 236 for (S32 i = 0; i < dyn_cons_defs->size(); i++) 237 if ((*dyn_cons_defs)[i].cons_type != OBJECT_CONSTRAINT || (*dyn_cons_defs)[i].cons_obj.object != scn_obj) 238 dyn_cons_defs2->push_back((*dyn_cons_defs)[i]); 239 240 Vector<dynConstraintDef>* tmp = dyn_cons_defs; 241 dyn_cons_defs = dyn_cons_defs2; 242 dyn_cons_defs2 = tmp; 243 dyn_cons_defs2->clear(); 244 245 if (isServerObject() && scn_obj->isScopeable()) 246 constraint_mgr->removeScopeableObject(scn_obj); 247 } 248 else if (dynamic_cast<NetConnection*>(obj)) 249 { 250 removeExplicitClient((NetConnection*)obj); 251 } 252 253 Parent::onDeleteNotify(obj); 254} 255 256bool afxChoreographer::onNewDataBlock(GameBaseData* dptr, bool reload) 257{ 258 datablock = dynamic_cast<afxChoreographerData*>(dptr); 259 if (!datablock || !Parent::onNewDataBlock(dptr, reload)) 260 return false; 261 262 exeblock = datablock; 263 264 return true; 265} 266 267void afxChoreographer::pack_constraint_info(NetConnection* conn, BitStream* stream) 268{ 269 stream->write(dyn_cons_defs->size()); 270 for (S32 i = 0; i < dyn_cons_defs->size(); i++) 271 { 272 if ((*dyn_cons_defs)[i].cons_type == OBJECT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.object != NULL) 273 { 274 stream->writeString((*dyn_cons_defs)[i].cons_name); 275 stream->write((*dyn_cons_defs)[i].cons_type); 276 SceneObject* object = (*dyn_cons_defs)[i].cons_obj.object; 277 S32 ghost_idx = conn->getGhostIndex(object); 278 if (stream->writeFlag(ghost_idx != -1)) 279 { 280 stream->writeRangedU32(U32(ghost_idx), 0, NetConnection::MaxGhostCount); 281 } 282 else 283 { 284 if (stream->writeFlag(object->getScopeId() > 0)) 285 { 286 stream->writeInt(object->getScopeId(), NetObject::SCOPE_ID_BITS); 287 stream->writeFlag(dynamic_cast<ShapeBase*>(object) != NULL); 288 } 289 } 290 } 291 else if ((*dyn_cons_defs)[i].cons_type == POINT_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.point != NULL) 292 { 293 stream->writeString((*dyn_cons_defs)[i].cons_name); 294 stream->write((*dyn_cons_defs)[i].cons_type); 295 mathWrite(*stream, *(*dyn_cons_defs)[i].cons_obj.point); 296 } 297 else if ((*dyn_cons_defs)[i].cons_type == TRANSFORM_CONSTRAINT && (*dyn_cons_defs)[i].cons_obj.xfm != NULL) 298 { 299 stream->writeString((*dyn_cons_defs)[i].cons_name); 300 stream->write((*dyn_cons_defs)[i].cons_type); 301 mathWrite(*stream, *(*dyn_cons_defs)[i].cons_obj.xfm); 302 } 303 } 304 305 constraint_mgr->packConstraintNames(conn, stream); 306} 307 308void afxChoreographer::unpack_constraint_info(NetConnection* conn, BitStream* stream) 309{ 310 S32 n_defs; 311 stream->read(&n_defs); 312 dyn_cons_defs->clear(); 313 for (S32 i = 0; i < n_defs; i++) 314 { 315 StringTableEntry cons_name = stream->readSTString(); 316 U8 cons_type; stream->read(&cons_type); 317 if (cons_type == OBJECT_CONSTRAINT) 318 { 319 SceneObject* scn_obj = NULL; 320 if (stream->readFlag()) 321 { 322 S32 ghost_idx = stream->readRangedU32(0, NetConnection::MaxGhostCount); 323 scn_obj = dynamic_cast<SceneObject*>(conn->resolveGhost(ghost_idx)); 324 if (scn_obj) 325 { 326 addObjectConstraint(scn_obj, cons_name); 327 } 328 else 329 Con::errorf("CANNOT RESOLVE GHOST %d %s", ghost_idx, cons_name); 330 } 331 else 332 { 333 if (stream->readFlag()) 334 { 335 mScope_id = stream->readInt(NetObject::SCOPE_ID_BITS); 336 bool is_shape = stream->readFlag(); 337 addObjectConstraint(mScope_id, cons_name, is_shape); 338 } 339 } 340 } 341 else if (cons_type == POINT_CONSTRAINT) 342 { 343 Point3F point; 344 mathRead(*stream, &point); 345 addPointConstraint(point, cons_name); 346 } 347 else if (cons_type == TRANSFORM_CONSTRAINT) 348 { 349 MatrixF xfm; 350 mathRead(*stream, &xfm); 351 addTransformConstraint(xfm, cons_name); 352 } 353 } 354 355 constraint_mgr->unpackConstraintNames(stream); 356} 357 358void afxChoreographer::setup_dynamic_constraints() 359{ 360 for (S32 i = 0; i < dyn_cons_defs->size(); i++) 361 { 362 switch ((*dyn_cons_defs)[i].cons_type) 363 { 364 case OBJECT_CONSTRAINT: 365 constraint_mgr->setReferenceObject((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.object); 366 break; 367 case POINT_CONSTRAINT: 368 constraint_mgr->setReferencePoint((*dyn_cons_defs)[i].cons_name, *(*dyn_cons_defs)[i].cons_obj.point); 369 break; 370 case TRANSFORM_CONSTRAINT: 371 constraint_mgr->setReferenceTransform((*dyn_cons_defs)[i].cons_name, *(*dyn_cons_defs)[i].cons_obj.xfm); 372 break; 373 case OBJECT_CONSTRAINT_SANS_OBJ: 374 constraint_mgr->setReferenceObjectByScopeId((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.scope_id, false); 375 break; 376 case OBJECT_CONSTRAINT_SANS_SHAPE: 377 constraint_mgr->setReferenceObjectByScopeId((*dyn_cons_defs)[i].cons_name, (*dyn_cons_defs)[i].cons_obj.scope_id, true); 378 break; 379 } 380 } 381} 382 383afxChoreographer::dynConstraintDef* afxChoreographer::find_cons_def_by_name(const char* cons_name) 384{ 385 StringTableEntry cons_name_ste = StringTable->insert(cons_name); 386 387 for (S32 i = 0; i < dyn_cons_defs->size(); i++) 388 { 389 if ((*dyn_cons_defs)[i].cons_name == cons_name_ste) 390 return &((*dyn_cons_defs)[i]); 391 } 392 393 return 0; 394} 395 396void afxChoreographer::check_packet_usage(NetConnection* conn, BitStream* stream, S32 mark_stream_pos, const char* msg_tag) 397{ 398 399 S32 packed_size = stream->getCurPos() - mark_stream_pos; 400 S32 current_headroom = stream->getMaxWriteBitNum()-(stream->getStreamSize()<<3); 401 S32 max_headroom = stream->getMaxWriteBitNum()-(conn->getMaxRatePacketSize()<<3); 402 403 if (packed_size > max_headroom) 404 { 405 Con::errorf("%s [%s] WARNING -- packed-bits (%d) > limit (%d) for max PacketSize settings. [%s]", 406 msg_tag, datablock->getName(), packed_size, max_headroom, "PACKET OVERRUN POSSIBLE"); 407 Con::errorf("getMaxRatePacketSize()=%d getCurRatePacketSize()=%d", conn->getMaxRatePacketSize(), conn->getCurRatePacketSize()); 408 } 409 // JTF Note: this current_headroom > 0 check is odd and occurs when object is created real early 410 // in the startup, such as when the dead orc gets fatal damage and we try to post a text effect. 411 else if (packed_size > current_headroom && current_headroom > 0) 412 { 413 Con::errorf("%s [%s] WARNING -- packed-bits (%d) > limit (%d) for current PacketSize settings. [%s]", 414 msg_tag, datablock->getName(), packed_size, current_headroom, "PACKET OVERRUN POSSIBLE"); 415 } 416 else 417 { 418 F32 percentage = 100.0f*((F32)packed_size/(F32)max_headroom); 419 if (percentage >= datablock->echo_packet_usage) 420 { 421 Con::warnf("%s [%s] -- packed-bits (%d) < limit (%d). [%.1f%% full]", msg_tag, datablock->getName(), 422 packed_size, max_headroom, percentage); 423 } 424 } 425} 426 427SceneObject* afxChoreographer::get_camera(Point3F* cam_pos) const 428{ 429 GameConnection* conn = GameConnection::getConnectionToServer(); 430 if (!conn) 431 { 432 if (cam_pos) 433 cam_pos->zero(); 434 return 0; 435 } 436 437 SceneObject* cam_obj = conn->getCameraObject(); 438 if (cam_pos) 439 { 440 if (cam_obj) 441 { 442 MatrixF cam_mtx; 443 conn->getControlCameraTransform(0, &cam_mtx); 444 cam_mtx.getColumn(3, cam_pos); 445 } 446 else 447 cam_pos->zero(); 448 } 449 450 return cam_obj; 451} 452 453U32 afxChoreographer::packUpdate(NetConnection* conn, U32 mask, BitStream* stream) 454{ 455 U32 retMask = Parent::packUpdate(conn, mask, stream); 456 457 if (stream->writeFlag(mask & InitialUpdateMask)) //-- INITIAL UPDATE ? 458 { 459 stream->write(ranking); 460 stream->write(lod); 461 stream->write(exec_conds_mask); 462 stream->write(choreographer_id); 463 464 // write dynamic fields beginning with arcaneFX::sParameterFieldPrefix 465 SimFieldDictionaryIterator itr(getFieldDictionary()); 466 SimFieldDictionary::Entry* entry; 467 U32 prefix_len = dStrlen(arcaneFX::sParameterFieldPrefix); 468 if (prefix_len > 0) 469 { 470 while ((entry = *itr) != NULL) 471 { 472 if (dStrncmp(entry->slotName, arcaneFX::sParameterFieldPrefix, prefix_len) == 0) 473 { 474 stream->writeFlag(true); 475 stream->writeString(entry->slotName); 476 stream->writeLongString(1023, entry->value); 477 } 478 ++itr; 479 } 480 } 481 stream->writeFlag(false); 482 } 483 484 if (stream->writeFlag(mask & TriggerMask)) 485 { 486 stream->write(trigger_mask); 487 } 488 489 // CONSTRAINT REMAPPING << 490 if (stream->writeFlag((mask & RemapConstraintMask) && !remapped_cons_defs.empty())) 491 { 492 remapped_cons_sent = true; 493 //Con::errorf("PACKING CONS REMAP %d conn:%d", remapped_cons_defs.size(), (U32) conn); 494 495 stream->write(remapped_cons_defs.size()); 496 for (S32 i = 0; i < remapped_cons_defs.size(); i++) 497 { 498 if (remapped_cons_defs[i]->cons_type == OBJECT_CONSTRAINT && remapped_cons_defs[i]->cons_obj.object != NULL) 499 { 500 //Con::errorf("PACKING CONS REMAP: name %s", remapped_cons_defs[i]->cons_name); 501 stream->writeString(remapped_cons_defs[i]->cons_name); 502 //Con::errorf("PACKING CONS REMAP: type %d", remapped_cons_defs[i]->cons_type); 503 stream->write(remapped_cons_defs[i]->cons_type); 504 SceneObject* object = remapped_cons_defs[i]->cons_obj.object; 505 S32 ghost_idx = conn->getGhostIndex(object); 506 //Con::errorf("PACKING CONS REMAP: ghost %d", ghost_idx); 507 if (stream->writeFlag(ghost_idx != -1)) 508 { 509 stream->writeRangedU32(U32(ghost_idx), 0, NetConnection::MaxGhostCount); 510 } 511 else 512 { 513 if (stream->writeFlag(object->getScopeId() > 0)) 514 { 515 stream->writeInt(object->getScopeId(), NetObject::SCOPE_ID_BITS); 516 stream->writeFlag(dynamic_cast<ShapeBase*>(object) != NULL); 517 } 518 } 519 } 520 else if (remapped_cons_defs[i]->cons_type == POINT_CONSTRAINT && remapped_cons_defs[i]->cons_obj.point != NULL) 521 { 522 stream->writeString(remapped_cons_defs[i]->cons_name); 523 stream->write(remapped_cons_defs[i]->cons_type); 524 mathWrite(*stream, *remapped_cons_defs[i]->cons_obj.point); 525 } 526 else if (remapped_cons_defs[i]->cons_type == TRANSFORM_CONSTRAINT && remapped_cons_defs[i]->cons_obj.xfm != NULL) 527 { 528 stream->writeString(remapped_cons_defs[i]->cons_name); 529 stream->write(remapped_cons_defs[i]->cons_type); 530 mathWrite(*stream, *remapped_cons_defs[i]->cons_obj.xfm); 531 } 532 } 533 } 534 // CONSTRAINT REMAPPING >> 535 536 AssertISV(stream->isValid(), "afxChoreographer::packUpdate(): write failure occurred, possibly caused by packet-size overrun."); 537 538 return retMask; 539} 540 541void afxChoreographer::unpackUpdate(NetConnection * conn, BitStream * stream) 542{ 543 Parent::unpackUpdate(conn, stream); 544 545 // InitialUpdate Only 546 if (stream->readFlag()) 547 { 548 stream->read(&ranking); 549 stream->read(&lod); 550 stream->read(&exec_conds_mask); 551 stream->read(&choreographer_id); 552 553 // read dynamic fields 554 while(stream->readFlag()) 555 { 556 char slotName[256]; 557 char value[1024]; 558 stream->readString(slotName); 559 stream->readLongString(1023, value); 560 setDataField(StringTable->insert(slotName), 0, value); 561 } 562 563 arcaneFX::registerClientChoreographer(this); 564 } 565 566 if (stream->readFlag()) // TriggerMask 567 { 568 stream->read(&trigger_mask); 569 } 570 571 // CONSTRAINT REMAPPING << 572 if (stream->readFlag()) // RemapConstraintMask 573 { 574 S32 n_defs; 575 stream->read(&n_defs); 576 for (S32 i = 0; i < n_defs; i++) 577 { 578 StringTableEntry cons_name = stream->readSTString(); 579 U8 cons_type; stream->read(&cons_type); 580 if (cons_type == OBJECT_CONSTRAINT) 581 { 582 SceneObject* scn_obj = NULL; 583 if (stream->readFlag()) 584 { 585 S32 ghost_idx = stream->readRangedU32(0, NetConnection::MaxGhostCount); 586 scn_obj = dynamic_cast<SceneObject*>(conn->resolveGhost(ghost_idx)); 587 if (scn_obj) 588 { 589 remapObjectConstraint(scn_obj, cons_name); 590 } 591 else 592 Con::errorf("CANNOT RESOLVE GHOST %d %s", ghost_idx, cons_name); 593 } 594 else 595 { 596 if (stream->readFlag()) 597 { 598 U16 scope_id = stream->readInt(NetObject::SCOPE_ID_BITS); 599 bool is_shape = stream->readFlag(); 600 remapObjectConstraint(scope_id, cons_name, is_shape); 601 } 602 } 603 } 604 else if (cons_type == POINT_CONSTRAINT) 605 { 606 Point3F point; 607 mathRead(*stream, &point); 608 remapPointConstraint(point, cons_name); 609 } 610 else if (cons_type == TRANSFORM_CONSTRAINT) 611 { 612 MatrixF xfm; 613 mathRead(*stream, &xfm); 614 remapTransformConstraint(xfm, cons_name); 615 } 616 } 617 } 618 // CONSTRAINT REMAPPING >> 619} 620 621void afxChoreographer::executeScriptEvent(const char* method, afxConstraint* cons, 622 const MatrixF& xfm, const char* data) 623{ 624 SceneObject* cons_obj = (cons) ? cons->getSceneObject() : NULL; 625 626 char *arg_buf = Con::getArgBuffer(256); 627 Point3F pos; 628 xfm.getColumn(3,&pos); 629 AngAxisF aa(xfm); 630 dSprintf(arg_buf,256,"%g %g %g %g %g %g %g", 631 pos.x, pos.y, pos.z, 632 aa.axis.x, aa.axis.y, aa.axis.z, aa.angle); 633 634 // CALL SCRIPT afxChoreographerData::method(%choreographer, %constraint, %transform, %data) 635 Con::executef(exeblock, method, 636 getIdString(), 637 (cons_obj) ? cons_obj->getIdString() : "", 638 arg_buf, 639 data); 640} 641 642void afxChoreographer::addObjectConstraint(SceneObject* object, const char* cons_name) 643{ 644 if (!object || !cons_name) 645 return; 646 647 dynConstraintDef dyn_def; 648 dyn_def.cons_name = StringTable->insert(cons_name); 649 dyn_def.cons_type = OBJECT_CONSTRAINT; 650 dyn_def.cons_obj.object = object; 651 dyn_cons_defs->push_back(dyn_def); 652 653#if defined(AFX_CAP_SCOPE_TRACKING) 654 if (isServerObject() && object->isScopeable()) 655 constraint_mgr->addScopeableObject(object); 656#endif 657 658 constraint_mgr->defineConstraint(OBJECT_CONSTRAINT, dyn_def.cons_name); 659 deleteNotify(object); 660} 661 662void afxChoreographer::addObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape) 663{ 664 if (!cons_name) 665 return; 666 667 dynConstraintDef dyn_def; 668 dyn_def.cons_name = StringTable->insert(cons_name); 669 dyn_def.cons_type = (is_shape) ? OBJECT_CONSTRAINT_SANS_SHAPE : OBJECT_CONSTRAINT_SANS_OBJ; 670 dyn_def.cons_obj.scope_id = scope_id; 671 dyn_cons_defs->push_back(dyn_def); 672 673 constraint_mgr->defineConstraint(OBJECT_CONSTRAINT, dyn_def.cons_name); 674} 675 676void afxChoreographer::addPointConstraint(Point3F& point, const char* cons_name) 677{ 678 dynConstraintDef dyn_def; 679 dyn_def.cons_name = StringTable->insert(cons_name); 680 dyn_def.cons_type = POINT_CONSTRAINT; 681 dyn_def.cons_obj.point = new Point3F(point); 682 dyn_cons_defs->push_back(dyn_def); 683 684 constraint_mgr->defineConstraint(POINT_CONSTRAINT, dyn_def.cons_name); 685} 686 687void afxChoreographer::addTransformConstraint(MatrixF& xfm, const char* cons_name) 688{ 689 dynConstraintDef dyn_def; 690 dyn_def.cons_name = StringTable->insert(cons_name); 691 dyn_def.cons_type = TRANSFORM_CONSTRAINT; 692 dyn_def.cons_obj.xfm = new MatrixF(xfm); 693 dyn_cons_defs->push_back(dyn_def); 694 695 constraint_mgr->defineConstraint(TRANSFORM_CONSTRAINT, dyn_def.cons_name); 696} 697 698// CONSTRAINT REMAPPING << 699static inline U32 resolve_cons_spec(const char* source_spec, Point3F& pos, MatrixF& xfm, SceneObject** scn_obj) 700{ 701 AngAxisF aa; 702 703 S32 args_n = dSscanf(source_spec, "%g %g %g %g %g %g %g", 704 &pos.x, &pos.y, &pos.z, 705 &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle); 706 707 // TRANSFORM CONSTRAINT SRC 708 if (args_n == 7) 709 { 710 aa.setMatrix(&xfm); 711 xfm.setColumn(3,pos); 712 return afxEffectDefs::TRANSFORM_CONSTRAINT; 713 } 714 715 // POINT CONSTRAINT SRC 716 if (args_n == 3) 717 { 718 return afxEffectDefs::POINT_CONSTRAINT; 719 } 720 721 SimObject* cons_sim_obj = Sim::findObject(source_spec); 722 *scn_obj = dynamic_cast<SceneObject*>(cons_sim_obj); 723 if (*scn_obj) 724 { 725 return afxEffectDefs::OBJECT_CONSTRAINT; 726 } 727 728 return afxEffectDefs::UNDEFINED_CONSTRAINT_TYPE; 729} 730// CONSTRAINT REMAPPING >> 731 732bool afxChoreographer::addConstraint(const char* source_spec, const char* cons_name) 733{ 734 VectorF pos; 735 MatrixF xfm; 736 SceneObject* scn_obj; 737 738 switch (resolve_cons_spec(source_spec, pos, xfm, &scn_obj)) 739 { 740 case TRANSFORM_CONSTRAINT: 741 addTransformConstraint(xfm, cons_name); 742 return true; 743 case POINT_CONSTRAINT: 744 addPointConstraint(pos, cons_name); 745 return true; 746 case OBJECT_CONSTRAINT: 747 addObjectConstraint(scn_obj, cons_name); 748 return true; 749 } 750 751 return false; 752} 753 754void afxChoreographer::addNamedEffect(afxEffectWrapper* ew) 755{ 756 named_effects.addObject(ew); 757} 758 759void afxChoreographer::removeNamedEffect(afxEffectWrapper* ew) 760{ 761 named_effects.removeObject(ew); 762} 763 764afxEffectWrapper* afxChoreographer::findNamedEffect(StringTableEntry name) 765{ 766 return (afxEffectWrapper*) named_effects.findObject(name); 767} 768 769void afxChoreographer::setGhostConstraintObject(SceneObject* obj, StringTableEntry cons_name) 770{ 771 if (constraint_mgr) 772 constraint_mgr->setReferenceObject(cons_name, obj); 773} 774 775void afxChoreographer::restoreScopedObject(SceneObject* obj) 776{ 777 constraint_mgr->restoreScopedObject(obj, this); 778 constraint_mgr->adjustProcessOrdering(this); 779} 780 781void afxChoreographer::addExplicitClient(NetConnection* conn) 782{ 783 if (!conn) 784 return; 785 786 for (S32 i = 0; i < explicit_clients.size(); i++) 787 { 788 if (explicit_clients[i] == conn) 789 return; 790 } 791 792 explicit_clients.push_back(conn); 793 deleteNotify(conn); 794} 795 796void afxChoreographer::removeExplicitClient(NetConnection* conn) 797{ 798 if (!conn) 799 return; 800 801 for (S32 i = 0; i < explicit_clients.size(); i++) 802 { 803 if (explicit_clients[i] == conn) 804 { 805 clearNotify(conn); 806 explicit_clients.erase_fast(i); 807 return; 808 } 809 } 810} 811 812void afxChoreographer::postProcessAfterObject(GameBase* obj) 813{ 814 proc_after_obj = obj; 815} 816 817void afxChoreographer::setTriggerMask(U32 mask) 818{ 819 if (mask != trigger_mask) 820 { 821 trigger_mask = mask; 822 setMaskBits(TriggerMask); 823 } 824} 825 826afxParticlePool* afxChoreographer::findParticlePool(afxParticlePoolData* key_block, U32 key_index) 827{ 828 for (S32 i = 0; i < particle_pools.size(); i++) 829 if (particle_pools[i] && particle_pools[i]->hasMatchingKeyBlock(key_block, key_index)) 830 return particle_pools[i]; 831 832 return 0; 833} 834 835void afxChoreographer::registerParticlePool(afxParticlePool* pool) 836{ 837 particle_pools.push_back(pool); 838} 839 840void afxChoreographer::unregisterParticlePool(afxParticlePool* pool) 841{ 842 for (S32 i = 0; i < particle_pools.size(); i++) 843 if (particle_pools[i] == pool) 844 { 845 particle_pools.erase_fast(i); 846 return; 847 } 848} 849 850//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 851 852DefineEngineMethod( afxChoreographer, setRanking, void, ( U32 ranking ),, 853 "Set a ranking value (0-255) for the choreographer.\n" ) 854{ 855 object->setRanking((U8)ranking); 856} 857 858DefineEngineMethod( afxChoreographer, setLevelOfDetail, void, ( U32 lod ),, 859 "Set a level-of-detail value (0-255) for the choreographer.\n" ) 860{ 861 object->setLevelOfDetail((U8)lod); 862} 863 864DefineEngineMethod( afxChoreographer, setExecConditions, void, ( U32 mask ),, 865 "Set a bitmask to specifiy the state of exec-conditions.\n" ) 866{ 867 object->setExecConditions(afxChoreographer::USER_EXEC_CONDS_MASK & mask); 868} 869 870DefineEngineMethod( afxChoreographer, addConstraint, void, ( const char* source, const char* name),, 871 "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" ) 872{ 873 if (!object->addConstraint(source, name)) 874 Con::errorf("afxChoreographer::addConstraint() -- failed to resolve constraint source [%s].", source); 875} 876 877DefineEngineMethod( afxChoreographer, addExplicitClient, void, ( NetConnection* client ),, 878 "Add an explicit client.\n" ) 879{ 880 if (!client) 881 { 882 Con::errorf(ConsoleLogEntry::General, "afxChoreographer::addExplicitClient: Failed to resolve client connection"); 883 return; 884 } 885 886 object->addExplicitClient(client); 887} 888 889DefineEngineMethod( afxChoreographer, setTriggerBit, void, ( U32 bit_num ),, 890 "Set a bit of the trigger-mask.\n" ) 891{ 892 U32 set_bit = 1 << bit_num; 893 object->setTriggerMask(set_bit | object->getTriggerMask()); 894} 895 896DefineEngineMethod( afxChoreographer, clearTriggerBit, void, ( U32 bit_num ),, 897 "Unset a bit of the trigger-mask.\n" ) 898{ 899 U32 clear_bit = 1 << bit_num; 900 object->setTriggerMask(~clear_bit & object->getTriggerMask()); 901} 902 903DefineEngineMethod( afxChoreographer, testTriggerBit, bool, ( U32 bit_num ),, 904 "Test state of a trigger-mask bit.\n" ) 905{ 906 U32 test_bit = 1 << bit_num; 907 return ((test_bit & object->getTriggerMask()) != 0); 908} 909 910//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 911 912// CONSTRAINT REMAPPING << 913 914void afxChoreographer::remapObjectConstraint(SceneObject* object, const char* cons_name) 915{ 916 if (!object || !cons_name) 917 return; 918 919 // must be a constraint-def with a matching name in the list 920 dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name); 921 if (!dyn_def) 922 { 923 Con::errorf("afxChoreographer::remapObjectConstraint() -- failed to find constraint name [%s].", cons_name); 924 return; 925 } 926 927 // constraint-def must have matching name constraint-type 928 if (dyn_def->cons_type != OBJECT_CONSTRAINT) 929 { 930 Con::errorf("afxChoreographer::remapObjectConstraint() -- remapped contraint type does not match existing constraint type."); 931 return; 932 } 933 934 // nothing to do if new object is same as old 935 if (dyn_def->cons_obj.object == object) 936 { 937#ifdef TORQUE_DEBUG 938 Con::warnf("afxChoreographer::remapObjectConstraint() -- remapped contraint object is same as existing object."); 939#endif 940 return; 941 } 942 943 dyn_def->cons_obj.object = object; 944 deleteNotify(object); 945 946 constraint_mgr->setReferenceObject(StringTable->insert(cons_name), object); 947 948#if defined(AFX_CAP_SCOPE_TRACKING) 949 if (isServerObject() && object->isScopeable()) 950 constraint_mgr->addScopeableObject(object); 951#endif 952 953 if (isServerObject()) 954 { 955 if (remapped_cons_sent) 956 { 957 remapped_cons_defs.clear(); 958 remapped_cons_sent = false; 959 } 960 remapped_cons_defs.push_back(dyn_def); 961 setMaskBits(RemapConstraintMask); 962 } 963} 964 965void afxChoreographer::remapObjectConstraint(U16 scope_id, const char* cons_name, bool is_shape) 966{ 967 if (!cons_name) 968 return; 969 970 // must be a constraint-def with a matching name in the list 971 dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name); 972 if (!dyn_def) 973 { 974 Con::errorf("afxChoreographer::remapObjectConstraint() -- failed to find constraint name [%s].", cons_name); 975 return; 976 } 977 978 // constraint-def must have matching name constraint-type 979 if (dyn_def->cons_type != OBJECT_CONSTRAINT) 980 { 981 Con::errorf("afxChoreographer::remapObjectConstraint() -- remapped contraint type does not match existing constraint type."); 982 return; 983 } 984 985 constraint_mgr->setReferenceObjectByScopeId(StringTable->insert(cons_name), scope_id, is_shape); 986} 987 988void afxChoreographer::remapPointConstraint(Point3F& point, const char* cons_name) 989{ 990 // must be a constraint-def with a matching name in the list 991 dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name); 992 if (!dyn_def) 993 { 994 Con::errorf("afxChoreographer::remapPointConstraint() -- failed to find constraint name [%s].", cons_name); 995 return; 996 } 997 998 // constraint-def must have matching name constraint-type 999 if (dyn_def->cons_type != POINT_CONSTRAINT) 1000 { 1001 Con::errorf("afxChoreographer::remapPointConstraint() -- remapped contraint type does not match existing constraint type."); 1002 return; 1003 } 1004 1005 *dyn_def->cons_obj.point = point; 1006 1007 constraint_mgr->setReferencePoint(StringTable->insert(cons_name), point); 1008 1009 if (isServerObject()) 1010 { 1011 if (remapped_cons_sent) 1012 { 1013 remapped_cons_defs.clear(); 1014 remapped_cons_sent = false; 1015 } 1016 remapped_cons_defs.push_back(dyn_def); 1017 setMaskBits(RemapConstraintMask); 1018 } 1019} 1020 1021void afxChoreographer::remapTransformConstraint(MatrixF& xfm, const char* cons_name) 1022{ 1023 // must be a constraint-def with a matching name in the list 1024 dynConstraintDef* dyn_def = find_cons_def_by_name(cons_name); 1025 if (!dyn_def) 1026 { 1027 Con::errorf("afxChoreographer::remapTransformConstraint() -- failed to find constraint name [%s].", cons_name); 1028 return; 1029 } 1030 1031 // constraint-def must have matching name constraint-type 1032 if (dyn_def->cons_type != POINT_CONSTRAINT) 1033 { 1034 Con::errorf("afxChoreographer::remapTransformConstraint() -- remapped contraint type does not match existing constraint type."); 1035 return; 1036 } 1037 1038 *dyn_def->cons_obj.xfm = xfm; 1039 1040 constraint_mgr->setReferenceTransform(StringTable->insert(cons_name), xfm); 1041 1042 if (isServerObject()) 1043 { 1044 if (remapped_cons_sent) 1045 { 1046 remapped_cons_defs.clear(); 1047 remapped_cons_sent = false; 1048 } 1049 remapped_cons_defs.push_back(dyn_def); 1050 setMaskBits(RemapConstraintMask); 1051 } 1052} 1053 1054bool afxChoreographer::remapConstraint(const char* source_spec, const char* cons_name) 1055{ 1056 SceneObject* scn_obj; 1057 Point3F pos; 1058 MatrixF xfm; 1059 1060 switch (resolve_cons_spec(source_spec, pos, xfm, &scn_obj)) 1061 { 1062 case TRANSFORM_CONSTRAINT: 1063 //addTransformConstraint(xfm, cons_name); 1064 return true; 1065 case POINT_CONSTRAINT: 1066 //addPointConstraint(pos, cons_name); 1067 return true; 1068 case OBJECT_CONSTRAINT: 1069 remapObjectConstraint(scn_obj, cons_name); 1070 return true; 1071 } 1072 1073 return false; 1074} 1075 1076DefineEngineMethod( afxChoreographer, remapConstraint, void, ( const char* source, const char* name),, 1077 "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" ) 1078{ 1079 if (!object->remapConstraint(source, name)) 1080 Con::errorf("afxChoreographer::remapConstraint() -- failed to resolve constraint source [%s].", source); 1081} 1082 1083// CONSTRAINT REMAPPING >> 1084 1085//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1086