afxConstraint.cpp
Engine/source/afx/afxConstraint.cpp
Public Defines
define
CONS_BY_ID(id) ((*mConstraints_v[().index])[().sub_index])
define
CONS_BY_IJ(i, j) ((*mConstraints_v[()])[(j)])
Public Functions
cmp_cons_defs(const void * a, const void * b)
newObjectCons(afxConstraintMgr * mgr, bool hist)
newObjectCons(afxConstraintMgr * mgr, StringTableEntry name, bool hist)
newPointCons(afxConstraintMgr * mgr, bool hist)
newShapeCons(afxConstraintMgr * mgr, bool hist)
newShapeCons(afxConstraintMgr * mgr, StringTableEntry name, bool hist)
newShapeNodeCons(afxConstraintMgr * mgr, StringTableEntry name, StringTableEntry node, bool hist)
newTransformCons(afxConstraintMgr * mgr, bool hist)
Detailed Description
Public Defines
CONS_BY_ID(id) ((*mConstraints_v[().index])[().sub_index])
CONS_BY_IJ(i, j) ((*mConstraints_v[()])[(j)])
Public Functions
cmp_cons_defs(const void * a, const void * b)
newObjectCons(afxConstraintMgr * mgr, bool hist)
newObjectCons(afxConstraintMgr * mgr, StringTableEntry name, bool hist)
newPointCons(afxConstraintMgr * mgr, bool hist)
newShapeCons(afxConstraintMgr * mgr, bool hist)
newShapeCons(afxConstraintMgr * mgr, StringTableEntry name, bool hist)
newShapeNodeCons(afxConstraintMgr * mgr, StringTableEntry name, StringTableEntry node, bool hist)
newTransformCons(afxConstraintMgr * mgr, bool hist)
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 "arcaneFX.h" 28 29#include "T3D/aiPlayer.h" 30#include "T3D/tsStatic.h" 31#include "sim/netConnection.h" 32#include "ts/tsShapeInstance.h" 33 34#include "afxConstraint.h" 35#include "afxChoreographer.h" 36#include "afxEffectWrapper.h" 37 38//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 39// afxConstraintDef 40 41// static 42StringTableEntry afxConstraintDef::SCENE_CONS_KEY; 43StringTableEntry afxConstraintDef::EFFECT_CONS_KEY; 44StringTableEntry afxConstraintDef::GHOST_CONS_KEY; 45 46afxConstraintDef::afxConstraintDef() 47{ 48 if (SCENE_CONS_KEY == 0) 49 { 50 SCENE_CONS_KEY = StringTable->insert("#scene"); 51 EFFECT_CONS_KEY = StringTable->insert("#effect"); 52 GHOST_CONS_KEY = StringTable->insert("#ghost"); 53 } 54 55 reset(); 56} 57 58bool afxConstraintDef::isDefined() 59{ 60 return (mDef_type != CONS_UNDEFINED); 61} 62 63bool afxConstraintDef::isArbitraryObject() 64{ 65 return ((mCons_src_name != ST_NULLSTRING) && (mDef_type == CONS_SCENE)); 66} 67 68void afxConstraintDef::reset() 69{ 70 mCons_src_name = ST_NULLSTRING; 71 mCons_node_name = ST_NULLSTRING; 72 mDef_type = CONS_UNDEFINED; 73 mHistory_time = 0; 74 mSample_rate = 30; 75 mRuns_on_server = false; 76 mRuns_on_client = false; 77 mPos_at_box_center = false; 78 mTreat_as_camera = false; 79} 80 81bool afxConstraintDef::parseSpec(const char* spec, bool runs_on_server, 82 bool runs_on_client) 83{ 84 reset(); 85 86 if (spec == 0 || spec[0] == '\0') 87 return false; 88 89 mHistory_time = 0.0f; 90 mSample_rate = 30; 91 92 mRuns_on_server = runs_on_server; 93 mRuns_on_client = runs_on_client; 94 95 // spec should be in one of these forms: 96 // CONSTRAINT_NAME (only) 97 // CONSTRAINT_NAME.NODE (shapeBase objects only) 98 // CONSTRAINT_NAME.#center 99 // object.OBJECT_NAME 100 // object.OBJECT_NAME.NODE (shapeBase objects only) 101 // object.OBJECT_NAME.#center 102 // effect.EFFECT_NAME 103 // effect.EFFECT_NAME.NODE 104 // effect.EFFECT_NAME.#center 105 // #ghost.EFFECT_NAME 106 // #ghost.EFFECT_NAME.NODE 107 // #ghost.EFFECT_NAME.#center 108 // 109 110 // create scratch buffer by duplicating spec. 111 char special = '\b'; 112 char* buffer = dStrdup(spec); 113 114 // substitute a dots not inside parens with special character 115 S32 n_nested = 0; 116 for (char* b = buffer; (*b) != '\0'; b++) 117 { 118 if ((*b) == '(') 119 n_nested++; 120 else if ((*b) == ')') 121 n_nested--; 122 else if ((*b) == '.' && n_nested == 0) 123 (*b) = special; 124 } 125 126 // divide name into '.' separated tokens (up to 8) 127 char* words[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 128 char* dot = buffer; 129 int wdx = 0; 130 while (wdx < 8) 131 { 132 words[wdx] = dot; 133 dot = dStrchr(words[wdx++], special); 134 if (!dot) 135 break; 136 *(dot++) = '\0'; 137 if ((*dot) == '\0') 138 break; 139 } 140 141 int n_words = wdx; 142 143 // at this point the spec has been split into words. 144 // n_words indicates how many words we have. 145 146 // no words found (must have been all whitespace) 147 if (n_words < 1) 148 { 149 dFree(buffer); 150 return false; 151 } 152 153 char* hist_spec = 0; 154 char* words2[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 155 int n_words2 = 0; 156 157 // move words to words2 while extracting #center and #history 158 for (S32 i = 0; i < n_words; i++) 159 { 160 if (String::compare(words[i], "#center") == 0) 161 mPos_at_box_center = true; 162 else if (dStrncmp(words[i], "#history(", 9) == 0) 163 hist_spec = words[i]; 164 else 165 words2[n_words2++] = words[i]; 166 } 167 168 // words2[] now contains just the constraint part 169 170 // no words found (must have been all #center and #history) 171 if (n_words2 < 1) 172 { 173 dFree(buffer); 174 return false; 175 } 176 177 if (hist_spec) 178 { 179 char* open_paren = dStrchr(hist_spec, '('); 180 if (open_paren) 181 { 182 hist_spec = open_paren+1; 183 if ((*hist_spec) != '\0') 184 { 185 char* close_paren = dStrchr(hist_spec, ')'); 186 if (close_paren) 187 (*close_paren) = '\0'; 188 char* slash = dStrchr(hist_spec, '/'); 189 if (slash) 190 (*slash) = ' '; 191 192 F32 hist_age = 0.0; 193 U32 hist_rate = 30; 194 S32 args = dSscanf(hist_spec,"%g %d", &hist_age, &hist_rate); 195 196 if (args > 0) 197 mHistory_time = hist_age; 198 if (args > 1) 199 mSample_rate = hist_rate; 200 } 201 } 202 } 203 204 StringTableEntry cons_name_key = StringTable->insert(words2[0]); 205 206 // must be in CONSTRAINT_NAME (only) form 207 if (n_words2 == 1) 208 { 209 // arbitrary object/effect constraints must have a name 210 if (cons_name_key == SCENE_CONS_KEY || cons_name_key == EFFECT_CONS_KEY) 211 { 212 dFree(buffer); 213 return false; 214 } 215 216 mCons_src_name = cons_name_key; 217 mDef_type = CONS_PREDEFINED; 218 dFree(buffer); 219 return true; 220 } 221 222 // "#scene.NAME" or "#scene.NAME.NODE"" 223 if (cons_name_key == SCENE_CONS_KEY) 224 { 225 mCons_src_name = StringTable->insert(words2[1]); 226 if (n_words2 > 2) 227 mCons_node_name = StringTable->insert(words2[2]); 228 mDef_type = CONS_SCENE; 229 dFree(buffer); 230 return true; 231 } 232 233 // "#effect.NAME" or "#effect.NAME.NODE" 234 if (cons_name_key == EFFECT_CONS_KEY) 235 { 236 mCons_src_name = StringTable->insert(words2[1]); 237 if (n_words2 > 2) 238 mCons_node_name = StringTable->insert(words2[2]); 239 mDef_type = CONS_EFFECT; 240 dFree(buffer); 241 return true; 242 } 243 244 // "#ghost.NAME" or "#ghost.NAME.NODE" 245 if (cons_name_key == GHOST_CONS_KEY) 246 { 247 if (runs_on_server) 248 { 249 dFree(buffer); 250 return false; 251 } 252 253 mCons_src_name = StringTable->insert(words2[1]); 254 if (n_words2 > 2) 255 mCons_node_name = StringTable->insert(words2[2]); 256 mDef_type = CONS_GHOST; 257 dFree(buffer); 258 return true; 259 } 260 261 // "CONSTRAINT_NAME.NODE" 262 if (n_words2 == 2) 263 { 264 mCons_src_name = cons_name_key; 265 mCons_node_name = StringTable->insert(words2[1]); 266 mDef_type = CONS_PREDEFINED; 267 dFree(buffer); 268 return true; 269 } 270 271 // must be in unsupported form 272 dFree(buffer); 273 return false; 274} 275 276void afxConstraintDef::gather_cons_defs(Vector<afxConstraintDef>& defs, afxEffectList& fx) 277{ 278 for (S32 i = 0; i < fx.size(); i++) 279 { 280 if (fx[i]) 281 fx[i]->gather_cons_defs(defs); 282 } 283} 284 285//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 286//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 287// afxConstraint 288 289afxConstraint::afxConstraint(afxConstraintMgr* mgr) 290{ 291 mMgr = mgr; 292 mIs_defined = false; 293 mIs_valid = false; 294 mLast_pos.zero(); 295 mLast_xfm.identity(); 296 mHistory_time = 0.0f; 297 mIs_alive = true; 298 mGone_missing = false; 299 mChange_code = 0; 300} 301 302afxConstraint::~afxConstraint() 303{ 304} 305 306//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 307 308inline afxPointConstraint* newPointCons(afxConstraintMgr* mgr, bool hist) 309{ 310 return (hist) ? new afxPointHistConstraint(mgr) : new afxPointConstraint(mgr); 311} 312 313inline afxTransformConstraint* newTransformCons(afxConstraintMgr* mgr, bool hist) 314{ 315 return (hist) ? new afxTransformHistConstraint(mgr) : new afxTransformConstraint(mgr); 316} 317 318inline afxShapeConstraint* newShapeCons(afxConstraintMgr* mgr, bool hist) 319{ 320 return (hist) ? new afxShapeHistConstraint(mgr) : new afxShapeConstraint(mgr); 321} 322 323inline afxShapeConstraint* newShapeCons(afxConstraintMgr* mgr, StringTableEntry name, bool hist) 324{ 325 return (hist) ? new afxShapeHistConstraint(mgr, name) : new afxShapeConstraint(mgr, name); 326} 327 328inline afxShapeNodeConstraint* newShapeNodeCons(afxConstraintMgr* mgr, StringTableEntry name, StringTableEntry node, bool hist) 329{ 330 return (hist) ? new afxShapeNodeHistConstraint(mgr, name, node) : new afxShapeNodeConstraint(mgr, name, node); 331} 332 333inline afxObjectConstraint* newObjectCons(afxConstraintMgr* mgr, bool hist) 334{ 335 return (hist) ? new afxObjectHistConstraint(mgr) : new afxObjectConstraint(mgr); 336} 337 338inline afxObjectConstraint* newObjectCons(afxConstraintMgr* mgr, StringTableEntry name, bool hist) 339{ 340 return (hist) ? new afxObjectHistConstraint(mgr, name) : new afxObjectConstraint(mgr, name); 341} 342 343//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 344// afxConstraintMgr 345 346#define CONS_BY_ID(id) ((*mConstraints_v[(id).index])[(id).sub_index]) 347#define CONS_BY_IJ(i,j) ((*mConstraints_v[(i)])[(j)]) 348 349afxConstraintMgr::afxConstraintMgr() 350{ 351 mStartTime = 0; 352 mOn_server = false; 353 mInitialized = false; 354 mScoping_dist_sq = 1000.0f*1000.0f; 355 missing_objs = &missing_objs_a; 356 missing_objs2 = &missing_objs_b; 357} 358 359afxConstraintMgr::~afxConstraintMgr() 360{ 361 for (S32 i = 0; i < mConstraints_v.size(); i++) 362 { 363 for (S32 j = 0; j < (*mConstraints_v[i]).size(); j++) 364 delete CONS_BY_IJ(i,j); 365 delete mConstraints_v[i]; 366 } 367} 368 369//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// 370 371S32 afxConstraintMgr::find_cons_idx_from_name(StringTableEntry which) 372{ 373 for (S32 i = 0; i < mConstraints_v.size(); i++) 374 { 375 afxConstraint* cons = CONS_BY_IJ(i,0); 376 if (cons && afxConstraintDef::CONS_EFFECT != cons->mCons_def.mDef_type && 377 which == cons->mCons_def.mCons_src_name) 378 { 379 return i; 380 } 381 } 382 383 return -1; 384} 385 386S32 afxConstraintMgr::find_effect_cons_idx_from_name(StringTableEntry which) 387{ 388 for (S32 i = 0; i < mConstraints_v.size(); i++) 389 { 390 afxConstraint* cons = CONS_BY_IJ(i,0); 391 if (cons && afxConstraintDef::CONS_EFFECT == cons->mCons_def.mDef_type && 392 which == cons->mCons_def.mCons_src_name) 393 { 394 return i; 395 } 396 } 397 398 return -1; 399} 400 401// Defines a predefined constraint with given name and type 402void afxConstraintMgr::defineConstraint(U32 type, StringTableEntry name) 403{ 404 preDef predef = { name, type }; 405 mPredefs.push_back(predef); 406} 407 408afxConstraintID afxConstraintMgr::setReferencePoint(StringTableEntry which, Point3F point, 409 Point3F vector) 410{ 411 S32 idx = find_cons_idx_from_name(which); 412 if (idx < 0) 413 return afxConstraintID(); 414 415 afxConstraintID id = afxConstraintID(idx); 416 setReferencePoint(id, point, vector); 417 418 return id; 419} 420 421afxConstraintID afxConstraintMgr::setReferenceTransform(StringTableEntry which, MatrixF& xfm) 422{ 423 S32 idx = find_cons_idx_from_name(which); 424 if (idx < 0) 425 return afxConstraintID(); 426 427 afxConstraintID id = afxConstraintID(idx); 428 setReferenceTransform(id, xfm); 429 430 return id; 431} 432 433// Assigns an existing scene-object to the named constraint 434afxConstraintID afxConstraintMgr::setReferenceObject(StringTableEntry which, SceneObject* obj) 435{ 436 S32 idx = find_cons_idx_from_name(which); 437 if (idx < 0) 438 return afxConstraintID(); 439 440 afxConstraintID id = afxConstraintID(idx); 441 setReferenceObject(id, obj); 442 443 return id; 444} 445 446// Assigns an un-scoped scene-object by scope_id to the named constraint 447afxConstraintID afxConstraintMgr::setReferenceObjectByScopeId(StringTableEntry which, U16 scope_id, bool is_shape) 448{ 449 S32 idx = find_cons_idx_from_name(which); 450 if (idx < 0) 451 return afxConstraintID(); 452 453 afxConstraintID id = afxConstraintID(idx); 454 setReferenceObjectByScopeId(id, scope_id, is_shape); 455 456 return id; 457} 458 459afxConstraintID afxConstraintMgr::setReferenceEffect(StringTableEntry which, afxEffectWrapper* ew) 460{ 461 S32 idx = find_effect_cons_idx_from_name(which); 462 463 if (idx < 0) 464 return afxConstraintID(); 465 466 afxConstraintID id = afxConstraintID(idx); 467 setReferenceEffect(id, ew); 468 469 return id; 470} 471 472afxConstraintID afxConstraintMgr::createReferenceEffect(StringTableEntry which, afxEffectWrapper* ew) 473{ 474 afxEffectConstraint* cons = new afxEffectConstraint(this, which); 475 //cons->cons_def = def; 476 cons->mCons_def.mDef_type = afxConstraintDef::CONS_EFFECT; 477 cons->mCons_def.mCons_src_name = which; 478 afxConstraintList* list = new afxConstraintList(); 479 list->push_back(cons); 480 mConstraints_v.push_back(list); 481 482 return setReferenceEffect(which, ew); 483} 484 485void afxConstraintMgr::setReferencePoint(afxConstraintID id, Point3F point, Point3F vector) 486{ 487 afxPointConstraint* pt_cons = dynamic_cast<afxPointConstraint*>(CONS_BY_ID(id)); 488 489 // need to change type 490 if (!pt_cons) 491 { 492 afxConstraint* cons = CONS_BY_ID(id); 493 pt_cons = newPointCons(this, cons->mCons_def.mHistory_time > 0.0f); 494 pt_cons->mCons_def = cons->mCons_def; 495 CONS_BY_ID(id) = pt_cons; 496 delete cons; 497 } 498 499 pt_cons->set(point, vector); 500 501 // nullify all subnodes 502 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 503 { 504 afxConstraint* cons = CONS_BY_IJ(id.index,j); 505 if (cons) 506 cons->unset(); 507 } 508} 509 510void afxConstraintMgr::setReferenceTransform(afxConstraintID id, MatrixF& xfm) 511{ 512 afxTransformConstraint* xfm_cons = dynamic_cast<afxTransformConstraint*>(CONS_BY_ID(id)); 513 514 // need to change type 515 if (!xfm_cons) 516 { 517 afxConstraint* cons = CONS_BY_ID(id); 518 xfm_cons = newTransformCons(this, cons->mCons_def.mHistory_time > 0.0f); 519 xfm_cons->mCons_def = cons->mCons_def; 520 CONS_BY_ID(id) = xfm_cons; 521 delete cons; 522 } 523 524 xfm_cons->set(xfm); 525 526 // nullify all subnodes 527 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 528 { 529 afxConstraint* cons = CONS_BY_IJ(id.index,j); 530 if (cons) 531 cons->unset(); 532 } 533} 534 535void afxConstraintMgr::set_ref_shape(afxConstraintID id, ShapeBase* shape) 536{ 537 id.sub_index = 0; 538 539 afxShapeConstraint* shape_cons = dynamic_cast<afxShapeConstraint*>(CONS_BY_ID(id)); 540 541 // need to change type 542 if (!shape_cons) 543 { 544 afxConstraint* cons = CONS_BY_ID(id); 545 shape_cons = newShapeCons(this, cons->mCons_def.mHistory_time > 0.0f); 546 shape_cons->mCons_def = cons->mCons_def; 547 CONS_BY_ID(id) = shape_cons; 548 delete cons; 549 } 550 551 // set new shape on root 552 shape_cons->set(shape); 553 554 // update all subnodes 555 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 556 { 557 afxConstraint* cons = CONS_BY_IJ(id.index,j); 558 if (cons) 559 { 560 if (dynamic_cast<afxShapeNodeConstraint*>(cons)) 561 ((afxShapeNodeConstraint*)cons)->set(shape); 562 else if (dynamic_cast<afxShapeConstraint*>(cons)) 563 ((afxShapeConstraint*)cons)->set(shape); 564 else if (dynamic_cast<afxObjectConstraint*>(cons)) 565 ((afxObjectConstraint*)cons)->set(shape); 566 else 567 cons->unset(); 568 } 569 } 570} 571 572void afxConstraintMgr::set_ref_shape(afxConstraintID id, U16 scope_id) 573{ 574 id.sub_index = 0; 575 576 afxShapeConstraint* shape_cons = dynamic_cast<afxShapeConstraint*>(CONS_BY_ID(id)); 577 578 // need to change type 579 if (!shape_cons) 580 { 581 afxConstraint* cons = CONS_BY_ID(id); 582 shape_cons = newShapeCons(this, cons->mCons_def.mHistory_time > 0.0f); 583 shape_cons->mCons_def = cons->mCons_def; 584 CONS_BY_ID(id) = shape_cons; 585 delete cons; 586 } 587 588 // set new shape on root 589 shape_cons->set_scope_id(scope_id); 590 591 // update all subnodes 592 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 593 { 594 afxConstraint* cons = CONS_BY_IJ(id.index,j); 595 if (cons) 596 cons->set_scope_id(scope_id); 597 } 598} 599 600// Assigns an existing scene-object to the constraint matching the given constraint-id. 601void afxConstraintMgr::setReferenceObject(afxConstraintID id, SceneObject* obj) 602{ 603 if (!mInitialized) 604 Con::errorf("afxConstraintMgr::setReferenceObject() -- constraint manager not initialized"); 605 606 if (!CONS_BY_ID(id)->mCons_def.mTreat_as_camera) 607 { 608 ShapeBase* shape = dynamic_cast<ShapeBase*>(obj); 609 if (shape) 610 { 611 set_ref_shape(id, shape); 612 return; 613 } 614 } 615 616 afxObjectConstraint* obj_cons = dynamic_cast<afxObjectConstraint*>(CONS_BY_ID(id)); 617 618 // need to change type 619 if (!obj_cons) 620 { 621 afxConstraint* cons = CONS_BY_ID(id); 622 obj_cons = newObjectCons(this, cons->mCons_def.mHistory_time > 0.0f); 623 obj_cons->mCons_def = cons->mCons_def; 624 CONS_BY_ID(id) = obj_cons; 625 delete cons; 626 } 627 628 obj_cons->set(obj); 629 630 // update all subnodes 631 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 632 { 633 afxConstraint* cons = CONS_BY_IJ(id.index,j); 634 if (cons) 635 { 636 if (dynamic_cast<afxObjectConstraint*>(cons)) 637 ((afxObjectConstraint*)cons)->set(obj); 638 else 639 cons->unset(); 640 } 641 } 642} 643 644// Assigns an un-scoped scene-object by scope_id to the constraint matching the 645// given constraint-id. 646void afxConstraintMgr::setReferenceObjectByScopeId(afxConstraintID id, U16 scope_id, bool is_shape) 647{ 648 if (!mInitialized) 649 Con::errorf("afxConstraintMgr::setReferenceObject() -- constraint manager not initialized"); 650 651 if (is_shape) 652 { 653 set_ref_shape(id, scope_id); 654 return; 655 } 656 657 afxObjectConstraint* obj_cons = dynamic_cast<afxObjectConstraint*>(CONS_BY_ID(id)); 658 659 // need to change type 660 if (!obj_cons) 661 { 662 afxConstraint* cons = CONS_BY_ID(id); 663 obj_cons = newObjectCons(this, cons->mCons_def.mHistory_time > 0.0f); 664 obj_cons->mCons_def = cons->mCons_def; 665 CONS_BY_ID(id) = obj_cons; 666 delete cons; 667 } 668 669 obj_cons->set_scope_id(scope_id); 670 671 // update all subnodes 672 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 673 { 674 afxConstraint* cons = CONS_BY_IJ(id.index,j); 675 if (cons) 676 cons->set_scope_id(scope_id); 677 } 678} 679 680void afxConstraintMgr::setReferenceEffect(afxConstraintID id, afxEffectWrapper* ew) 681{ 682 afxEffectConstraint* eff_cons = dynamic_cast<afxEffectConstraint*>(CONS_BY_ID(id)); 683 if (!eff_cons) 684 return; 685 686 eff_cons->set(ew); 687 688 // update all subnodes 689 for (S32 j = 1; j < (*mConstraints_v[id.index]).size(); j++) 690 { 691 afxConstraint* cons = CONS_BY_IJ(id.index,j); 692 if (cons) 693 { 694 if (dynamic_cast<afxEffectNodeConstraint*>(cons)) 695 ((afxEffectNodeConstraint*)cons)->set(ew); 696 else if (dynamic_cast<afxEffectConstraint*>(cons)) 697 ((afxEffectConstraint*)cons)->set(ew); 698 else 699 cons->unset(); 700 } 701 } 702} 703 704void afxConstraintMgr::invalidateReference(afxConstraintID id) 705{ 706 afxConstraint* cons = CONS_BY_ID(id); 707 if (cons) 708 cons->mIs_valid = false; 709} 710 711void afxConstraintMgr::create_constraint(const afxConstraintDef& def) 712{ 713 if (def.mDef_type == afxConstraintDef::CONS_UNDEFINED) 714 return; 715 716 //Con::printf("CON - %s [%s] [%s] h=%g", def.cons_type_name, def.cons_src_name, def.cons_node_name, def.history_time); 717 718 bool want_history = (def.mHistory_time > 0.0f); 719 720 // constraint is an arbitrary named scene object 721 // 722 if (def.mDef_type == afxConstraintDef::CONS_SCENE) 723 { 724 if (def.mCons_src_name == ST_NULLSTRING) 725 return; 726 727 // find the arbitrary object by name 728 SceneObject* arb_obj; 729 if (mOn_server) 730 { 731 arb_obj = dynamic_cast<SceneObject*>(Sim::findObject(def.mCons_src_name)); 732 if (!arb_obj) 733 Con::errorf("afxConstraintMgr -- failed to find scene constraint source, \"%s\" on server.", 734 def.mCons_src_name); 735 } 736 else 737 { 738 arb_obj = find_object_from_name(def.mCons_src_name); 739 if (!arb_obj) 740 Con::errorf("afxConstraintMgr -- failed to find scene constraint source, \"%s\" on client.", 741 def.mCons_src_name); 742 } 743 744 // if it's a shapeBase object, create a Shape or ShapeNode constraint 745 if (dynamic_cast<ShapeBase*>(arb_obj)) 746 { 747 if (def.mCons_node_name == ST_NULLSTRING && !def.mPos_at_box_center) 748 { 749 afxShapeConstraint* cons = newShapeCons(this, def.mCons_src_name, want_history); 750 cons->mCons_def = def; 751 cons->set((ShapeBase*)arb_obj); 752 afxConstraintList* list = new afxConstraintList(); 753 list->push_back(cons); 754 mConstraints_v.push_back(list); 755 } 756 else if (def.mPos_at_box_center) 757 { 758 afxShapeConstraint* cons = newShapeCons(this, def.mCons_src_name, want_history); 759 cons->mCons_def = def; 760 cons->set((ShapeBase*)arb_obj); 761 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; // SHAPE-NODE CONS-LIST (#scene)(#center) 762 if (list && (*list)[0]) 763 list->push_back(cons); 764 } 765 else 766 { 767 afxShapeNodeConstraint* sub = newShapeNodeCons(this, def.mCons_src_name, def.mCons_node_name, want_history); 768 sub->mCons_def = def; 769 sub->set((ShapeBase*)arb_obj); 770 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; 771 if (list && (*list)[0]) 772 list->push_back(sub); 773 } 774 } 775 // if it's not a shapeBase object, create an Object constraint 776 else if (arb_obj) 777 { 778 if (!def.mPos_at_box_center) 779 { 780 afxObjectConstraint* cons = newObjectCons(this, def.mCons_src_name, want_history); 781 cons->mCons_def = def; 782 cons->set(arb_obj); 783 afxConstraintList* list = new afxConstraintList(); // OBJECT CONS-LIST (#scene) 784 list->push_back(cons); 785 mConstraints_v.push_back(list); 786 } 787 else // if (def.pos_at_box_center) 788 { 789 afxObjectConstraint* cons = newObjectCons(this, def.mCons_src_name, want_history); 790 cons->mCons_def = def; 791 cons->set(arb_obj); 792 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; // OBJECT CONS-LIST (#scene)(#center) 793 if (list && (*list)[0]) 794 list->push_back(cons); 795 } 796 } 797 } 798 799 // constraint is an arbitrary named effect 800 // 801 else if (def.mDef_type == afxConstraintDef::CONS_EFFECT) 802 { 803 if (def.mCons_src_name == ST_NULLSTRING) 804 return; 805 806 // create an Effect constraint 807 if (def.mCons_node_name == ST_NULLSTRING && !def.mPos_at_box_center) 808 { 809 afxEffectConstraint* cons = new afxEffectConstraint(this, def.mCons_src_name); 810 cons->mCons_def = def; 811 afxConstraintList* list = new afxConstraintList(); 812 list->push_back(cons); 813 mConstraints_v.push_back(list); 814 } 815 // create an Effect #center constraint 816 else if (def.mPos_at_box_center) 817 { 818 afxEffectConstraint* cons = new afxEffectConstraint(this, def.mCons_src_name); 819 cons->mCons_def = def; 820 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; // EFFECT-NODE CONS-LIST (#effect) 821 if (list && (*list)[0]) 822 list->push_back(cons); 823 } 824 // create an EffectNode constraint 825 else 826 { 827 afxEffectNodeConstraint* sub = new afxEffectNodeConstraint(this, def.mCons_src_name, def.mCons_node_name); 828 sub->mCons_def = def; 829 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; 830 if (list && (*list)[0]) 831 list->push_back(sub); 832 } 833 } 834 835 // constraint is a predefined constraint 836 // 837 else 838 { 839 afxConstraint* cons = 0; 840 afxConstraint* cons_ctr = 0; 841 afxConstraint* sub = 0; 842 843 if (def.mDef_type == afxConstraintDef::CONS_GHOST) 844 { 845 for (S32 i = 0; i < mPredefs.size(); i++) 846 { 847 if (mPredefs[i].name == def.mCons_src_name) 848 { 849 if (def.mCons_node_name == ST_NULLSTRING && !def.mPos_at_box_center) 850 { 851 cons = newShapeCons(this, want_history); 852 cons->mCons_def = def; 853 } 854 else if (def.mPos_at_box_center) 855 { 856 cons_ctr = newShapeCons(this, want_history); 857 cons_ctr->mCons_def = def; 858 } 859 else 860 { 861 sub = newShapeNodeCons(this, ST_NULLSTRING, def.mCons_node_name, want_history); 862 sub->mCons_def = def; 863 } 864 break; 865 } 866 } 867 } 868 else 869 { 870 for (S32 i = 0; i < mPredefs.size(); i++) 871 { 872 if (mPredefs[i].name == def.mCons_src_name) 873 { 874 switch (mPredefs[i].type) 875 { 876 case POINT_CONSTRAINT: 877 cons = newPointCons(this, want_history); 878 cons->mCons_def = def; 879 break; 880 case TRANSFORM_CONSTRAINT: 881 cons = newTransformCons(this, want_history); 882 cons->mCons_def = def; 883 break; 884 case OBJECT_CONSTRAINT: 885 if (def.mCons_node_name == ST_NULLSTRING && !def.mPos_at_box_center) 886 { 887 cons = newShapeCons(this, want_history); 888 cons->mCons_def = def; 889 } 890 else if (def.mPos_at_box_center) 891 { 892 cons_ctr = newShapeCons(this, want_history); 893 cons_ctr->mCons_def = def; 894 } 895 else 896 { 897 sub = newShapeNodeCons(this, ST_NULLSTRING, def.mCons_node_name, want_history); 898 sub->mCons_def = def; 899 } 900 break; 901 case CAMERA_CONSTRAINT: 902 cons = newObjectCons(this, want_history); 903 cons->mCons_def = def; 904 cons->mCons_def.mTreat_as_camera = true; 905 break; 906 } 907 break; 908 } 909 } 910 } 911 912 if (cons) 913 { 914 afxConstraintList* list = new afxConstraintList(); 915 list->push_back(cons); 916 mConstraints_v.push_back(list); 917 } 918 else if (cons_ctr && mConstraints_v.size() > 0) 919 { 920 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; // PREDEF-NODE CONS-LIST 921 if (list && (*list)[0]) 922 list->push_back(cons_ctr); 923 } 924 else if (sub && mConstraints_v.size() > 0) 925 { 926 afxConstraintList* list = mConstraints_v[mConstraints_v.size()-1]; 927 if (list && (*list)[0]) 928 list->push_back(sub); 929 } 930 else 931 Con::printf("predef not found %s", def.mCons_src_name); 932 } 933} 934 935afxConstraintID afxConstraintMgr::getConstraintId(const afxConstraintDef& def) 936{ 937 if (def.mDef_type == afxConstraintDef::CONS_UNDEFINED) 938 return afxConstraintID(); 939 940 if (def.mCons_src_name != ST_NULLSTRING) 941 { 942 for (S32 i = 0; i < mConstraints_v.size(); i++) 943 { 944 afxConstraintList* list = mConstraints_v[i]; 945 afxConstraint* cons = (*list)[0]; 946 if (def.mCons_src_name == cons->mCons_def.mCons_src_name) 947 { 948 for (S32 j = 0; j < list->size(); j++) 949 { 950 afxConstraint* sub = (*list)[j]; 951 if (def.mCons_node_name == sub->mCons_def.mCons_node_name && 952 def.mPos_at_box_center == sub->mCons_def.mPos_at_box_center && 953 def.mCons_src_name == sub->mCons_def.mCons_src_name) 954 { 955 return afxConstraintID(i, j); 956 } 957 } 958 959 // if we're here, it means the root object name matched but the node name 960 // did not. 961 if (def.mDef_type == afxConstraintDef::CONS_PREDEFINED && !def.mPos_at_box_center) 962 { 963 afxShapeConstraint* shape_cons = dynamic_cast<afxShapeConstraint*>(cons); 964 if (shape_cons) 965 { 966 //Con::errorf("Append a Node constraint [%s.%s] [%d,%d]", def.cons_src_name, def.cons_node_name, i, list->size()); 967 bool want_history = (def.mHistory_time > 0.0f); 968 afxConstraint* sub = newShapeNodeCons(this, ST_NULLSTRING, def.mCons_node_name, want_history); 969 sub->mCons_def = def; 970 ((afxShapeConstraint*)sub)->set(shape_cons->mShape); 971 list->push_back(sub); 972 973 return afxConstraintID(i, list->size()-1); 974 } 975 } 976 977 break; 978 } 979 } 980 } 981 982 return afxConstraintID(); 983} 984 985afxConstraint* afxConstraintMgr::getConstraint(afxConstraintID id) 986{ 987 if (id.undefined()) 988 return 0; 989 990 afxConstraint* cons = CONS_BY_IJ(id.index,id.sub_index); 991 if (cons && !cons->isDefined()) 992 return NULL; 993 994 return cons; 995} 996 997void afxConstraintMgr::sample(F32 dt, U32 now, const Point3F* cam_pos) 998{ 999 U32 elapsed = now - mStartTime; 1000 1001 for (S32 i = 0; i < mConstraints_v.size(); i++) 1002 { 1003 afxConstraintList* list = mConstraints_v[i]; 1004 for (S32 j = 0; j < list->size(); j++) 1005 (*list)[j]->sample(dt, elapsed, cam_pos); 1006 } 1007} 1008 1009S32 QSORT_CALLBACK cmp_cons_defs(const void* a, const void* b) 1010{ 1011 afxConstraintDef* def_a = (afxConstraintDef*) a; 1012 afxConstraintDef* def_b = (afxConstraintDef*) b; 1013 1014 if (def_a->mDef_type == def_b->mDef_type) 1015 { 1016 if (def_a->mCons_src_name == def_b->mCons_src_name) 1017 { 1018 if (def_a->mPos_at_box_center == def_b->mPos_at_box_center) 1019 return (def_a->mCons_node_name - def_b->mCons_node_name); 1020 else 1021 return (def_a->mPos_at_box_center) ? 1 : -1; 1022 } 1023 return (def_a->mCons_src_name - def_b->mCons_src_name); 1024 } 1025 1026 return (def_a->mDef_type - def_b->mDef_type); 1027} 1028 1029void afxConstraintMgr::initConstraintDefs(Vector<afxConstraintDef>& all_defs, bool on_server, F32 scoping_dist) 1030{ 1031 mInitialized = true; 1032 mOn_server = on_server; 1033 1034 if (scoping_dist > 0.0) 1035 mScoping_dist_sq = scoping_dist*scoping_dist; 1036 else 1037 { 1038 SceneManager* sg = (on_server) ? gServerSceneGraph : gClientSceneGraph; 1039 F32 vis_dist = (sg) ? sg->getVisibleDistance() : 1000.0f; 1040 mScoping_dist_sq = vis_dist*vis_dist; 1041 } 1042 1043 if (all_defs.size() < 1) 1044 return; 1045 1046 // find effect ghost constraints 1047 if (!on_server) 1048 { 1049 Vector<afxConstraintDef> ghost_defs; 1050 1051 for (S32 i = 0; i < all_defs.size(); i++) 1052 if (all_defs[i].mDef_type == afxConstraintDef::CONS_GHOST && all_defs[i].mCons_src_name != ST_NULLSTRING) 1053 ghost_defs.push_back(all_defs[i]); 1054 1055 if (ghost_defs.size() > 0) 1056 { 1057 // sort the defs 1058 if (ghost_defs.size() > 1) 1059 dQsort(ghost_defs.address(), ghost_defs.size(), sizeof(afxConstraintDef), cmp_cons_defs); 1060 1061 S32 last = 0; 1062 defineConstraint(OBJECT_CONSTRAINT, ghost_defs[0].mCons_src_name); 1063 1064 for (S32 i = 1; i < ghost_defs.size(); i++) 1065 { 1066 if (ghost_defs[last].mCons_src_name != ghost_defs[i].mCons_src_name) 1067 { 1068 defineConstraint(OBJECT_CONSTRAINT, ghost_defs[i].mCons_src_name); 1069 last++; 1070 } 1071 } 1072 } 1073 } 1074 1075 Vector<afxConstraintDef> defs; 1076 1077 // collect defs that run here (server or client) 1078 if (on_server) 1079 { 1080 for (S32 i = 0; i < all_defs.size(); i++) 1081 if (all_defs[i].mRuns_on_server) 1082 defs.push_back(all_defs[i]); 1083 } 1084 else 1085 { 1086 for (S32 i = 0; i < all_defs.size(); i++) 1087 if (all_defs[i].mRuns_on_client) 1088 defs.push_back(all_defs[i]); 1089 } 1090 1091 // create unique set of constraints. 1092 // 1093 if (defs.size() > 0) 1094 { 1095 // sort the defs 1096 if (defs.size() > 1) 1097 dQsort(defs.address(), defs.size(), sizeof(afxConstraintDef), cmp_cons_defs); 1098 1099 Vector<afxConstraintDef> unique_defs; 1100 S32 last = 0; 1101 1102 // manufacture root-object def if absent 1103 if (defs[0].mCons_node_name != ST_NULLSTRING) 1104 { 1105 afxConstraintDef root_def = defs[0]; 1106 root_def.mCons_node_name = ST_NULLSTRING; 1107 unique_defs.push_back(root_def); 1108 last++; 1109 } 1110 else if (defs[0].mPos_at_box_center) 1111 { 1112 afxConstraintDef root_def = defs[0]; 1113 root_def.mPos_at_box_center = false; 1114 unique_defs.push_back(root_def); 1115 last++; 1116 } 1117 1118 unique_defs.push_back(defs[0]); 1119 1120 for (S32 i = 1; i < defs.size(); i++) 1121 { 1122 if (unique_defs[last].mCons_node_name != defs[i].mCons_node_name || 1123 unique_defs[last].mCons_src_name != defs[i].mCons_src_name || 1124 unique_defs[last].mPos_at_box_center != defs[i].mPos_at_box_center || 1125 unique_defs[last].mDef_type != defs[i].mDef_type) 1126 { 1127 // manufacture root-object def if absent 1128 if (defs[i].mCons_src_name != ST_NULLSTRING && unique_defs[last].mCons_src_name != defs[i].mCons_src_name) 1129 { 1130 if (defs[i].mCons_node_name != ST_NULLSTRING || defs[i].mPos_at_box_center) 1131 { 1132 afxConstraintDef root_def = defs[i]; 1133 root_def.mCons_node_name = ST_NULLSTRING; 1134 root_def.mPos_at_box_center = false; 1135 unique_defs.push_back(root_def); 1136 last++; 1137 } 1138 } 1139 unique_defs.push_back(defs[i]); 1140 last++; 1141 } 1142 else 1143 { 1144 if (defs[i].mHistory_time > unique_defs[last].mHistory_time) 1145 unique_defs[last].mHistory_time = defs[i].mHistory_time; 1146 if (defs[i].mSample_rate > unique_defs[last].mSample_rate) 1147 unique_defs[last].mSample_rate = defs[i].mSample_rate; 1148 } 1149 } 1150 1151 //Con::printf("\nConstraints on %s", (on_server) ? "server" : "client"); 1152 for (S32 i = 0; i < unique_defs.size(); i++) 1153 create_constraint(unique_defs[i]); 1154 } 1155 1156 // collect the names of all the arbitrary object constraints 1157 // that run on clients and store in names_on_server array. 1158 // 1159 if (on_server) 1160 { 1161 mNames_on_server.clear(); 1162 defs.clear(); 1163 1164 for (S32 i = 0; i < all_defs.size(); i++) 1165 if (all_defs[i].mRuns_on_client && all_defs[i].isArbitraryObject()) 1166 defs.push_back(all_defs[i]); 1167 1168 if (defs.size() < 1) 1169 return; 1170 1171 // sort the defs 1172 if (defs.size() > 1) 1173 dQsort(defs.address(), defs.size(), sizeof(afxConstraintDef), cmp_cons_defs); 1174 1175 S32 last = 0; 1176 mNames_on_server.push_back(defs[0].mCons_src_name); 1177 1178 for (S32 i = 1; i < defs.size(); i++) 1179 { 1180 if (mNames_on_server[last] != defs[i].mCons_src_name) 1181 { 1182 mNames_on_server.push_back(defs[i].mCons_src_name); 1183 last++; 1184 } 1185 } 1186 } 1187} 1188 1189void afxConstraintMgr::packConstraintNames(NetConnection* conn, BitStream* stream) 1190{ 1191 // pack any named constraint names and ghost indices 1192 if (stream->writeFlag(mNames_on_server.size() > 0)) //-- ANY NAMED CONS_BY_ID? 1193 { 1194 stream->write(mNames_on_server.size()); 1195 for (S32 i = 0; i < mNames_on_server.size(); i++) 1196 { 1197 stream->writeString(mNames_on_server[i]); 1198 NetObject* obj = dynamic_cast<NetObject*>(Sim::findObject(mNames_on_server[i])); 1199 if (!obj) 1200 { 1201 //Con::printf("CONSTRAINT-OBJECT %s does not exist.", names_on_server[i]); 1202 stream->write((S32)-1); 1203 } 1204 else 1205 { 1206 S32 ghost_id = conn->getGhostIndex(obj); 1207 /* 1208 if (ghost_id == -1) 1209 Con::printf("CONSTRAINT-OBJECT %s does not have a ghost.", names_on_server[i]); 1210 else 1211 Con::printf("CONSTRAINT-OBJECT %s name to server.", names_on_server[i]); 1212 */ 1213 stream->write(ghost_id); 1214 } 1215 } 1216 } 1217} 1218 1219void afxConstraintMgr::unpackConstraintNames(BitStream* stream) 1220{ 1221 if (stream->readFlag()) //-- ANY NAMED CONS_BY_ID? 1222 { 1223 mNames_on_server.clear(); 1224 S32 sz; stream->read(&sz); 1225 for (S32 i = 0; i < sz; i++) 1226 { 1227 mNames_on_server.push_back(stream->readSTString()); 1228 S32 ghost_id; stream->read(&ghost_id); 1229 mGhost_ids.push_back(ghost_id); 1230 } 1231 } 1232} 1233 1234//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// 1235 1236SceneObject* afxConstraintMgr::find_object_from_name(StringTableEntry name) 1237{ 1238 if (mNames_on_server.size() > 0) 1239 { 1240 for (S32 i = 0; i < mNames_on_server.size(); i++) 1241 if (mNames_on_server[i] == name) 1242 { 1243 if (mGhost_ids[i] == -1) 1244 return 0; 1245 NetConnection* conn = NetConnection::getConnectionToServer(); 1246 if (!conn) 1247 return 0; 1248 return dynamic_cast<SceneObject*>(conn->resolveGhost(mGhost_ids[i])); 1249 } 1250 } 1251 1252 return dynamic_cast<SceneObject*>(Sim::findObject(name)); 1253} 1254 1255void afxConstraintMgr::addScopeableObject(SceneObject* object) 1256{ 1257 for (S32 i = 0; i < scopeable_objs.size(); i++) 1258 { 1259 if (scopeable_objs[i] == object) 1260 return; 1261 } 1262 1263 object->addScopeRef(); 1264 scopeable_objs.push_back(object); 1265} 1266 1267void afxConstraintMgr::removeScopeableObject(SceneObject* object) 1268{ 1269 for (S32 i = 0; i < scopeable_objs.size(); i++) 1270 if (scopeable_objs[i] == object) 1271 { 1272 object->removeScopeRef(); 1273 scopeable_objs.erase_fast(i); 1274 return; 1275 } 1276} 1277 1278void afxConstraintMgr::clearAllScopeableObjs() 1279{ 1280 for (S32 i = 0; i < scopeable_objs.size(); i++) 1281 scopeable_objs[i]->removeScopeRef(); 1282 scopeable_objs.clear(); 1283} 1284 1285void afxConstraintMgr::postMissingConstraintObject(afxConstraint* cons, bool is_deleting) 1286{ 1287 if (cons->mGone_missing) 1288 return; 1289 1290 if (!is_deleting) 1291 { 1292 SceneObject* obj = arcaneFX::findScopedObject(cons->getScopeId()); 1293 if (obj) 1294 { 1295 cons->restoreObject(obj); 1296 return; 1297 } 1298 } 1299 1300 cons->mGone_missing = true; 1301 missing_objs->push_back(cons); 1302} 1303 1304void afxConstraintMgr::restoreScopedObject(SceneObject* obj, afxChoreographer* ch) 1305{ 1306 for (S32 i = 0; i < missing_objs->size(); i++) 1307 { 1308 if ((*missing_objs)[i]->getScopeId() == obj->getScopeId()) 1309 { 1310 (*missing_objs)[i]->mGone_missing = false; 1311 (*missing_objs)[i]->restoreObject(obj); 1312 if (ch) 1313 ch->restoreObject(obj); 1314 } 1315 else 1316 missing_objs2->push_back((*missing_objs)[i]); 1317 } 1318 1319 Vector<afxConstraint*>* tmp = missing_objs; 1320 missing_objs = missing_objs2; 1321 missing_objs2 = tmp; 1322 missing_objs2->clear(); 1323} 1324 1325void afxConstraintMgr::adjustProcessOrdering(afxChoreographer* ch) 1326{ 1327 Vector<ProcessObject*> cons_sources; 1328 1329 // add choreographer to the list 1330 cons_sources.push_back(ch); 1331 1332 // collect all the ProcessObject related constraint sources 1333 for (S32 i = 0; i < mConstraints_v.size(); i++) 1334 { 1335 afxConstraintList* list = mConstraints_v[i]; 1336 afxConstraint* cons = (*list)[0]; 1337 if (cons) 1338 { 1339 ProcessObject* pobj = dynamic_cast<ProcessObject*>(cons->getSceneObject()); 1340 if (pobj) 1341 cons_sources.push_back(pobj); 1342 } 1343 } 1344 1345 ProcessList* proc_list; 1346 if (ch->isServerObject()) 1347 proc_list = ServerProcessList::get(); 1348 else 1349 proc_list = ClientProcessList::get(); 1350 if (!proc_list) 1351 return; 1352 1353 GameBase* nearest_to_end = dynamic_cast<GameBase*>(proc_list->findNearestToEnd(cons_sources)); 1354 GameBase* chor = (GameBase*) ch; 1355 1356 // choreographer needs to be processed after the latest process object 1357 if (chor != nearest_to_end && nearest_to_end != 0) 1358 { 1359 //Con::printf("Choreographer processing BEFORE some of its constraints... fixing. [%s] -- %s", 1360 // (ch->isServerObject()) ? "S" : "C", nearest_to_end->getClassName()); 1361 if (chor->isProperlyAdded()) 1362 ch->processAfter(nearest_to_end); 1363 else 1364 ch->postProcessAfterObject(nearest_to_end); 1365 } 1366 else 1367 { 1368 //Con::printf("Choreographer processing AFTER its constraints... fine. [%s]", 1369 // (ch->isServerObject()) ? "S" : "C"); 1370 } 1371} 1372 1373//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1374// afxPointConstraint 1375 1376afxPointConstraint::afxPointConstraint(afxConstraintMgr* mgr) 1377 : afxConstraint(mgr) 1378{ 1379 mPoint.zero(); 1380 mVector.set(0,0,1); 1381} 1382 1383afxPointConstraint::~afxPointConstraint() 1384{ 1385} 1386 1387void afxPointConstraint::set(Point3F point, Point3F vector) 1388{ 1389 mPoint = point; 1390 mVector = vector; 1391 mIs_defined = true; 1392 mIs_valid = true; 1393 mChange_code++; 1394 sample(0.0f, 0, 0); 1395} 1396 1397void afxPointConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 1398{ 1399 if (cam_pos) 1400 { 1401 Point3F dir = (*cam_pos) - mPoint; 1402 F32 dist_sq = dir.lenSquared(); 1403 if (dist_sq > mMgr->getScopingDistanceSquared()) 1404 { 1405 mIs_valid = false; 1406 return; 1407 } 1408 mIs_valid = true; 1409 } 1410 1411 mLast_pos = mPoint; 1412 mLast_xfm.identity(); 1413 mLast_xfm.setPosition(mPoint); 1414} 1415 1416//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1417// afxTransformConstraint 1418 1419afxTransformConstraint::afxTransformConstraint(afxConstraintMgr* mgr) 1420 : afxConstraint(mgr) 1421{ 1422 mXfm.identity(); 1423} 1424 1425afxTransformConstraint::~afxTransformConstraint() 1426{ 1427} 1428 1429void afxTransformConstraint::set(const MatrixF& xfm) 1430{ 1431 mXfm = xfm; 1432 mIs_defined = true; 1433 mIs_valid = true; 1434 mChange_code++; 1435 sample(0.0f, 0, 0); 1436} 1437 1438void afxTransformConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 1439{ 1440 if (cam_pos) 1441 { 1442 Point3F dir = (*cam_pos) - mXfm.getPosition(); 1443 F32 dist_sq = dir.lenSquared(); 1444 if (dist_sq > mMgr->getScopingDistanceSquared()) 1445 { 1446 mIs_valid = false; 1447 return; 1448 } 1449 mIs_valid = true; 1450 } 1451 1452 mLast_xfm = mXfm; 1453 mLast_pos = mXfm.getPosition(); 1454} 1455 1456//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1457// afxShapeConstraint 1458 1459afxShapeConstraint::afxShapeConstraint(afxConstraintMgr* mgr) 1460 : afxConstraint(mgr) 1461{ 1462 mArb_name = ST_NULLSTRING; 1463 mShape = 0; 1464 mScope_id = 0; 1465 mClip_tag = 0; 1466 mLock_tag = 0; 1467} 1468 1469afxShapeConstraint::afxShapeConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name) 1470 : afxConstraint(mgr) 1471{ 1472 mArb_name = arb_name; 1473 mShape = 0; 1474 mScope_id = 0; 1475 mClip_tag = 0; 1476 mLock_tag = 0; 1477} 1478 1479afxShapeConstraint::~afxShapeConstraint() 1480{ 1481 if (mShape) 1482 clearNotify(mShape); 1483} 1484 1485void afxShapeConstraint::set(ShapeBase* shape) 1486{ 1487 if (mShape) 1488 { 1489 mScope_id = 0; 1490 clearNotify(mShape); 1491 if (mClip_tag > 0) 1492 remapAnimation(mClip_tag, shape); 1493 if (mLock_tag > 0) 1494 unlockAnimation(mLock_tag); 1495 } 1496 1497 mShape = shape; 1498 1499 if (mShape) 1500 { 1501 deleteNotify(mShape); 1502 mScope_id = mShape->getScopeId(); 1503 } 1504 1505 if (mShape != NULL) 1506 { 1507 mIs_defined = true; 1508 mIs_valid = true; 1509 mChange_code++; 1510 sample(0.0f, 0, 0); 1511 } 1512 else 1513 mIs_valid = false; 1514} 1515 1516void afxShapeConstraint::set_scope_id(U16 scope_id) 1517{ 1518 if (mShape) 1519 clearNotify(mShape); 1520 1521 mShape = 0; 1522 mScope_id = scope_id; 1523 1524 mIs_defined = (mScope_id > 0); 1525 mIs_valid = false; 1526 mMgr->postMissingConstraintObject(this); 1527} 1528 1529void afxShapeConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 1530{ 1531 if (mGone_missing) 1532 return; 1533 1534 if (mShape) 1535 { 1536 mLast_xfm = mShape->getRenderTransform(); 1537 if (mCons_def.mPos_at_box_center) 1538 mLast_pos = mShape->getBoxCenter(); 1539 else 1540 mLast_pos = mShape->getRenderPosition(); 1541 } 1542} 1543 1544void afxShapeConstraint::restoreObject(SceneObject* obj) 1545{ 1546 if (mShape) 1547 { 1548 mScope_id = 0; 1549 clearNotify(mShape); 1550 } 1551 1552 mShape = (ShapeBase* )obj; 1553 1554 if (mShape) 1555 { 1556 deleteNotify(mShape); 1557 mScope_id = mShape->getScopeId(); 1558 } 1559 1560 mIs_valid = (mShape != NULL); 1561} 1562 1563void afxShapeConstraint::onDeleteNotify(SimObject* obj) 1564{ 1565 if (mShape == dynamic_cast<ShapeBase*>(obj)) 1566 { 1567 mShape = 0; 1568 mIs_valid = false; 1569 if (mScope_id > 0) 1570 mMgr->postMissingConstraintObject(this, true); 1571 } 1572 1573 Parent::onDeleteNotify(obj); 1574} 1575 1576U32 afxShapeConstraint::setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans, bool is_death_anim) 1577{ 1578 if (!mShape) 1579 return 0; 1580 1581 if (mShape->isServerObject()) 1582 { 1583 AIPlayer* ai_player = dynamic_cast<AIPlayer*>(mShape); 1584 if (ai_player && !ai_player->isBlendAnimation(clip)) 1585 { 1586 ai_player->saveMoveState(); 1587 ai_player->stopMove(); 1588 } 1589 } 1590 1591 mClip_tag = mShape->playAnimation(clip, pos, rate, trans, false/*hold*/, true/*wait*/, is_death_anim); 1592 return mClip_tag; 1593} 1594 1595void afxShapeConstraint::remapAnimation(U32 tag, ShapeBase* other_shape) 1596{ 1597 if (mClip_tag == 0) 1598 return; 1599 1600 if (!mShape) 1601 return; 1602 1603 if (!other_shape) 1604 { 1605 resetAnimation(tag); 1606 return; 1607 } 1608 1609 Con::errorf("remapAnimation -- Clip name, %s.", mShape->getLastClipName(tag)); 1610 1611 if (mShape->isClientObject()) 1612 { 1613 mShape->restoreAnimation(tag); 1614 } 1615 else 1616 { 1617 AIPlayer* ai_player = dynamic_cast<AIPlayer*>(mShape); 1618 if (ai_player) 1619 ai_player->restartMove(tag); 1620 else 1621 mShape->restoreAnimation(tag); 1622 } 1623 1624 mClip_tag = 0; 1625} 1626 1627void afxShapeConstraint::resetAnimation(U32 tag) 1628{ 1629 if (mClip_tag == 0) 1630 return; 1631 1632 if (!mShape) 1633 return; 1634 1635 if (mShape->isClientObject()) 1636 { 1637 mShape->restoreAnimation(tag); 1638 } 1639 else 1640 { 1641 AIPlayer* ai_player = dynamic_cast<AIPlayer*>(mShape); 1642 if (ai_player) 1643 ai_player->restartMove(tag); 1644 else 1645 mShape->restoreAnimation(tag); 1646 } 1647 1648 if ((tag & 0x80000000) == 0 && tag == mClip_tag) 1649 mClip_tag = 0; 1650} 1651 1652U32 afxShapeConstraint::lockAnimation() 1653{ 1654 if (!mShape) 1655 return 0; 1656 1657 mLock_tag = mShape->lockAnimation(); 1658 return mLock_tag; 1659} 1660 1661void afxShapeConstraint::unlockAnimation(U32 tag) 1662{ 1663 if (mLock_tag == 0) 1664 return; 1665 1666 if (!mShape) 1667 return; 1668 1669 mShape->unlockAnimation(tag); 1670 mLock_tag = 0; 1671} 1672 1673F32 afxShapeConstraint::getAnimClipDuration(const char* clip) 1674{ 1675 return (mShape) ? mShape->getAnimationDuration(clip) : 0.0f; 1676} 1677 1678S32 afxShapeConstraint::getDamageState() 1679{ 1680 return (mShape) ? mShape->getDamageState() : -1; 1681} 1682 1683U32 afxShapeConstraint::getTriggers() 1684{ 1685 return (mShape) ? mShape->getShapeInstance()->getTriggerStateMask() : 0; 1686} 1687 1688//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1689// afxShapeNodeConstraint 1690 1691afxShapeNodeConstraint::afxShapeNodeConstraint(afxConstraintMgr* mgr) 1692 : afxShapeConstraint(mgr) 1693{ 1694 mArb_node = ST_NULLSTRING; 1695 mShape_node_ID = -1; 1696} 1697 1698afxShapeNodeConstraint::afxShapeNodeConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name, StringTableEntry arb_node) 1699 : afxShapeConstraint(mgr, arb_name) 1700{ 1701 mArb_node = arb_node; 1702 mShape_node_ID = -1; 1703} 1704 1705void afxShapeNodeConstraint::set(ShapeBase* shape) 1706{ 1707 if (shape) 1708 { 1709 mShape_node_ID = shape->getShape()->findNode(mArb_node); 1710 if (mShape_node_ID == -1) 1711 Con::errorf("Failed to find node [%s]", mArb_node); 1712 } 1713 else 1714 mShape_node_ID = -1; 1715 1716 Parent::set(shape); 1717} 1718 1719void afxShapeNodeConstraint::set_scope_id(U16 scope_id) 1720{ 1721 mShape_node_ID = -1; 1722 Parent::set_scope_id(scope_id); 1723} 1724 1725void afxShapeNodeConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 1726{ 1727 if (mShape && mShape_node_ID != -1) 1728 { 1729 mLast_xfm = mShape->getRenderTransform(); 1730 mLast_xfm.scale(mShape->getScale()); 1731 mLast_xfm.mul(mShape->getShapeInstance()->mNodeTransforms[mShape_node_ID]); 1732 mLast_pos = mLast_xfm.getPosition(); 1733 } 1734} 1735 1736void afxShapeNodeConstraint::restoreObject(SceneObject* obj) 1737{ 1738 ShapeBase* shape = dynamic_cast<ShapeBase*>(obj); 1739 if (shape) 1740 { 1741 mShape_node_ID = shape->getShape()->findNode(mArb_node); 1742 if (mShape_node_ID == -1) 1743 Con::errorf("Failed to find node [%s]", mArb_node); 1744 } 1745 else 1746 mShape_node_ID = -1; 1747 Parent::restoreObject(obj); 1748} 1749 1750void afxShapeNodeConstraint::onDeleteNotify(SimObject* obj) 1751{ 1752 Parent::onDeleteNotify(obj); 1753} 1754 1755//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1756// afxObjectConstraint 1757 1758afxObjectConstraint::afxObjectConstraint(afxConstraintMgr* mgr) 1759 : afxConstraint(mgr) 1760{ 1761 mArb_name = ST_NULLSTRING; 1762 mObj = 0; 1763 mScope_id = 0; 1764 mIs_camera = false; 1765} 1766 1767afxObjectConstraint::afxObjectConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name) 1768 : afxConstraint(mgr) 1769{ 1770 mArb_name = arb_name; 1771 mObj = 0; 1772 mScope_id = 0; 1773 mIs_camera = false; 1774} 1775 1776afxObjectConstraint::~afxObjectConstraint() 1777{ 1778 if (mObj) 1779 clearNotify(mObj); 1780} 1781 1782void afxObjectConstraint::set(SceneObject* obj) 1783{ 1784 if (mObj) 1785 { 1786 mScope_id = 0; 1787 clearNotify(mObj); 1788 } 1789 1790 mObj = obj; 1791 1792 if (mObj) 1793 { 1794 deleteNotify(mObj); 1795 mScope_id = mObj->getScopeId(); 1796 } 1797 1798 if (mObj != NULL) 1799 { 1800 mIs_camera = mObj->isCamera(); 1801 1802 mIs_defined = true; 1803 mIs_valid = true; 1804 mChange_code++; 1805 sample(0.0f, 0, 0); 1806 } 1807 else 1808 mIs_valid = false; 1809} 1810 1811void afxObjectConstraint::set_scope_id(U16 scope_id) 1812{ 1813 if (mObj) 1814 clearNotify(mObj); 1815 1816 mObj = 0; 1817 mScope_id = scope_id; 1818 1819 mIs_defined = (scope_id > 0); 1820 mIs_valid = false; 1821 mMgr->postMissingConstraintObject(this); 1822} 1823 1824void afxObjectConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 1825{ 1826 if (mGone_missing) 1827 return; 1828 1829 if (mObj) 1830 { 1831 if (!mIs_camera && mCons_def.mTreat_as_camera && dynamic_cast<ShapeBase*>(mObj)) 1832 { 1833 ShapeBase* cam_obj = (ShapeBase*) mObj; 1834 F32 pov = 1.0f; 1835 cam_obj->getCameraTransform(&pov, &mLast_xfm); 1836 mLast_xfm.getColumn(3, &mLast_pos); 1837 } 1838 else 1839 { 1840 mLast_xfm = mObj->getRenderTransform(); 1841 if (mCons_def.mPos_at_box_center) 1842 mLast_pos = mObj->getBoxCenter(); 1843 else 1844 mLast_pos = mObj->getRenderPosition(); 1845 } 1846 } 1847} 1848 1849void afxObjectConstraint::restoreObject(SceneObject* obj) 1850{ 1851 if (mObj) 1852 { 1853 mScope_id = 0; 1854 clearNotify(mObj); 1855 } 1856 1857 mObj = obj; 1858 1859 if (mObj) 1860 { 1861 deleteNotify(mObj); 1862 mScope_id = mObj->getScopeId(); 1863 } 1864 1865 mIs_valid = (mObj != NULL); 1866} 1867 1868void afxObjectConstraint::onDeleteNotify(SimObject* obj) 1869{ 1870 if (mObj == dynamic_cast<SceneObject*>(obj)) 1871 { 1872 mObj = 0; 1873 mIs_valid = false; 1874 if (mScope_id > 0) 1875 mMgr->postMissingConstraintObject(this, true); 1876 } 1877 1878 Parent::onDeleteNotify(obj); 1879} 1880 1881U32 afxObjectConstraint::getTriggers() 1882{ 1883 TSStatic* ts_static = dynamic_cast<TSStatic*>(mObj); 1884 if (ts_static) 1885 { 1886 TSShapeInstance* obj_inst = ts_static->getShapeInstance(); 1887 return (obj_inst) ? obj_inst->getTriggerStateMask() : 0; 1888 } 1889 1890 ShapeBase* shape_base = dynamic_cast<ShapeBase*>(mObj); 1891 if (shape_base) 1892 { 1893 TSShapeInstance* obj_inst = shape_base->getShapeInstance(); 1894 return (obj_inst) ? obj_inst->getTriggerStateMask() : 0; 1895 } 1896 1897 return 0; 1898} 1899 1900//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1901// afxEffectConstraint 1902 1903afxEffectConstraint::afxEffectConstraint(afxConstraintMgr* mgr) 1904 : afxConstraint(mgr) 1905{ 1906 mEffect_name = ST_NULLSTRING; 1907 mEffect = 0; 1908 mClip_tag = 0; 1909 mIs_death_clip = false; 1910 mLock_tag = 0; 1911} 1912 1913afxEffectConstraint::afxEffectConstraint(afxConstraintMgr* mgr, StringTableEntry effect_name) 1914 : afxConstraint(mgr) 1915{ 1916 mEffect_name = effect_name; 1917 mEffect = 0; 1918 mClip_tag = 0; 1919 mIs_death_clip = false; 1920 mLock_tag = 0; 1921} 1922 1923afxEffectConstraint::~afxEffectConstraint() 1924{ 1925} 1926 1927bool afxEffectConstraint::getPosition(Point3F& pos, F32 hist) 1928{ 1929 if (!mEffect || !mEffect->inScope()) 1930 return false; 1931 1932 if (mCons_def.mPos_at_box_center) 1933 mEffect->getUpdatedBoxCenter(pos); 1934 else 1935 mEffect->getUpdatedPosition(pos); 1936 1937 return true; 1938} 1939 1940bool afxEffectConstraint::getTransform(MatrixF& xfm, F32 hist) 1941{ 1942 if (!mEffect || !mEffect->inScope()) 1943 return false; 1944 1945 mEffect->getUpdatedTransform(xfm); 1946 return true; 1947} 1948 1949bool afxEffectConstraint::getAltitudes(F32& terrain_alt, F32& interior_alt) 1950{ 1951 if (!mEffect) 1952 return false; 1953 1954 mEffect->getAltitudes(terrain_alt, interior_alt); 1955 return true; 1956} 1957 1958void afxEffectConstraint::set(afxEffectWrapper* effect) 1959{ 1960 mEffect = effect; 1961 1962 if (mEffect != NULL) 1963 { 1964 mIs_defined = true; 1965 mIs_valid = true; 1966 mChange_code++; 1967 } 1968 else 1969 mIs_valid = false; 1970} 1971 1972U32 afxEffectConstraint::setAnimClip(const char* clip, F32 pos, F32 rate, F32 trans, bool is_death_anim) 1973{ 1974 return (mEffect) ? mEffect->setAnimClip(clip, pos, rate, trans) : 0; 1975} 1976 1977void afxEffectConstraint::resetAnimation(U32 tag) 1978{ 1979 if (mEffect) 1980 mEffect->resetAnimation(tag); 1981} 1982 1983F32 afxEffectConstraint::getAnimClipDuration(const char* clip) 1984{ 1985 return (mEffect) ? getAnimClipDuration(clip) : 0; 1986} 1987 1988U32 afxEffectConstraint::getTriggers() 1989{ 1990 return (mEffect) ? mEffect->getTriggers() : 0; 1991} 1992 1993//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1994// afxEffectNodeConstraint 1995 1996afxEffectNodeConstraint::afxEffectNodeConstraint(afxConstraintMgr* mgr) 1997 : afxEffectConstraint(mgr) 1998{ 1999 mEffect_node = ST_NULLSTRING; 2000 mEffect_node_ID = -1; 2001} 2002 2003afxEffectNodeConstraint::afxEffectNodeConstraint(afxConstraintMgr* mgr, StringTableEntry name, StringTableEntry node) 2004: afxEffectConstraint(mgr, name) 2005{ 2006 mEffect_node = node; 2007 mEffect_node_ID = -1; 2008} 2009 2010 2011 2012bool afxEffectNodeConstraint::getPosition(Point3F& pos, F32 hist) 2013{ 2014 if (!mEffect || !mEffect->inScope()) 2015 return false; 2016 2017 TSShapeInstance* ts_shape_inst = mEffect->getTSShapeInstance(); 2018 if (!ts_shape_inst) 2019 return false; 2020 2021 if (mEffect_node_ID == -1) 2022 { 2023 TSShape* ts_shape = mEffect->getTSShape(); 2024 mEffect_node_ID = (ts_shape) ? ts_shape->findNode(mEffect_node) : -1; 2025 } 2026 2027 if (mEffect_node_ID == -1) 2028 return false; 2029 2030 mEffect->getUpdatedTransform(mLast_xfm); 2031 2032 Point3F scale; 2033 mEffect->getUpdatedScale(scale); 2034 2035 MatrixF gag = ts_shape_inst->mNodeTransforms[mEffect_node_ID]; 2036 gag.setPosition( gag.getPosition()*scale ); 2037 2038 MatrixF xfm; 2039 xfm.mul(mLast_xfm, gag); 2040 // 2041 pos = xfm.getPosition(); 2042 2043 return true; 2044} 2045 2046bool afxEffectNodeConstraint::getTransform(MatrixF& xfm, F32 hist) 2047{ 2048 if (!mEffect || !mEffect->inScope()) 2049 return false; 2050 2051 TSShapeInstance* ts_shape_inst = mEffect->getTSShapeInstance(); 2052 if (!ts_shape_inst) 2053 return false; 2054 2055 if (mEffect_node_ID == -1) 2056 { 2057 TSShape* ts_shape = mEffect->getTSShape(); 2058 mEffect_node_ID = (ts_shape) ? ts_shape->findNode(mEffect_node) : -1; 2059 } 2060 2061 if (mEffect_node_ID == -1) 2062 return false; 2063 2064 mEffect->getUpdatedTransform(mLast_xfm); 2065 2066 Point3F scale; 2067 mEffect->getUpdatedScale(scale); 2068 2069 MatrixF gag = ts_shape_inst->mNodeTransforms[mEffect_node_ID]; 2070 gag.setPosition( gag.getPosition()*scale ); 2071 2072 xfm.mul(mLast_xfm, gag); 2073 2074 return true; 2075} 2076 2077void afxEffectNodeConstraint::set(afxEffectWrapper* effect) 2078{ 2079 if (effect) 2080 { 2081 TSShape* ts_shape = effect->getTSShape(); 2082 mEffect_node_ID = (ts_shape) ? ts_shape->findNode(mEffect_node) : -1; 2083 } 2084 else 2085 mEffect_node_ID = -1; 2086 2087 Parent::set(effect); 2088} 2089 2090//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2091// afxSampleBuffer 2092 2093afxSampleBuffer::afxSampleBuffer() 2094{ 2095 mBuffer_sz = 0; 2096 mBuffer_ms = 0; 2097 mMS_per_sample = 33; 2098 mElapsed_ms = 0; 2099 mLast_sample_ms = 0; 2100 mNext_sample_num = 0; 2101 mNum_samples = 0; 2102} 2103 2104afxSampleBuffer::~afxSampleBuffer() 2105{ 2106} 2107 2108void afxSampleBuffer::configHistory(F32 hist_len, U8 sample_rate) 2109{ 2110 mBuffer_sz = mCeil(hist_len*sample_rate) + 1; 2111 mMS_per_sample = mCeil(1000.0f/sample_rate); 2112 mBuffer_ms = mBuffer_sz*mMS_per_sample; 2113} 2114 2115void afxSampleBuffer::recordSample(F32 dt, U32 elapsed_ms, void* data) 2116{ 2117 mElapsed_ms = elapsed_ms; 2118 2119 if (!data) 2120 return; 2121 2122 U32 now_sample_num = elapsed_ms/<a href="/coding/class/classafxsamplebuffer/#classafxsamplebuffer_1a366a1ad057f2e72aa3743bd7303454e0">mMS_per_sample</a>; 2123 if (mNext_sample_num <= now_sample_num) 2124 { 2125 mLast_sample_ms = elapsed_ms; 2126 while (mNext_sample_num <= now_sample_num) 2127 { 2128 recSample(mNext_sample_num % mBuffer_sz, data); 2129 mNext_sample_num++; 2130 mNum_samples++; 2131 } 2132 } 2133} 2134 2135inline bool afxSampleBuffer::compute_idx_from_lag(F32 lag, U32& idx) 2136{ 2137 bool in_bounds = true; 2138 2139 U32 lag_ms = lag*1000.0f; 2140 U32 rec_ms = (mElapsed_ms < mBuffer_ms) ? mElapsed_ms : mBuffer_ms; 2141 if (lag_ms > rec_ms) 2142 { 2143 // hasn't produced enough history 2144 lag_ms = rec_ms; 2145 in_bounds = false; 2146 } 2147 2148 U32 latest_sample_num = mLast_sample_ms/<a href="/coding/class/classafxsamplebuffer/#classafxsamplebuffer_1a366a1ad057f2e72aa3743bd7303454e0">mMS_per_sample</a>; 2149 U32 then_sample_num = (mElapsed_ms - lag_ms)/<a href="/coding/class/classafxsamplebuffer/#classafxsamplebuffer_1a366a1ad057f2e72aa3743bd7303454e0">mMS_per_sample</a>; 2150 2151 if (then_sample_num > latest_sample_num) 2152 { 2153 // latest sample is older than lag 2154 then_sample_num = latest_sample_num; 2155 in_bounds = false; 2156 } 2157 2158 idx = then_sample_num % mBuffer_sz; 2159 return in_bounds; 2160} 2161 2162inline bool afxSampleBuffer::compute_idx_from_lag(F32 lag, U32& idx1, U32& idx2, F32& t) 2163{ 2164 bool in_bounds = true; 2165 2166 F32 lag_ms = lag*1000.0f; 2167 F32 rec_ms = (mElapsed_ms < mBuffer_ms) ? mElapsed_ms : mBuffer_ms; 2168 if (lag_ms > rec_ms) 2169 { 2170 // hasn't produced enough history 2171 lag_ms = rec_ms; 2172 in_bounds = false; 2173 } 2174 2175 F32 per_samp = mMS_per_sample; 2176 F32 latest_sample_num = mLast_sample_ms/per_samp; 2177 F32 then_sample_num = (mElapsed_ms - lag_ms)/per_samp; 2178 2179 U32 latest_sample_num_i = latest_sample_num; 2180 U32 then_sample_num_i = then_sample_num; 2181 2182 if (then_sample_num_i >= latest_sample_num_i) 2183 { 2184 if (latest_sample_num_i < then_sample_num_i) 2185 in_bounds = false; 2186 t = 0.0; 2187 idx1 = then_sample_num_i % mBuffer_sz; 2188 idx2 = idx1; 2189 } 2190 else 2191 { 2192 t = then_sample_num - then_sample_num_i; 2193 idx1 = then_sample_num_i % mBuffer_sz; 2194 idx2 = (then_sample_num_i+1) % mBuffer_sz; 2195 } 2196 2197 return in_bounds; 2198} 2199 2200//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2201// afxSampleXfmBuffer 2202 2203afxSampleXfmBuffer::afxSampleXfmBuffer() 2204{ 2205 mXfm_buffer = 0; 2206} 2207 2208afxSampleXfmBuffer::~afxSampleXfmBuffer() 2209{ 2210 delete [] mXfm_buffer; 2211} 2212 2213void afxSampleXfmBuffer::configHistory(F32 hist_len, U8 sample_rate) 2214{ 2215 if (!mXfm_buffer) 2216 { 2217 afxSampleBuffer::configHistory(hist_len, sample_rate); 2218 if (mBuffer_sz > 0) 2219 mXfm_buffer = new MatrixF[mBuffer_sz]; 2220 } 2221} 2222 2223void afxSampleXfmBuffer::recSample(U32 idx, void* data) 2224{ 2225 mXfm_buffer[idx] = *((MatrixF*)data); 2226} 2227 2228void afxSampleXfmBuffer::getSample(F32 lag, void* data, bool& in_bounds) 2229{ 2230 U32 idx1, idx2; 2231 F32 t; 2232 in_bounds = compute_idx_from_lag(lag, idx1, idx2, t); 2233 2234 if (idx1 == idx2) 2235 { 2236 MatrixF* m1 = &mXfm_buffer[idx1]; 2237 *((MatrixF*)data) = *m1; 2238 } 2239 else 2240 { 2241 MatrixF* m1 = &mXfm_buffer[idx1]; 2242 MatrixF* m2 = &mXfm_buffer[idx2]; 2243 2244 Point3F p1 = m1->getPosition(); 2245 Point3F p2 = m2->getPosition(); 2246 Point3F p; p.interpolate(p1, p2, t); 2247 2248 if (t < 0.5f) 2249 *((MatrixF*)data) = *m1; 2250 else 2251 *((MatrixF*)data) = *m2; 2252 2253 ((MatrixF*)data)->setPosition(p); 2254 } 2255} 2256 2257//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2258// afxPointHistConstraint 2259 2260afxPointHistConstraint::afxPointHistConstraint(afxConstraintMgr* mgr) 2261 : afxPointConstraint(mgr) 2262{ 2263 mSamples = 0; 2264} 2265 2266afxPointHistConstraint::~afxPointHistConstraint() 2267{ 2268 delete mSamples; 2269} 2270 2271void afxPointHistConstraint::set(Point3F point, Point3F vector) 2272{ 2273 if (!mSamples) 2274 { 2275 mSamples = new afxSampleXfmBuffer; 2276 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2277 } 2278 2279 Parent::set(point, vector); 2280} 2281 2282void afxPointHistConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 2283{ 2284 Parent::sample(dt, elapsed_ms, cam_pos); 2285 2286 if (isDefined()) 2287 { 2288 if (isValid()) 2289 mSamples->recordSample(dt, elapsed_ms, &mLast_xfm); 2290 else 2291 mSamples->recordSample(dt, elapsed_ms, 0); 2292 } 2293} 2294 2295bool afxPointHistConstraint::getPosition(Point3F& pos, F32 hist) 2296{ 2297 bool in_bounds; 2298 2299 MatrixF xfm; 2300 mSamples->getSample(hist, &xfm, in_bounds); 2301 2302 pos = xfm.getPosition(); 2303 2304 return in_bounds; 2305} 2306 2307bool afxPointHistConstraint::getTransform(MatrixF& xfm, F32 hist) 2308{ 2309 bool in_bounds; 2310 2311 mSamples->getSample(hist, &xfm, in_bounds); 2312 2313 return in_bounds; 2314} 2315 2316//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2317// afxPointHistConstraint 2318 2319afxTransformHistConstraint::afxTransformHistConstraint(afxConstraintMgr* mgr) 2320 : afxTransformConstraint(mgr) 2321{ 2322 mSamples = 0; 2323} 2324 2325afxTransformHistConstraint::~afxTransformHistConstraint() 2326{ 2327 delete mSamples; 2328} 2329 2330void afxTransformHistConstraint::set(const MatrixF& xfm) 2331{ 2332 if (!mSamples) 2333 { 2334 mSamples = new afxSampleXfmBuffer; 2335 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2336 } 2337 2338 Parent::set(xfm); 2339} 2340 2341void afxTransformHistConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 2342{ 2343 Parent::sample(dt, elapsed_ms, cam_pos); 2344 2345 if (isDefined()) 2346 { 2347 if (isValid()) 2348 mSamples->recordSample(dt, elapsed_ms, &mLast_xfm); 2349 else 2350 mSamples->recordSample(dt, elapsed_ms, 0); 2351 } 2352} 2353 2354bool afxTransformHistConstraint::getPosition(Point3F& pos, F32 hist) 2355{ 2356 bool in_bounds; 2357 2358 MatrixF xfm; 2359 mSamples->getSample(hist, &xfm, in_bounds); 2360 2361 pos = xfm.getPosition(); 2362 2363 return in_bounds; 2364} 2365 2366bool afxTransformHistConstraint::getTransform(MatrixF& xfm, F32 hist) 2367{ 2368 bool in_bounds; 2369 2370 mSamples->getSample(hist, &xfm, in_bounds); 2371 2372 return in_bounds; 2373} 2374 2375//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2376// afxShapeHistConstraint 2377 2378afxShapeHistConstraint::afxShapeHistConstraint(afxConstraintMgr* mgr) 2379 : afxShapeConstraint(mgr) 2380{ 2381 mSamples = 0; 2382} 2383 2384afxShapeHistConstraint::afxShapeHistConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name) 2385 : afxShapeConstraint(mgr, arb_name) 2386{ 2387 mSamples = 0; 2388} 2389 2390afxShapeHistConstraint::~afxShapeHistConstraint() 2391{ 2392 delete mSamples; 2393} 2394 2395void afxShapeHistConstraint::set(ShapeBase* shape) 2396{ 2397 if (shape && !mSamples) 2398 { 2399 mSamples = new afxSampleXfmBuffer; 2400 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2401 } 2402 2403 Parent::set(shape); 2404} 2405 2406void afxShapeHistConstraint::set_scope_id(U16 scope_id) 2407{ 2408 if (scope_id > 0 && !mSamples) 2409 { 2410 mSamples = new afxSampleXfmBuffer; 2411 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2412 } 2413 2414 Parent::set_scope_id(scope_id); 2415} 2416 2417void afxShapeHistConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 2418{ 2419 Parent::sample(dt, elapsed_ms, cam_pos); 2420 2421 if (isDefined()) 2422 { 2423 if (isValid()) 2424 mSamples->recordSample(dt, elapsed_ms, &mLast_xfm); 2425 else 2426 mSamples->recordSample(dt, elapsed_ms, 0); 2427 } 2428} 2429 2430bool afxShapeHistConstraint::getPosition(Point3F& pos, F32 hist) 2431{ 2432 bool in_bounds; 2433 2434 MatrixF xfm; 2435 mSamples->getSample(hist, &xfm, in_bounds); 2436 2437 pos = xfm.getPosition(); 2438 2439 return in_bounds; 2440} 2441 2442bool afxShapeHistConstraint::getTransform(MatrixF& xfm, F32 hist) 2443{ 2444 bool in_bounds; 2445 2446 mSamples->getSample(hist, &xfm, in_bounds); 2447 2448 return in_bounds; 2449} 2450 2451void afxShapeHistConstraint::onDeleteNotify(SimObject* obj) 2452{ 2453 Parent::onDeleteNotify(obj); 2454} 2455 2456//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2457// afxShapeNodeHistConstraint 2458 2459afxShapeNodeHistConstraint::afxShapeNodeHistConstraint(afxConstraintMgr* mgr) 2460 : afxShapeNodeConstraint(mgr) 2461{ 2462 mSamples = 0; 2463} 2464 2465afxShapeNodeHistConstraint::afxShapeNodeHistConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name, 2466 StringTableEntry arb_node) 2467 : afxShapeNodeConstraint(mgr, arb_name, arb_node) 2468{ 2469 mSamples = 0; 2470} 2471 2472afxShapeNodeHistConstraint::~afxShapeNodeHistConstraint() 2473{ 2474 delete mSamples; 2475} 2476 2477void afxShapeNodeHistConstraint::set(ShapeBase* shape) 2478{ 2479 if (shape && !mSamples) 2480 { 2481 mSamples = new afxSampleXfmBuffer; 2482 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2483 } 2484 2485 Parent::set(shape); 2486} 2487 2488void afxShapeNodeHistConstraint::set_scope_id(U16 scope_id) 2489{ 2490 if (scope_id > 0 && !mSamples) 2491 { 2492 mSamples = new afxSampleXfmBuffer; 2493 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2494 } 2495 2496 Parent::set_scope_id(scope_id); 2497} 2498 2499void afxShapeNodeHistConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 2500{ 2501 Parent::sample(dt, elapsed_ms, cam_pos); 2502 2503 if (isDefined()) 2504 { 2505 if (isValid()) 2506 mSamples->recordSample(dt, elapsed_ms, &mLast_xfm); 2507 else 2508 mSamples->recordSample(dt, elapsed_ms, 0); 2509 } 2510} 2511 2512bool afxShapeNodeHistConstraint::getPosition(Point3F& pos, F32 hist) 2513{ 2514 bool in_bounds; 2515 2516 MatrixF xfm; 2517 mSamples->getSample(hist, &xfm, in_bounds); 2518 2519 pos = xfm.getPosition(); 2520 2521 return in_bounds; 2522} 2523 2524bool afxShapeNodeHistConstraint::getTransform(MatrixF& xfm, F32 hist) 2525{ 2526 bool in_bounds; 2527 2528 mSamples->getSample(hist, &xfm, in_bounds); 2529 2530 return in_bounds; 2531} 2532 2533void afxShapeNodeHistConstraint::onDeleteNotify(SimObject* obj) 2534{ 2535 Parent::onDeleteNotify(obj); 2536} 2537 2538//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2539// afxObjectHistConstraint 2540 2541afxObjectHistConstraint::afxObjectHistConstraint(afxConstraintMgr* mgr) 2542 : afxObjectConstraint(mgr) 2543{ 2544 mSamples = 0; 2545} 2546 2547afxObjectHistConstraint::afxObjectHistConstraint(afxConstraintMgr* mgr, StringTableEntry arb_name) 2548 : afxObjectConstraint(mgr, arb_name) 2549{ 2550 mSamples = 0; 2551} 2552 2553afxObjectHistConstraint::~afxObjectHistConstraint() 2554{ 2555 delete mSamples; 2556} 2557 2558void afxObjectHistConstraint::set(SceneObject* obj) 2559{ 2560 if (obj && !mSamples) 2561 { 2562 mSamples = new afxSampleXfmBuffer; 2563 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2564 } 2565 2566 Parent::set(obj); 2567} 2568 2569void afxObjectHistConstraint::set_scope_id(U16 scope_id) 2570{ 2571 if (scope_id > 0 && !mSamples) 2572 { 2573 mSamples = new afxSampleXfmBuffer; 2574 mSamples->configHistory(mCons_def.mHistory_time, mCons_def.mSample_rate); 2575 } 2576 2577 Parent::set_scope_id(scope_id); 2578} 2579 2580void afxObjectHistConstraint::sample(F32 dt, U32 elapsed_ms, const Point3F* cam_pos) 2581{ 2582 Parent::sample(dt, elapsed_ms, cam_pos); 2583 2584 if (isDefined()) 2585 { 2586 if (isValid()) 2587 mSamples->recordSample(dt, elapsed_ms, &mLast_xfm); 2588 else 2589 mSamples->recordSample(dt, elapsed_ms, 0); 2590 } 2591} 2592 2593bool afxObjectHistConstraint::getPosition(Point3F& pos, F32 hist) 2594{ 2595 bool in_bounds; 2596 2597 MatrixF xfm; 2598 mSamples->getSample(hist, &xfm, in_bounds); 2599 2600 pos = xfm.getPosition(); 2601 2602 return in_bounds; 2603} 2604 2605bool afxObjectHistConstraint::getTransform(MatrixF& xfm, F32 hist) 2606{ 2607 bool in_bounds; 2608 2609 mSamples->getSample(hist, &xfm, in_bounds); 2610 2611 return in_bounds; 2612} 2613 2614void afxObjectHistConstraint::onDeleteNotify(SimObject* obj) 2615{ 2616 Parent::onDeleteNotify(obj); 2617} 2618 2619//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 2620 2621