SWF_SpriteInstance.cpp 39 KB

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