SWF_SpriteInstance.cpp (40392B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 #pragma hdrstop 29 #include "../idlib/precompiled.h" 30 31 idSWFScriptObject_SpriteInstancePrototype spriteInstanceScriptObjectPrototype; 32 33 /* 34 ======================== 35 idSWFSpriteInstance::idSWFSpriteInstance 36 ======================== 37 */ 38 idSWFSpriteInstance::idSWFSpriteInstance() : 39 sprite( NULL ), 40 parent( NULL ), 41 depth( 0 ), 42 isPlaying( true ), 43 isVisible( true ), 44 childrenRunning( true ), 45 currentFrame( 0 ), 46 itemIndex( 0 ), 47 materialOverride( NULL ), 48 materialWidth( 0 ), 49 materialHeight( 0 ), 50 xOffset( 0.0f ), 51 yOffset( 0.0f ), 52 moveToXScale( 1.0f ), 53 moveToYScale( 1.0f ), 54 moveToSpeed( 1.0f ), 55 firstRun( false ), 56 stereoDepth( 0 ) 57 { 58 } 59 60 /* 61 ======================== 62 idSWFSpriteInstance::Init 63 ======================== 64 */ 65 void idSWFSpriteInstance::Init( idSWFSprite * _sprite, idSWFSpriteInstance * _parent, int _depth ) { 66 sprite = _sprite; 67 parent = _parent; 68 depth = _depth; 69 70 frameCount = sprite->frameCount; 71 72 scriptObject = idSWFScriptObject::Alloc(); 73 scriptObject->SetPrototype( &spriteInstanceScriptObjectPrototype ); 74 scriptObject->SetSprite( this ); 75 76 firstRun = true; 77 78 actionScript = idSWFScriptFunction_Script::Alloc(); 79 80 idList<idSWFScriptObject *, TAG_SWF> scope; 81 scope.Append( sprite->swf->globals ); 82 scope.Append( scriptObject ); 83 actionScript->SetScope( scope ); 84 actionScript->SetDefaultSprite( this ); 85 86 for (int i = 0; i < sprite->doInitActions.Num(); i++) { 87 actionScript->SetData( sprite->doInitActions[i].Ptr(), sprite->doInitActions[i].Length() ); 88 actionScript->Call( scriptObject, idSWFParmList() ); 89 } 90 91 Play(); 92 } 93 94 /* 95 ======================== 96 idSWFSpriteInstance::~idSWFSpriteInstance 97 ======================== 98 */ 99 idSWFSpriteInstance::~idSWFSpriteInstance() { 100 if ( parent != NULL ) { 101 parent->scriptObject->Set( name, idSWFScriptVar() ); 102 } 103 FreeDisplayList(); 104 displayList.Clear(); 105 scriptObject->SetSprite( NULL ); 106 scriptObject->Clear(); 107 scriptObject->Release(); 108 actionScript->Release(); 109 } 110 111 /* 112 ======================== 113 idSWFSpriteInstance::FreeDisplayList 114 ======================== 115 */ 116 void idSWFSpriteInstance::FreeDisplayList() { 117 for ( int i = 0; i < displayList.Num(); i++ ) { 118 sprite->swf->spriteInstanceAllocator.Free( displayList[i].spriteInstance ); 119 sprite->swf->textInstanceAllocator.Free( displayList[i].textInstance ); 120 } 121 displayList.SetNum( 0 ); // not calling Clear() so we don't continuously re-allocate memory 122 currentFrame = 0; 123 } 124 125 /* 126 ======================== 127 idSWFSpriteInstance::FindDisplayEntry 128 ======================== 129 */ 130 swfDisplayEntry_t * idSWFSpriteInstance::FindDisplayEntry( int depth ) { 131 int len = displayList.Num(); 132 int mid = len; 133 int offset = 0; 134 while ( mid > 0 ) { 135 mid = len >> 1; 136 if ( displayList[offset+mid].depth <= depth ) { 137 offset += mid; 138 } 139 len -= mid; 140 } 141 if ( displayList[offset].depth == depth ) { 142 return &displayList[offset]; 143 } 144 return NULL; 145 } 146 147 /* 148 ======================== 149 idSWFSpriteInstance::AddDisplayEntry 150 ======================== 151 */ 152 swfDisplayEntry_t * idSWFSpriteInstance::AddDisplayEntry( int depth, int characterID ) { 153 int i = 0; 154 for ( ; i < displayList.Num(); i++ ) { 155 if ( displayList[i].depth == depth ) { 156 return NULL; 157 } 158 if ( displayList[i].depth > depth ) { 159 break; 160 } 161 } 162 163 swfDisplayEntry_t & display = displayList[ displayList.Insert( swfDisplayEntry_t(), i ) ]; 164 display.depth = depth; 165 display.characterID = characterID; 166 167 idSWFDictionaryEntry * dictEntry = sprite->swf->FindDictionaryEntry( characterID ); 168 if ( dictEntry != NULL ) { 169 if ( dictEntry->type == SWF_DICT_SPRITE ) { 170 display.spriteInstance = sprite->swf->spriteInstanceAllocator.Alloc(); 171 display.spriteInstance->Init( dictEntry->sprite, this, depth ); 172 display.spriteInstance->RunTo( 1 ); 173 } else if ( dictEntry->type == SWF_DICT_EDITTEXT ) { 174 display.textInstance = sprite->swf->textInstanceAllocator.Alloc(); 175 display.textInstance->Init( dictEntry->edittext, sprite->GetSWF() ); 176 } 177 } 178 return &display; 179 } 180 181 /* 182 ======================== 183 idSWFSpriteInstance::RemoveDisplayEntry 184 ======================== 185 */ 186 void idSWFSpriteInstance::RemoveDisplayEntry( int depth ) { 187 swfDisplayEntry_t * entry = FindDisplayEntry( depth ); 188 if ( entry != NULL ) { 189 sprite->swf->spriteInstanceAllocator.Free( entry->spriteInstance ); 190 sprite->swf->textInstanceAllocator.Free( entry->textInstance ); 191 displayList.RemoveIndex( displayList.IndexOf( entry ) ); 192 } 193 } 194 195 /* 196 ================================================ 197 idSort_SpriteDepth 198 ================================================ 199 */ 200 class idSort_SpriteDepth : public idSort_Quick< swfDisplayEntry_t, idSort_SpriteDepth > { 201 public: 202 int Compare( const swfDisplayEntry_t & a, const swfDisplayEntry_t & b ) const { return a.depth - b.depth; } 203 }; 204 205 /* 206 ======================== 207 idSWFSpriteInstance::SwapDepths 208 ======================== 209 */ 210 void idSWFSpriteInstance::SwapDepths( int depth1, int depth2 ) { 211 for ( int i = 0; i < displayList.Num(); i++ ) { 212 if ( displayList[i].depth == depth1 ) { 213 displayList[i].depth = depth2; 214 215 } else if ( displayList[i].depth == depth2 ) { 216 displayList[i].depth = depth1; 217 } 218 if ( displayList[i].spriteInstance != NULL ) { 219 displayList[i].spriteInstance->depth = displayList[i].depth; 220 } 221 } 222 223 displayList.SortWithTemplate( idSort_SpriteDepth() ); 224 } 225 226 /* 227 =================== 228 idSWFSpriteInstance::Run 229 =================== 230 */ 231 bool idSWFSpriteInstance::Run() { 232 if ( !isVisible ) { 233 return false; 234 } 235 236 if ( childrenRunning ) { 237 childrenRunning = false; 238 for ( int i = 0; i < displayList.Num(); i++ ) { 239 if ( displayList[i].spriteInstance != NULL ) { 240 Prefetch( displayList[i].spriteInstance, 0 ); 241 } 242 } 243 for ( int i = 0; i < displayList.Num(); i++ ) { 244 if ( displayList[i].spriteInstance != NULL ) { 245 childrenRunning |= displayList[i].spriteInstance->Run(); 246 } 247 } 248 } 249 if ( isPlaying ) { 250 if ( currentFrame == frameCount ) { 251 if ( frameCount > 1 ) { 252 FreeDisplayList(); 253 RunTo( 1 ); 254 } 255 } else { 256 RunTo( currentFrame + 1 ); 257 } 258 } 259 return childrenRunning || isPlaying; 260 } 261 262 /* 263 =================== 264 idSWFSpriteInstance::RunActions 265 =================== 266 */ 267 bool idSWFSpriteInstance::RunActions() { 268 if ( !isVisible ) { 269 actions.SetNum( 0 ); 270 return false; 271 } 272 273 if ( firstRun && scriptObject->HasProperty( "onLoad" ) ) { 274 firstRun = false; 275 idSWFScriptVar onLoad = scriptObject->Get( "onLoad" ); 276 onLoad.GetFunction()->Call( scriptObject, idSWFParmList() ); 277 } 278 279 if ( onEnterFrame.IsFunction() ) { 280 onEnterFrame.GetFunction()->Call( scriptObject, idSWFParmList() ); 281 } 282 283 for ( int i = 0; i < actions.Num(); i++ ) { 284 actionScript->SetData( actions[i].data, actions[i].dataLength ); 285 actionScript->Call( scriptObject, idSWFParmList() ); 286 } 287 actions.SetNum( 0 ); 288 289 for ( int i = 0; i < displayList.Num(); i++ ) { 290 if ( displayList[i].spriteInstance != NULL ) { 291 Prefetch( displayList[i].spriteInstance, 0 ); 292 } 293 } 294 for ( int i = 0; i < displayList.Num(); i++ ) { 295 if ( displayList[i].spriteInstance != NULL ) { 296 displayList[i].spriteInstance->RunActions(); 297 } 298 } 299 300 return true; 301 } 302 303 /* 304 =================== 305 idSWFSpriteInstance::NextFrame 306 =================== 307 */ 308 void idSWFSpriteInstance::NextFrame() { 309 if ( currentFrame < frameCount ) { 310 RunTo( currentFrame + 1 ); 311 } 312 } 313 314 /* 315 =================== 316 idSWFSpriteInstance::PrevFrame 317 =================== 318 */ 319 void idSWFSpriteInstance::PrevFrame() { 320 if ( currentFrame > 1 ) { 321 RunTo( currentFrame - 1 ); 322 } 323 } 324 325 /* 326 =================== 327 idSWFSpriteInstance::Play 328 =================== 329 */ 330 void idSWFSpriteInstance::Play() { 331 for ( idSWFSpriteInstance * p = parent; p != NULL; p = p->parent ) { 332 p->childrenRunning = true; 333 } 334 isPlaying = true; 335 } 336 337 /* 338 =================== 339 idSWFSpriteInstance::Stop 340 =================== 341 */ 342 void idSWFSpriteInstance::Stop() { 343 isPlaying = false; 344 } 345 346 /* 347 =================== 348 idSWFSpriteInstance::RunTo 349 =================== 350 */ 351 void idSWFSpriteInstance::RunTo( int targetFrame ) { 352 if ( targetFrame == currentFrame ) { 353 return; // otherwise we'll re-run the current frame 354 } 355 if ( targetFrame < currentFrame ) { 356 FreeDisplayList(); 357 } 358 if ( targetFrame < 1 ) { 359 return; 360 } 361 362 if ( targetFrame > sprite->frameOffsets.Num() - 1 ) { 363 targetFrame = sprite->frameOffsets.Num() - 1; 364 } 365 366 //actions.Clear(); 367 368 uint32 firstActionCommand = sprite->frameOffsets[ targetFrame - 1 ]; 369 370 for ( uint32 c = sprite->frameOffsets[ currentFrame ]; c < sprite->frameOffsets[ targetFrame ]; c++ ) { 371 idSWFSprite::swfSpriteCommand_t & command = sprite->commands[ c ]; 372 if ( command.tag == Tag_DoAction && c < firstActionCommand ) { 373 // Skip DoAction up to the firstActionCommand 374 // This is to properly support skipping to a specific frame 375 // for example if we're on frame 3 and skipping to frame 10, we want 376 // to run all the commands PlaceObject commands for frames 4-10 but 377 // only the DoAction commands for frame 10 378 continue; 379 } 380 command.stream.Rewind(); 381 switch ( command.tag ) { 382 #define HANDLE_SWF_TAG( x ) case Tag_##x: x( command.stream ); break; 383 HANDLE_SWF_TAG( PlaceObject2 ); 384 HANDLE_SWF_TAG( PlaceObject3 ); 385 HANDLE_SWF_TAG( RemoveObject2 ); 386 HANDLE_SWF_TAG( StartSound ); 387 HANDLE_SWF_TAG( DoAction ); 388 #undef HANDLE_SWF_TAG 389 default: 390 idLib::Printf( "Run Sprite: Unhandled tag %s\n", idSWF::GetTagName( command.tag ) ); 391 } 392 } 393 394 currentFrame = targetFrame; 395 } 396 397 /* 398 ======================== 399 idSWFSpriteInstance::DoAction 400 ======================== 401 */ 402 void idSWFSpriteInstance::DoAction( idSWFBitStream & bitstream ) { 403 swfAction_t & action = actions.Alloc(); 404 action.data = bitstream.ReadData( bitstream.Length() ); 405 action.dataLength = bitstream.Length(); 406 } 407 408 /* 409 ======================== 410 idSWFSpriteInstance::FindChildSprite 411 ======================== 412 */ 413 idSWFSpriteInstance * idSWFSpriteInstance::FindChildSprite( const char * targetName ) { 414 for ( int i = 0; i < displayList.Num(); i++ ) { 415 if ( displayList[i].spriteInstance != NULL ) { 416 if ( displayList[i].spriteInstance->name.Icmp( targetName ) == 0 ) { 417 return displayList[i].spriteInstance; 418 } 419 } 420 } 421 return NULL; 422 } 423 424 /* 425 ======================== 426 idSWFSpriteInstance::ResolveTarget 427 Gets the sprite instance for names like: 428 ../foo/bar 429 /foo/bar 430 foo/bar 431 ======================== 432 */ 433 idSWFSpriteInstance * idSWFSpriteInstance::ResolveTarget( const char * targetName ) { 434 if ( targetName[0] == 0 ) { 435 return this; 436 } 437 idSWFSpriteInstance * target = this; 438 const char * c = targetName; 439 if ( c[0] == '/' ) { 440 while ( target->parent != NULL ) { 441 target = target->parent; 442 } 443 c++; 444 } 445 idStrList spriteNames; 446 spriteNames.Append( c ); 447 for ( int index = 0, ofs = spriteNames[index].Find( '/' ); ofs != -1; index++, ofs = spriteNames[index].Find( '/' ) ) { 448 spriteNames.Append( spriteNames[index].c_str() + ofs + 1 ); 449 spriteNames[index].CapLength( ofs ); 450 } 451 for ( int i = 0; i < spriteNames.Num(); i++ ) { 452 if ( spriteNames[i] == ".." ) { 453 target = target->parent; 454 } else { 455 target = target->FindChildSprite( spriteNames[i] ); 456 } 457 if ( target == NULL ) { 458 // Everything is likely to fail after this point 459 idLib::Warning( "SWF: Could not resolve %s, %s not found", targetName, spriteNames[i].c_str() ); 460 return this; 461 } 462 } 463 return target; 464 } 465 466 /* 467 ======================== 468 idSWFSpriteInstance::FindFrame 469 ======================== 470 */ 471 uint32 idSWFSpriteInstance::FindFrame( const char * labelName ) const { 472 int frameNum = atoi( labelName ); 473 if ( frameNum > 0 ) { 474 return frameNum; 475 } 476 for ( int i = 0; i < sprite->frameLabels.Num(); i++ ) { 477 if ( sprite->frameLabels[i].frameLabel.Icmp( labelName ) == 0 ) { 478 return sprite->frameLabels[i].frameNum; 479 } 480 } 481 idLib::Warning( "Could not find frame '%s' in sprite '%s'", labelName, GetName() ); 482 return currentFrame; 483 } 484 485 /* 486 ======================== 487 idSWFSpriteInstance::FrameExists 488 ======================== 489 */ 490 bool idSWFSpriteInstance::FrameExists( const char * labelName ) const { 491 int frameNum = atoi( labelName ); 492 if ( frameNum > 0 ) { 493 return frameNum <= sprite->frameCount; 494 } 495 496 for ( int i = 0; i < sprite->frameLabels.Num(); i++ ) { 497 if ( sprite->frameLabels[i].frameLabel.Icmp( labelName ) == 0 ) { 498 return true; 499 } 500 } 501 502 return false; 503 } 504 505 /* 506 ======================== 507 idSWFSpriteInstance::IsBetweenFrames 508 Checks if the current frame is between the given inclusive range. 509 ======================== 510 */ 511 bool idSWFSpriteInstance::IsBetweenFrames( const char * frameLabel1, const char * frameLabel2 ) const { 512 return currentFrame >= FindFrame( frameLabel1 ) && currentFrame <= FindFrame( frameLabel2 ); 513 } 514 515 /* 516 ======================== 517 idSWFSpriteInstance::SetMaterial 518 ======================== 519 */ 520 void idSWFSpriteInstance::SetMaterial( const idMaterial * material, int width, int height ) { 521 materialOverride = material; 522 523 if ( materialOverride != NULL ) { 524 // Converting this to a short should be safe since we don't support images larger than 8k anyway 525 if ( materialOverride->GetStage(0) != NULL && materialOverride->GetStage(0)->texture.cinematic != NULL ) { 526 materialWidth = 256; 527 materialHeight = 256; 528 } else { 529 assert( materialOverride->GetImageWidth() > 0 && materialOverride->GetImageHeight() > 0 ); 530 assert( materialOverride->GetImageWidth() <= 8192 && materialOverride->GetImageHeight() <= 8192 ); 531 materialWidth = (uint16)materialOverride->GetImageWidth(); 532 materialHeight = (uint16)materialOverride->GetImageHeight(); 533 } 534 } else { 535 materialWidth = 0; 536 materialHeight = 0; 537 } 538 539 if ( width >= 0 ) { 540 materialWidth = (uint16)width; 541 } 542 543 if ( height >= 0 ) { 544 materialHeight = (uint16)height; 545 } 546 } 547 548 /* 549 ======================== 550 idSWFSpriteInstance::SetVisible 551 ======================== 552 */ 553 void idSWFSpriteInstance::SetVisible( bool visible ) { 554 isVisible = visible; 555 if ( isVisible ) { 556 for ( idSWFSpriteInstance * p = parent; p != NULL; p = p->parent ) { 557 p->childrenRunning = true; 558 } 559 } 560 } 561 562 /* 563 ======================== 564 idSWFSpriteInstance::PlayFrame 565 ======================== 566 */ 567 void idSWFSpriteInstance::PlayFrame( const idSWFParmList & parms ) { 568 if ( parms.Num() > 0 ) { 569 actions.Clear(); 570 RunTo( FindFrame( parms[0].ToString() ) ); 571 Play(); 572 } else { 573 idLib::Warning( "gotoAndPlay: expected 1 paramater" ); 574 } 575 } 576 577 /* 578 ======================== 579 idSWFSpriteInstance::StopFrame 580 ======================== 581 */ 582 void idSWFSpriteInstance::StopFrame( const idSWFParmList & parms ) { 583 if ( parms.Num() > 0 ) { 584 if ( parms[0].IsNumeric() && parms[0].ToInteger() < 1 ) { 585 RunTo( FindFrame( "1" ) ); 586 } else { 587 RunTo( FindFrame( parms[0].ToString() ) ); 588 } 589 Stop(); 590 } else { 591 idLib::Warning( "gotoAndStop: expected 1 paramater" ); 592 } 593 } 594 595 /* 596 ======================== 597 idSWFSpriteInstance::GetXPos 598 ======================== 599 */ 600 float idSWFSpriteInstance::GetXPos() const { 601 if ( parent == NULL ) { 602 return 0.0f; 603 } 604 605 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 606 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 607 idLib::Warning( "GetXPos: Couldn't find our display entry in our parent's display list for depth %d", depth ); 608 return 0.0f; 609 } 610 611 return thisDisplayEntry->matrix.tx; 612 } 613 614 /* 615 ======================== 616 idSWFSpriteInstance::GetYPos 617 ======================== 618 */ 619 float idSWFSpriteInstance::GetYPos( bool overallPos ) const { 620 if ( parent == NULL ) { 621 return 0.0f; 622 } 623 624 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 625 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 626 idLib::Warning( "GetYPos: Couldn't find our display entry in our parents display list for depth %d", depth ); 627 return 0.0f; 628 } 629 630 return thisDisplayEntry->matrix.ty; 631 } 632 633 /* 634 ======================== 635 idSWFSpriteInstance::SetXPos 636 ======================== 637 */ 638 void idSWFSpriteInstance::SetXPos( float xPos ) { 639 if ( parent == NULL ) { 640 return; 641 } 642 643 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 644 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 645 idLib::Warning( "_y: Couldn't find our display entry in our parents display list" ); 646 return; 647 } 648 649 thisDisplayEntry->matrix.tx = xPos; 650 } 651 652 /* 653 ======================== 654 idSWFSpriteInstance::SetYPos 655 ======================== 656 */ 657 void idSWFSpriteInstance::SetYPos( float yPos ) { 658 if ( parent == NULL ) { 659 return; 660 } 661 662 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 663 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 664 idLib::Warning( "_y: Couldn't find our display entry in our parents display list" ); 665 return; 666 } 667 668 thisDisplayEntry->matrix.ty = yPos; 669 } 670 671 /* 672 ======================== 673 idSWFSpriteInstance::SetPos 674 ======================== 675 */ 676 void idSWFSpriteInstance::SetPos( float xPos, float yPos ) { 677 if ( parent == NULL ) { 678 return; 679 } 680 681 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 682 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 683 idLib::Warning( "_y: Couldn't find our display entry in our parents display list" ); 684 return; 685 } 686 687 thisDisplayEntry->matrix.tx = xPos; 688 thisDisplayEntry->matrix.ty = yPos; 689 } 690 691 /* 692 ======================== 693 idSWFSpriteInstance::SetRotation 694 ======================== 695 */ 696 void idSWFSpriteInstance::SetRotation( float rot ) { 697 if ( parent == NULL ) { 698 return; 699 } 700 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 701 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 702 idLib::Warning( "_rotation: Couldn't find our display entry in our parents display list" ); 703 return; 704 } 705 706 swfMatrix_t & matrix = thisDisplayEntry->matrix; 707 float xscale = matrix.Scale( idVec2( 1.0f, 0.0f ) ).Length(); 708 float yscale = matrix.Scale( idVec2( 0.0f, 1.0f ) ).Length(); 709 710 float s, c; 711 idMath::SinCos( DEG2RAD( rot ), s, c ); 712 matrix.xx = c * xscale; 713 matrix.yx = s * xscale; 714 matrix.xy = -s * yscale; 715 matrix.yy = c * yscale; 716 } 717 718 /* 719 ======================== 720 idSWFSpriteInstance::SetScale 721 ======================== 722 */ 723 void idSWFSpriteInstance::SetScale( float x, float y ) { 724 if ( parent == NULL ) { 725 return; 726 } 727 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 728 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 729 idLib::Warning( "scale: Couldn't find our display entry in our parents display list" ); 730 return; 731 } 732 733 float newScale = x / 100.0f; 734 // this is done funky to maintain the current rotation 735 idVec2 currentScale = thisDisplayEntry->matrix.Scale( idVec2( 1.0f, 0.0f ) ); 736 if ( currentScale.Normalize() == 0.0f ) { 737 thisDisplayEntry->matrix.xx = newScale; 738 thisDisplayEntry->matrix.yx = 0.0f; 739 } else { 740 thisDisplayEntry->matrix.xx = currentScale.x * newScale; 741 thisDisplayEntry->matrix.yx = currentScale.y * newScale; 742 } 743 744 newScale = y / 100.0f; 745 // this is done funky to maintain the current rotation 746 currentScale = thisDisplayEntry->matrix.Scale( idVec2( 0.0f, 1.0f ) ); 747 if ( currentScale.Normalize() == 0.0f ) { 748 thisDisplayEntry->matrix.yy = newScale; 749 thisDisplayEntry->matrix.xy = 0.0f; 750 } else { 751 thisDisplayEntry->matrix.yy = currentScale.y * newScale; 752 thisDisplayEntry->matrix.xy = currentScale.x * newScale; 753 } 754 } 755 756 /* 757 ======================== 758 idSWFSpriteInstance::SetMoveToScale 759 ======================== 760 */ 761 void idSWFSpriteInstance::SetMoveToScale( float x, float y ) { 762 moveToXScale = x; 763 moveToYScale = y; 764 } 765 766 /* 767 ======================== 768 idSWFSpriteInstance::SetMoveToScale 769 ======================== 770 */ 771 bool idSWFSpriteInstance::UpdateMoveToScale( float speed ) { 772 773 if ( parent == NULL ) { 774 return false; 775 } 776 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 777 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 778 idLib::Warning( "SetMoveToScale: Couldn't find our display entry in our parents display list" ); 779 return false; 780 } 781 782 swfMatrix_t & matrix = thisDisplayEntry->matrix; 783 float xscale = matrix.Scale( idVec2( 1.0f, 0.0f ) ).Length() * 100.0f; 784 float yscale = matrix.Scale( idVec2( 0.0f, 1.0f ) ).Length() * 100.0f; 785 786 float toX = xscale; 787 if ( moveToXScale >= 0.0f ) { 788 toX = moveToXScale * 100.0f; 789 } 790 791 float toY = yscale; 792 if ( moveToYScale >= 0.0f ) { 793 toY = moveToYScale * 100.0f; 794 } 795 796 int rXTo = idMath::Ftoi( toX + 0.5f ); 797 int rYTo = idMath::Ftoi( toY + 0.5f ); 798 int rXScale = idMath::Ftoi( xscale + 0.5f ); 799 int rYScale = idMath::Ftoi( yscale + 0.5f ); 800 801 if ( rXTo == rXScale && rYTo == rYScale ) { 802 return false; 803 } 804 805 float newXScale = xscale; 806 float newYScale = yscale; 807 808 if ( rXTo != rXScale && toX >= 0.0f ) { 809 if ( toX < xscale ) { 810 newXScale -= speed; 811 newXScale = idMath::ClampFloat( toX, 100.0f, newXScale ); 812 } else if ( toX > xscale ) { 813 newXScale += speed; 814 newXScale = idMath::ClampFloat( 0.0f, toX, newXScale ); 815 } 816 } 817 818 if ( rYTo != rYScale && toY >= 0.0f ) { 819 if ( toY < yscale ) { 820 newYScale -= speed; 821 newYScale = idMath::ClampFloat( toY, 100.0f, newYScale ); 822 } else if ( toY > yscale ) { 823 newYScale += speed; 824 newYScale = idMath::ClampFloat( 0.0f, toY, newYScale ); 825 } 826 } 827 828 SetScale( newXScale, newYScale ); 829 return true; 830 } 831 832 /* 833 ======================== 834 idSWFSpriteInstance::SetAlpha 835 ======================== 836 */ 837 void idSWFSpriteInstance::SetAlpha( float val ) { 838 if ( parent == NULL ) { 839 return; 840 } 841 842 swfDisplayEntry_t * thisDisplayEntry = parent->FindDisplayEntry( depth ); 843 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != this ) { 844 idLib::Warning( "_alpha: Couldn't find our display entry in our parents display list" ); 845 return; 846 } 847 thisDisplayEntry->cxf.mul.w = val; 848 } 849 850 /* 851 ======================== 852 idSWFScriptObject_SpriteInstancePrototype 853 ======================== 854 */ 855 #define SWF_SPRITE_FUNCTION_DEFINE( x ) idSWFScriptVar idSWFScriptObject_SpriteInstancePrototype::idSWFScriptFunction_##x::Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) 856 #define SWF_SPRITE_NATIVE_VAR_DEFINE_GET( x ) idSWFScriptVar idSWFScriptObject_SpriteInstancePrototype::idSWFScriptNativeVar_##x::Get( class idSWFScriptObject * object ) 857 #define SWF_SPRITE_NATIVE_VAR_DEFINE_SET( x ) void idSWFScriptObject_SpriteInstancePrototype::idSWFScriptNativeVar_##x::Set( class idSWFScriptObject * object, const idSWFScriptVar & value ) 858 859 #define SWF_SPRITE_PTHIS_FUNC( x ) idSWFSpriteInstance * pThis = thisObject ? thisObject->GetSprite() : NULL; if ( !verify( pThis != NULL ) ) { idLib::Warning( "SWF: tried to call " x " on NULL sprite" ); return idSWFScriptVar(); } 860 #define SWF_SPRITE_PTHIS_GET( x ) idSWFSpriteInstance * pThis = object ? object->GetSprite() : NULL; if ( pThis == NULL ) { return idSWFScriptVar(); } 861 #define SWF_SPRITE_PTHIS_SET( x ) idSWFSpriteInstance * pThis = object ? object->GetSprite() : NULL; if ( pThis == NULL ) { return; } 862 863 #define SWF_SPRITE_FUNCTION_SET( x ) scriptFunction_##x.AddRef(); Set( #x, &scriptFunction_##x ); 864 #define SWF_SPRITE_NATIVE_VAR_SET( x ) SetNative( #x, &swfScriptVar_##x ); 865 866 idSWFScriptObject_SpriteInstancePrototype::idSWFScriptObject_SpriteInstancePrototype() { 867 SWF_SPRITE_FUNCTION_SET( duplicateMovieClip ); 868 SWF_SPRITE_FUNCTION_SET( gotoAndPlay ); 869 SWF_SPRITE_FUNCTION_SET( gotoAndStop ); 870 SWF_SPRITE_FUNCTION_SET( swapDepths ); 871 SWF_SPRITE_FUNCTION_SET( nextFrame ); 872 SWF_SPRITE_FUNCTION_SET( prevFrame ); 873 SWF_SPRITE_FUNCTION_SET( play ); 874 SWF_SPRITE_FUNCTION_SET( stop ); 875 876 SWF_SPRITE_NATIVE_VAR_SET( _x ); 877 SWF_SPRITE_NATIVE_VAR_SET( _y ); 878 SWF_SPRITE_NATIVE_VAR_SET( _xscale ); 879 SWF_SPRITE_NATIVE_VAR_SET( _yscale ); 880 SWF_SPRITE_NATIVE_VAR_SET( _alpha ); 881 SWF_SPRITE_NATIVE_VAR_SET( _brightness ); 882 SWF_SPRITE_NATIVE_VAR_SET( _visible ); 883 SWF_SPRITE_NATIVE_VAR_SET( _width ); 884 SWF_SPRITE_NATIVE_VAR_SET( _height ); 885 SWF_SPRITE_NATIVE_VAR_SET( _rotation ); 886 SWF_SPRITE_NATIVE_VAR_SET( _name ); 887 SWF_SPRITE_NATIVE_VAR_SET( _currentframe ); 888 SWF_SPRITE_NATIVE_VAR_SET( _totalframes ); 889 SWF_SPRITE_NATIVE_VAR_SET( _target ); 890 SWF_SPRITE_NATIVE_VAR_SET( _framesloaded ); 891 SWF_SPRITE_NATIVE_VAR_SET( _droptarget ); 892 SWF_SPRITE_NATIVE_VAR_SET( _url ); 893 SWF_SPRITE_NATIVE_VAR_SET( _highquality ); 894 SWF_SPRITE_NATIVE_VAR_SET( _focusrect ); 895 SWF_SPRITE_NATIVE_VAR_SET( _soundbuftime ); 896 SWF_SPRITE_NATIVE_VAR_SET( _quality ); 897 SWF_SPRITE_NATIVE_VAR_SET( _mousex ); 898 SWF_SPRITE_NATIVE_VAR_SET( _mousey ); 899 900 SWF_SPRITE_NATIVE_VAR_SET( _stereoDepth ); 901 SWF_SPRITE_NATIVE_VAR_SET( _itemindex ); 902 SWF_SPRITE_NATIVE_VAR_SET( material ); 903 SWF_SPRITE_NATIVE_VAR_SET( materialWidth ); 904 SWF_SPRITE_NATIVE_VAR_SET( materialHeight ); 905 SWF_SPRITE_NATIVE_VAR_SET( xOffset ); 906 907 SWF_SPRITE_NATIVE_VAR_SET( onEnterFrame ); 908 //SWF_SPRITE_NATIVE_VAR_SET( onLoad ); 909 } 910 911 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _target ) { return ""; } 912 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _droptarget ) { return ""; } 913 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _url ) { return ""; } 914 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _highquality ) { return 2; } 915 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _focusrect ) { return true; } 916 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _soundbuftime ) { return 0; } 917 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _quality ) { return "BEST"; } 918 919 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _width ) { return 0.0f; } 920 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _width ) { } 921 922 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _height ) { return 0.0f; } 923 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _height ) { } 924 925 SWF_SPRITE_FUNCTION_DEFINE( duplicateMovieClip ) { 926 SWF_SPRITE_PTHIS_FUNC( "duplicateMovieClip" ); 927 928 if ( pThis->parent == NULL ) { 929 idLib::Warning( "Tried to duplicate root movie clip" ); 930 return idSWFScriptVar(); 931 } 932 if ( parms.Num() < 2 ) { 933 idLib::Warning( "duplicateMovieClip: expected 2 parameters" ); 934 return idSWFScriptVar(); 935 } 936 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 937 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 938 idLib::Warning( "duplicateMovieClip: Couldn't find our display entry in our parents display list" ); 939 return idSWFScriptVar(); 940 } 941 942 swfMatrix_t matrix = thisDisplayEntry->matrix; 943 swfColorXform_t cxf = thisDisplayEntry->cxf; 944 945 swfDisplayEntry_t * display = pThis->parent->AddDisplayEntry( 16384 + parms[1].ToInteger(), thisDisplayEntry->characterID ); 946 if ( display == NULL ) { 947 return idSWFScriptVar(); 948 } 949 display->matrix = matrix; 950 display->cxf = cxf; 951 952 idStr name = parms[0].ToString(); 953 pThis->parent->scriptObject->Set( name, display->spriteInstance->scriptObject ); 954 display->spriteInstance->name = name; 955 display->spriteInstance->RunTo( 1 ); 956 957 return display->spriteInstance->scriptObject; 958 } 959 960 SWF_SPRITE_FUNCTION_DEFINE( gotoAndPlay ) { 961 SWF_SPRITE_PTHIS_FUNC( "gotoAndPlay" ); 962 963 if ( parms.Num() > 0 ) { 964 pThis->actions.Clear(); 965 pThis->RunTo( pThis->FindFrame( parms[0].ToString() ) ); 966 pThis->Play(); 967 } else { 968 idLib::Warning( "gotoAndPlay: expected 1 paramater" ); 969 } 970 return idSWFScriptVar(); 971 } 972 973 SWF_SPRITE_FUNCTION_DEFINE( gotoAndStop ) { 974 SWF_SPRITE_PTHIS_FUNC( "gotoAndStop" ); 975 976 if ( parms.Num() > 0 ) { 977 // Flash forces frames values less than 1 to 1. 978 if ( parms[0].IsNumeric() && parms[0].ToInteger() < 1 ) { 979 pThis->RunTo( pThis->FindFrame( "1" ) ); 980 } else { 981 pThis->RunTo( pThis->FindFrame( parms[0].ToString() ) ); 982 } 983 pThis->Stop(); 984 } else { 985 idLib::Warning( "gotoAndStop: expected 1 paramater" ); 986 } 987 return idSWFScriptVar(); 988 } 989 990 SWF_SPRITE_FUNCTION_DEFINE( swapDepths ) { 991 SWF_SPRITE_PTHIS_FUNC( "swapDepths" ); 992 993 if ( pThis->parent == NULL ) { 994 idLib::Warning( "Tried to swap depths on root movie clip" ); 995 return idSWFScriptVar(); 996 } 997 if ( parms.Num() < 1 ) { 998 idLib::Warning( "swapDepths: expected 1 parameters" ); 999 return idSWFScriptVar(); 1000 } 1001 pThis->parent->SwapDepths( pThis->depth, parms[0].ToInteger() ); 1002 return idSWFScriptVar(); 1003 } 1004 1005 SWF_SPRITE_FUNCTION_DEFINE( nextFrame ) { 1006 SWF_SPRITE_PTHIS_FUNC( "nextFrame" ); 1007 pThis->NextFrame(); 1008 return idSWFScriptVar(); 1009 } 1010 1011 SWF_SPRITE_FUNCTION_DEFINE( prevFrame ) { 1012 SWF_SPRITE_PTHIS_FUNC( "prevFrame" ); 1013 pThis->PrevFrame(); 1014 return idSWFScriptVar(); 1015 } 1016 SWF_SPRITE_FUNCTION_DEFINE( play ) { 1017 SWF_SPRITE_PTHIS_FUNC( "play" ); 1018 pThis->Play(); 1019 return idSWFScriptVar(); 1020 } 1021 SWF_SPRITE_FUNCTION_DEFINE( stop ) { 1022 SWF_SPRITE_PTHIS_FUNC( "stop" ); 1023 pThis->Stop(); 1024 return idSWFScriptVar(); 1025 } 1026 1027 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _x ) { 1028 SWF_SPRITE_PTHIS_GET( "_x" ); 1029 return pThis->GetXPos(); 1030 } 1031 1032 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _x ) { 1033 SWF_SPRITE_PTHIS_SET( "_x" ); 1034 pThis->SetXPos( value.ToFloat() ); 1035 } 1036 1037 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _y ) { 1038 SWF_SPRITE_PTHIS_GET( "_y" ); 1039 return pThis->GetYPos(); 1040 } 1041 1042 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _y ) { 1043 SWF_SPRITE_PTHIS_SET( "_y" ); 1044 pThis->SetYPos( value.ToFloat() ); 1045 } 1046 1047 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _xscale ) { 1048 SWF_SPRITE_PTHIS_GET( "_xscale" ); 1049 if ( pThis->parent == NULL ) { 1050 return 1.0f; 1051 } 1052 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1053 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1054 idLib::Warning( "_xscale: Couldn't find our display entry in our parents display list" ); 1055 return 1.0f; 1056 } 1057 return thisDisplayEntry->matrix.Scale( idVec2( 1.0f, 0.0f ) ).Length() * 100.0f; 1058 } 1059 1060 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _xscale ) { 1061 SWF_SPRITE_PTHIS_SET( "_xscale" ); 1062 if ( pThis->parent == NULL ) { 1063 return; 1064 } 1065 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1066 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1067 idLib::Warning( "_xscale: Couldn't find our display entry in our parents display list" ); 1068 return; 1069 } 1070 float newScale = value.ToFloat() / 100.0f; 1071 // this is done funky to maintain the current rotation 1072 idVec2 currentScale = thisDisplayEntry->matrix.Scale( idVec2( 1.0f, 0.0f ) ); 1073 if ( currentScale.Normalize() == 0.0f ) { 1074 thisDisplayEntry->matrix.xx = newScale; 1075 thisDisplayEntry->matrix.yx = 0.0f; 1076 } else { 1077 thisDisplayEntry->matrix.xx = currentScale.x * newScale; 1078 thisDisplayEntry->matrix.yx = currentScale.y * newScale; 1079 } 1080 } 1081 1082 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _yscale ) { 1083 SWF_SPRITE_PTHIS_GET( "_yscale" ); 1084 if ( pThis->parent == NULL ) { 1085 return 1.0f; 1086 } 1087 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1088 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1089 idLib::Warning( "_yscale: Couldn't find our display entry in our parents display list" ); 1090 return 1.0f; 1091 } 1092 return thisDisplayEntry->matrix.Scale( idVec2( 0.0f, 1.0f ) ).Length() * 100.0f; 1093 } 1094 1095 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _yscale ) { 1096 SWF_SPRITE_PTHIS_SET( "_yscale" ); 1097 if ( pThis->parent == NULL ) { 1098 return; 1099 } 1100 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1101 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1102 idLib::Warning( "_yscale: Couldn't find our display entry in our parents display list" ); 1103 return; 1104 } 1105 float newScale = value.ToFloat() / 100.0f; 1106 // this is done funky to maintain the current rotation 1107 idVec2 currentScale = thisDisplayEntry->matrix.Scale( idVec2( 0.0f, 1.0f ) ); 1108 if ( currentScale.Normalize() == 0.0f ) { 1109 thisDisplayEntry->matrix.yy = newScale; 1110 thisDisplayEntry->matrix.xy = 0.0f; 1111 } else { 1112 thisDisplayEntry->matrix.yy = currentScale.y * newScale; 1113 thisDisplayEntry->matrix.xy = currentScale.x * newScale; 1114 } 1115 } 1116 1117 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _alpha ) { 1118 SWF_SPRITE_PTHIS_GET( "_alpha" ); 1119 if ( pThis->parent == NULL ) { 1120 return 1.0f; 1121 } 1122 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1123 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1124 idLib::Warning( "_alpha: Couldn't find our display entry in our parents display list" ); 1125 return 1.0f; 1126 } 1127 return thisDisplayEntry->cxf.mul.w; 1128 } 1129 1130 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _alpha ) { 1131 SWF_SPRITE_PTHIS_SET( "_alpha" ); 1132 1133 pThis->SetAlpha( value.ToFloat() ); 1134 } 1135 1136 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _brightness ) { 1137 SWF_SPRITE_PTHIS_GET( "_brightness" ); 1138 if ( pThis->parent == NULL ) { 1139 return 1.0f; 1140 } 1141 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1142 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1143 idLib::Warning( "_brightness: Couldn't find our display entry in our parents display list" ); 1144 return 1.0f; 1145 } 1146 // This works as long as the user only used the "brightess" control in the editor 1147 // If they used anything else (tint/advanced) then this will return fairly random values 1148 const idVec4 & mul = thisDisplayEntry->cxf.mul; 1149 const idVec4 & add = thisDisplayEntry->cxf.add; 1150 float avgMul = ( mul.x + mul.y + mul.z ) / 3.0f; 1151 float avgAdd = ( add.x + add.y + add.z ) / 3.0f; 1152 if ( avgAdd > 1.0f ) { 1153 return avgAdd; 1154 } else { 1155 return avgMul - 1.0f; 1156 } 1157 } 1158 1159 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _brightness ) { 1160 SWF_SPRITE_PTHIS_SET( "_brightness" ); 1161 if ( pThis->parent == NULL ) { 1162 return; 1163 } 1164 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1165 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1166 idLib::Warning( "_brightness: Couldn't find our display entry in our parents display list" ); 1167 return; 1168 } 1169 // This emulates adjusting the "brightness" slider in the editor 1170 // Although the editor forces alpha to 100% 1171 float b = value.ToFloat(); 1172 float c = 1.0f - b; 1173 if ( b < 0.0f ) { 1174 c = 1.0f + b; 1175 b = 0.0f; 1176 } 1177 thisDisplayEntry->cxf.add.Set( b, b, b, thisDisplayEntry->cxf.add.w ); 1178 thisDisplayEntry->cxf.mul.Set( c, c, c, thisDisplayEntry->cxf.mul.w ); 1179 } 1180 1181 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _visible ) { 1182 SWF_SPRITE_PTHIS_GET( "_visible" ); 1183 return pThis->isVisible; 1184 } 1185 1186 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _visible ) { 1187 SWF_SPRITE_PTHIS_SET( "_visible" ); 1188 pThis->isVisible = value.ToBool(); 1189 if ( pThis->isVisible ) { 1190 for ( idSWFSpriteInstance * p = pThis->parent; p != NULL; p = p->parent ) { 1191 p->childrenRunning = true; 1192 } 1193 } 1194 } 1195 1196 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _rotation ) { 1197 SWF_SPRITE_PTHIS_GET( "_rotation" ); 1198 if ( pThis->parent == NULL ) { 1199 return 0.0f; 1200 } 1201 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1202 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1203 idLib::Warning( "_rotation: Couldn't find our display entry in our parents display list" ); 1204 return 0.0f; 1205 } 1206 idVec2 scale = thisDisplayEntry->matrix.Scale( idVec2( 0.0f, 1.0f ) ); 1207 scale.Normalize(); 1208 float rotation = RAD2DEG( idMath::ACos( scale.y ) ); 1209 if ( scale.x < 0.0f ) { 1210 rotation = -rotation; 1211 } 1212 return rotation; 1213 } 1214 1215 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _rotation ) { 1216 SWF_SPRITE_PTHIS_SET( "_rotation" ); 1217 if ( pThis->parent == NULL ) { 1218 return; 1219 } 1220 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1221 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1222 idLib::Warning( "_rotation: Couldn't find our display entry in our parents display list" ); 1223 return; 1224 } 1225 swfMatrix_t & matrix = thisDisplayEntry->matrix; 1226 float xscale = matrix.Scale( idVec2( 1.0f, 0.0f ) ).Length(); 1227 float yscale = matrix.Scale( idVec2( 0.0f, 1.0f ) ).Length(); 1228 1229 float s, c; 1230 idMath::SinCos( DEG2RAD( value.ToFloat() ), s, c ); 1231 matrix.xx = c * xscale; 1232 matrix.yx = s * xscale; 1233 matrix.xy = -s * yscale; 1234 matrix.yy = c * yscale; 1235 } 1236 1237 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _name ) { 1238 SWF_SPRITE_PTHIS_GET( "_name" ); 1239 return pThis->name.c_str(); 1240 } 1241 1242 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _currentframe ) { 1243 SWF_SPRITE_PTHIS_GET( "_currentframe" ); 1244 return pThis->currentFrame; 1245 } 1246 1247 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _totalframes ) { 1248 SWF_SPRITE_PTHIS_GET( "_totalframes" ); 1249 return pThis->frameCount; 1250 } 1251 1252 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _framesloaded ) { 1253 SWF_SPRITE_PTHIS_GET( "_framesloaded" ); 1254 return pThis->frameCount; 1255 } 1256 1257 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _mousex ) { 1258 SWF_SPRITE_PTHIS_GET( "_mousex" ); 1259 if ( pThis->parent == NULL ) { 1260 return pThis->sprite->GetSWF()->GetMouseX(); 1261 } 1262 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1263 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1264 idLib::Warning( "_mousex: Couldn't find our display entry in our parents display list" ); 1265 return pThis->sprite->GetSWF()->GetMouseX(); 1266 } 1267 return pThis->sprite->GetSWF()->GetMouseX() - thisDisplayEntry->matrix.ty; 1268 } 1269 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _mousey ) { 1270 SWF_SPRITE_PTHIS_GET( "_mousey" ); 1271 if ( pThis->parent == NULL ) { 1272 return pThis->sprite->GetSWF()->GetMouseY(); 1273 } 1274 swfDisplayEntry_t * thisDisplayEntry = pThis->parent->FindDisplayEntry( pThis->depth ); 1275 if ( thisDisplayEntry == NULL || thisDisplayEntry->spriteInstance != pThis ) { 1276 idLib::Warning( "_mousey: Couldn't find our display entry in our parents display list" ); 1277 return pThis->sprite->GetSWF()->GetMouseY(); 1278 } 1279 return pThis->sprite->GetSWF()->GetMouseY() - thisDisplayEntry->matrix.ty; 1280 } 1281 1282 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _itemindex ) { 1283 SWF_SPRITE_PTHIS_GET( "_itemindex" ); 1284 return pThis->itemIndex; 1285 } 1286 1287 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _itemindex ) { 1288 SWF_SPRITE_PTHIS_SET( "_itemindex" ); 1289 pThis->itemIndex = value.ToInteger(); 1290 } 1291 1292 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( _stereoDepth ) { 1293 SWF_SPRITE_PTHIS_SET( "_stereoDepth" ); 1294 pThis->stereoDepth = value.ToInteger(); 1295 } 1296 1297 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( _stereoDepth ) { 1298 SWF_SPRITE_PTHIS_GET( "_stereoDepth" ); 1299 return pThis->stereoDepth; 1300 } 1301 1302 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( material ) { 1303 SWF_SPRITE_PTHIS_GET( "material" ); 1304 if ( pThis->materialOverride == NULL ) { 1305 return idSWFScriptVar(); 1306 } else { 1307 return pThis->materialOverride->GetName(); 1308 } 1309 } 1310 1311 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( material ) { 1312 SWF_SPRITE_PTHIS_SET( "material" ); 1313 if ( !value.IsString() ) { 1314 pThis->materialOverride = NULL; 1315 } else { 1316 // God I hope this material was referenced during map load 1317 pThis->SetMaterial( declManager->FindMaterial( value.ToString(), false ) ); 1318 } 1319 } 1320 1321 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( materialWidth ) { 1322 SWF_SPRITE_PTHIS_GET( "materialWidth" ); 1323 return pThis->materialWidth; 1324 } 1325 1326 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( materialWidth ) { 1327 SWF_SPRITE_PTHIS_SET( "materialWidth" ); 1328 assert( value.ToInteger() > 0 ); 1329 assert( value.ToInteger() <= 8192 ); 1330 pThis->materialWidth = (uint16)value.ToInteger(); 1331 } 1332 1333 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( materialHeight ) { 1334 SWF_SPRITE_PTHIS_GET( "materialHeight" ); 1335 return pThis->materialHeight; 1336 } 1337 1338 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( materialHeight ) { 1339 SWF_SPRITE_PTHIS_SET( "materialHeight" ); 1340 assert( value.ToInteger() > 0 ); 1341 assert( value.ToInteger() <= 8192 ); 1342 pThis->materialHeight = (uint16)value.ToInteger(); 1343 } 1344 1345 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( xOffset ) { 1346 SWF_SPRITE_PTHIS_GET( "xOffset" ); 1347 return pThis->xOffset; 1348 } 1349 1350 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( xOffset ) { 1351 SWF_SPRITE_PTHIS_SET( "xOffset" ); 1352 pThis->xOffset = value.ToFloat(); 1353 } 1354 1355 SWF_SPRITE_NATIVE_VAR_DEFINE_GET( onEnterFrame ) { 1356 SWF_SPRITE_PTHIS_GET( "onEnterFrame" ); 1357 return pThis->onEnterFrame; 1358 } 1359 1360 SWF_SPRITE_NATIVE_VAR_DEFINE_SET( onEnterFrame ) { 1361 SWF_SPRITE_PTHIS_SET( "onEnterFrame" ); 1362 pThis->onEnterFrame = value; 1363 }