Torque3D Documentation / _generateds / afxChoreographer.cpp

afxChoreographer.cpp

Engine/source/afx/afxChoreographer.cpp

More...

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