MechListBox.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. #define MECHLISTBOX_CPP
  2. /*************************************************************************************************\
  3. MechListBox.cpp : Implementation of the MechListBox component.
  4. //---------------------------------------------------------------------------//
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. //===========================================================================//
  7. \*************************************************************************************************/
  8. #include "MechListBox.h"
  9. #include "LogisticsMech.h"
  10. #include "paths.h"
  11. #include "iniFile.h"
  12. #include "err.h"
  13. #include "userInput.h"
  14. #include "MechBayScreen.h"
  15. #include "LogisticsData.h"
  16. #include "MechPurchaseScreen.h"
  17. #include "gameSound.h"
  18. MechListBoxItem* MechListBoxItem::s_templateItem = NULL;
  19. bool MechListBox::s_DrawCBills = true;
  20. bool MechListBoxItem::bAddCalledThisFrame = 0;
  21. MechListBox::MechListBox( bool bDel, bool bInclude )
  22. {
  23. bDeleteIfNoInventory = bDel;
  24. bIncludeForceGroup = bInclude;
  25. bOrange = 0;
  26. skipAmount = 5;
  27. }
  28. //-------------------------------------------------------------------------------------------------
  29. MechListBox::~MechListBox()
  30. {
  31. removeAllItems( true );
  32. delete MechListBoxItem::s_templateItem;
  33. MechListBoxItem::s_templateItem = NULL;
  34. }
  35. void MechListBox::setScrollBarOrange()
  36. {
  37. scrollBar->setOrange();
  38. }
  39. void MechListBox::setScrollBarGreen()
  40. {
  41. scrollBar->setGreen();
  42. }
  43. void MechListBox::drawCBills( bool bDraw )
  44. {
  45. s_DrawCBills = bDraw;
  46. }
  47. void MechListBox::update()
  48. {
  49. aListBox::update();
  50. MechListBoxItem::bAddCalledThisFrame = false;
  51. if ( bDeleteIfNoInventory )
  52. {
  53. for ( int i = 0; i < itemCount; i++ )
  54. {
  55. if ( ((MechListBoxItem*)items[i])->mechCount == 0 )
  56. {
  57. RemoveItem( items[i], true );
  58. i--;
  59. disableItemsThatCanNotGoInFG();
  60. // find better thing to select if necessary
  61. if ( itemSelected >= itemCount || itemSelected == -1
  62. || items[itemSelected]->getState() == aListItem::DISABLED
  63. // || !LogisticsData::instance->canAddMechToForceGroup( ((MechListBoxItem*)items[itemSelected])->getMech() )
  64. )
  65. {
  66. if ( itemCount )
  67. {
  68. for ( int j = 0; j < itemCount; j++ )
  69. if ( items[j]->getState() != aListItem::DISABLED )
  70. {
  71. SelectItem( j );
  72. break;
  73. }
  74. }
  75. else
  76. itemSelected = -1;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. LogisticsMech* MechListBox::getCurrentMech()
  83. {
  84. if ( itemSelected != -1 )
  85. {
  86. return ((MechListBoxItem*)items[itemSelected])->pMech;
  87. }
  88. return 0;
  89. }
  90. int MechListBox::init()
  91. {
  92. if ( MechListBoxItem::s_templateItem )
  93. return 0;
  94. char path[256];
  95. strcpy( path, artPath );
  96. strcat( path, "mcl_gn_availablemechentry.fit" );
  97. FitIniFile file;
  98. if ( NO_ERR != file.open( path ) )
  99. {
  100. char errorStr[256];
  101. sprintf( errorStr, "couldn't open file %s", path );
  102. Assert( 0, 0, errorStr );
  103. return -1;
  104. }
  105. MechListBoxItem::init( file );
  106. return 0;
  107. }
  108. //-------------------------------------------------------------------------------------------------
  109. bool MechListBoxItem::pointInside(long xPos, long yPos) const
  110. {
  111. int minX = location[0].x + outline.globalX();
  112. int minY = location[0].y + outline.globalY();
  113. int maxX = location[0].x + outline.globalX() + outline.width();
  114. int maxY = location[0].y + outline.globalY() + outline.height();
  115. if ( minX < xPos && xPos < maxX
  116. && minY < yPos && yPos < maxY )
  117. return true;
  118. return 0;
  119. }
  120. MechListBoxItem::MechListBoxItem( LogisticsMech* pRefMech, long count )
  121. {
  122. bIncludeForceGroup = 0;
  123. bOrange = 0;
  124. if ( s_templateItem )
  125. {
  126. *this = *s_templateItem;
  127. }
  128. animTime = 0.f;
  129. pMech = pRefMech;
  130. if ( !pMech )
  131. return;
  132. aObject::init( 0, outline.top(), outline.width(), outline.height() );
  133. setColor( 0, 0 );
  134. chassisName.setText( pMech->getChassisName() );
  135. char text[32];
  136. sprintf( text, "%ld", pMech->getCost() );
  137. costText.setText( text );
  138. mechCount = LogisticsData::instance->getVariantsInInventory( pRefMech->getVariant(), bIncludeForceGroup );
  139. sprintf( text, "%ld", mechCount );
  140. countText.setText( text );
  141. MechListBox::initIcon( pRefMech, mechIcon );
  142. variantName.setText( pMech->getName() );
  143. sprintf( text, "%.0lf", pMech->getMaxWeight() );
  144. weightText.setText( text );
  145. addChild( &weightIcon );
  146. addChild( &mechIcon );
  147. addChild( &costIcon );
  148. addChild( &chassisName );
  149. addChild( &weightText );
  150. addChild( &countText );
  151. addChild( &variantName );
  152. addChild( &costText );
  153. // addChild( &line );
  154. // addChild( &outline );
  155. bDim = 0;
  156. }
  157. MechListBoxItem::~MechListBoxItem()
  158. {
  159. removeAllChildren( false );
  160. }
  161. void MechListBoxItem::init( FitIniFile& file )
  162. {
  163. if ( !s_templateItem )
  164. {
  165. s_templateItem = new MechListBoxItem( NULL, 0 );
  166. file.seekBlock( "MainBox" );
  167. long width, height;
  168. file.readIdLong( "Width", width );
  169. file.readIdLong( "Height", height );
  170. ((aObject*)s_templateItem)->init( 0, 0, width, height );
  171. memset( s_templateItem->animationIDs, 0, sizeof(long) * 9 );
  172. // rects
  173. s_templateItem->line.init( &file, "Rect1" );
  174. s_templateItem->outline.init( &file, "Rect0" );
  175. long curAnim = 0;
  176. // statics
  177. s_templateItem->weightIcon.init( &file, "Static0" );
  178. assignAnimation( file, curAnim );
  179. s_templateItem->mechIcon.init( &file, "Static1" );
  180. assignAnimation( file, curAnim );
  181. s_templateItem->costIcon.init( &file, "Static2" );
  182. assignAnimation( file, curAnim );
  183. // texts
  184. s_templateItem->chassisName.init( &file, "Text0" );
  185. assignAnimation( file, curAnim );
  186. s_templateItem->weightText.init( &file, "Text1" );
  187. assignAnimation( file, curAnim );
  188. s_templateItem->countText.init( &file, "Text2" );
  189. assignAnimation( file, curAnim );
  190. s_templateItem->variantName.init( &file, "Text3" );
  191. assignAnimation( file, curAnim );
  192. s_templateItem->costText.init( &file, "Text4" );
  193. assignAnimation( file, curAnim );
  194. char blockName[64];
  195. for ( int i = 0; i < 4; i++ )
  196. {
  197. sprintf( blockName, "OrangeAnimation%ld", i );
  198. s_templateItem->animations[1][i].init( &file, blockName );
  199. sprintf( blockName, "Animation%ld", i );
  200. s_templateItem->animations[0][i].init( &file, blockName );
  201. }
  202. }
  203. }
  204. void MechListBoxItem::assignAnimation( FitIniFile& file, long& curAnim )
  205. {
  206. char tmpStr[64];
  207. s_templateItem->animationIDs[curAnim] = -1;
  208. if ( NO_ERR == file.readIdString( "Animation", tmpStr, 63 ) )
  209. {
  210. for ( int j = 0; j < strlen( tmpStr ); j++ )
  211. {
  212. if ( isdigit( tmpStr[j] ) )
  213. {
  214. tmpStr[j+1] = 0;
  215. s_templateItem->animationIDs[curAnim] = atoi( &tmpStr[j] );
  216. }
  217. }
  218. }
  219. curAnim++;
  220. }
  221. MechListBoxItem& MechListBoxItem::operator=( const MechListBoxItem& src )
  222. {
  223. if ( &src != this )
  224. {
  225. chassisName = src.chassisName;
  226. costIcon = src.costIcon;
  227. costText = src.costText;
  228. line = src.line;
  229. mechIcon = src.mechIcon;
  230. outline = src.outline;
  231. variantName = src.variantName;
  232. weightIcon = src.weightIcon;
  233. weightText = src.weightText;
  234. countText = src.countText;
  235. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  236. {
  237. animations[0][i] = src.animations[0][i];
  238. animations[1][i] = src.animations[1][i];
  239. }
  240. for ( i = 0; i < 9; i++ )
  241. {
  242. animationIDs[i] = src.animationIDs[i];
  243. }
  244. }
  245. return *this;
  246. }
  247. void MechListBoxItem::update()
  248. {
  249. char text[32];
  250. int oldMechCount = mechCount;
  251. if ( !pMech )
  252. {
  253. mechCount = 0;
  254. return;
  255. }
  256. mechCount = LogisticsData::instance->getVariantsInInventory( pMech->getVariant(), bIncludeForceGroup );
  257. if ( oldMechCount != mechCount )
  258. {
  259. animTime = .0001f;
  260. }
  261. sprintf( text, "%ld", mechCount );
  262. countText.setText( text );
  263. if ( animTime )
  264. {
  265. if ( animTime < .25f
  266. || ( animTime > .5f && animTime <= .75f ) )
  267. {
  268. countText.setColor( 0 );
  269. }
  270. else
  271. countText.setColor( 0xffffffff );
  272. animTime += frameLength;
  273. if ( animTime > 1.0f )
  274. animTime = 0.f;
  275. }
  276. bool isInside = pointInside( userInput->getMouseX(), userInput->getMouseY() );
  277. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  278. animations[bOrange][i].update();
  279. if ( state == aListItem::SELECTED )
  280. {
  281. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  282. animations[bOrange][i].setState( aAnimGroup::PRESSED );
  283. // if ( userInput->isLeftClick() && isInside )
  284. // setMech();
  285. if ( userInput->isLeftDrag() &&
  286. pointInside( userInput->getMouseDragX(), userInput->getMouseDragY() ) )
  287. startDrag();
  288. }
  289. else if ( state == aListItem::HIGHLITE )
  290. {
  291. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  292. animations[bOrange][i].setState( aAnimGroup::HIGHLIGHT );
  293. }
  294. else if ( state == aListItem::DISABLED && isShowing() )
  295. {
  296. if ( userInput->isLeftClick() && isInside )
  297. {
  298. soundSystem->playDigitalSample( LOG_WRONGBUTTON );
  299. setMech(); // need to call explicitly
  300. }
  301. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  302. animations[bOrange][i].setState( aAnimGroup::DISABLED );
  303. }
  304. else
  305. {
  306. for ( int i = 0; i < ANIMATION_COUNT; i++ )
  307. animations[bOrange][i].setState( aAnimGroup::NORMAL );
  308. }
  309. if ( userInput->isLeftDoubleClick() && isInside && state != aListItem::DISABLED && isShowing() )
  310. doAdd();
  311. aObject::update();
  312. }
  313. void MechListBoxItem::render()
  314. {
  315. if ( !MechListBox::s_DrawCBills )
  316. {
  317. costText.showGUIWindow( 0 );
  318. costIcon.showGUIWindow( 0 );
  319. }
  320. else
  321. {
  322. costText.showGUIWindow( 1 );
  323. costIcon.showGUIWindow( 1 );
  324. }
  325. for ( int i = 0; i < this->pNumberOfChildren; i++ )
  326. {
  327. long index = animationIDs[i];
  328. if ( index != -1 )
  329. {
  330. if ( pChildren[i]->isShowing() )
  331. {
  332. if ( !animTime || pChildren[i] != &countText )
  333. {
  334. long color = animations[bOrange][index].getCurrentColor( animations[bOrange][index].getState());
  335. pChildren[i]->setColor( color );
  336. }
  337. }
  338. }
  339. pChildren[i]->render();
  340. }
  341. if ( bDim )
  342. {
  343. mechIcon.setColor( 0xa0000000 );
  344. mechIcon.render();
  345. }
  346. outline.setColor(animations[bOrange][2].getCurrentColor(animations[bOrange][2].getState()));
  347. outline.render( location[0].x, location[0].y );
  348. line.setColor(animations[bOrange][2].getCurrentColor(animations[bOrange][2].getState()));
  349. line.render(location[0].x, location[0].y);
  350. }
  351. void MechListBoxItem::setMech()
  352. {
  353. MechBayScreen::instance()->setMech( pMech );
  354. MechPurchaseScreen::instance()->setMech( pMech, true );
  355. }
  356. void MechListBoxItem::startDrag()
  357. {
  358. if ( state != DISABLED )
  359. {
  360. MechBayScreen::instance()->beginDrag( pMech );
  361. MechPurchaseScreen::instance()->beginDrag( pMech );
  362. }
  363. }
  364. void MechListBoxItem::doAdd()
  365. {
  366. if ( !bAddCalledThisFrame ) // only select one, sometimes we auto scroll, don't want to be selecting each time
  367. {
  368. MechBayScreen::instance()->handleMessage( ID, MB_MSG_ADD );
  369. MechPurchaseScreen::instance()->handleMessage( ID, MB_MSG_ADD );
  370. bAddCalledThisFrame = true;
  371. }
  372. }
  373. void MechListBox::initIcon( LogisticsMech* pMech, aObject& mechIcon )
  374. {
  375. mechIcon = (MechListBoxItem::s_templateItem->mechIcon);
  376. long index = pMech->getIconIndex();
  377. long xIndex = index % 10;
  378. long yIndex = index / 10;
  379. float fX = xIndex;
  380. float fY = yIndex;
  381. float width = mechIcon.width();
  382. float height = mechIcon.height();
  383. float u = (fX * width);
  384. float v = (fY * height);
  385. fX += 1.f;
  386. fY += 1.f;
  387. float u2 = (fX * width);
  388. float v2 = (fY * height);
  389. mechIcon.setFileWidth(256.f);
  390. mechIcon.setUVs( u, v, u2, v2 );
  391. }
  392. long MechListBox::AddItem(aListItem* itemString)
  393. {
  394. itemString->setID( ID );
  395. MechListBoxItem* pItem = dynamic_cast<MechListBoxItem*>(itemString);
  396. EString addedName;
  397. char tmp[256];
  398. cLoadString( pItem->getMech()->getChassisName(), tmp, 255 );
  399. addedName = tmp;
  400. if ( pItem )
  401. {
  402. pItem->bOrange = bOrange;
  403. pItem->bIncludeForceGroup = bIncludeForceGroup;
  404. if ( !bDeleteIfNoInventory )
  405. {
  406. pItem->countText.setColor( 0 );
  407. pItem->countText.showGUIWindow( 0 );
  408. }
  409. EString chassisName;
  410. for ( int i = 0; i < itemCount; i++ )
  411. {
  412. long ID = ((MechListBoxItem*)items[i])->pMech->getChassisName();
  413. char tmpChassisName[256];
  414. cLoadString( ID, tmpChassisName, 255 );
  415. chassisName = tmpChassisName;
  416. if ( ((MechListBoxItem*)items[i])->pMech->getMaxWeight() < pItem->pMech->getMaxWeight() )
  417. {
  418. return InsertItem( itemString, i );
  419. break;
  420. }
  421. else if ( ((MechListBoxItem*)items[i])->pMech->getMaxWeight() == pItem->pMech->getMaxWeight()
  422. && chassisName.Compare( addedName ) > 0 )
  423. {
  424. return InsertItem( itemString, i );
  425. }
  426. else if ( ((MechListBoxItem*)items[i])->pMech->getMaxWeight() == pItem->pMech->getMaxWeight()
  427. && chassisName.Compare( addedName ) == 0
  428. && ((MechListBoxItem*)itemString)->pMech->getName().Find("Prime") != -1 )
  429. {
  430. return InsertItem( itemString, i );
  431. }
  432. else if ( ((MechListBoxItem*)items[i])->pMech->getMaxWeight() == pItem->pMech->getMaxWeight()
  433. && chassisName.Compare( addedName ) == 0
  434. && ( ((MechListBoxItem*)items[i])->pMech->getName().Find("Prime" ) == -1 )
  435. && ((MechListBoxItem*)items[i])->pMech->getName().Compare( pItem->pMech->getName() ) > 0 )
  436. {
  437. return InsertItem( itemString, i );
  438. }
  439. }
  440. }
  441. return aListBox::AddItem( itemString );
  442. }
  443. void MechListBox::dimItem( LogisticsMech* pMech, bool bDim )
  444. {
  445. for ( int i = 0; i < itemCount; i++ )
  446. {
  447. if ( ((MechListBoxItem*)items[i])->pMech == pMech )
  448. {
  449. ((MechListBoxItem*)items[i])->bDim = bDim;
  450. }
  451. }
  452. }
  453. void MechListBox::undimAll()
  454. {
  455. for ( int i = 0; i < itemCount; i++ )
  456. {
  457. ((MechListBoxItem*)items[i])->bDim = 0;
  458. }
  459. }
  460. void MechListBox::disableItemsThatCostMoreThanRP()
  461. {
  462. bool bDisabledSel = 0;
  463. for ( int i = 0; i < itemCount; i++ )
  464. {
  465. if ( ((MechListBoxItem*)items[i])->pMech->getCost() > LogisticsData::instance->getCBills() )
  466. {
  467. items[i]->setState( aListItem::DISABLED );
  468. if ( itemSelected == i )
  469. bDisabledSel = true;
  470. }
  471. else
  472. {
  473. if ( items[i]->getState() == aListItem::DISABLED )
  474. items[i]->setState( aListItem::ENABLED );
  475. }
  476. }
  477. if ( bDisabledSel )
  478. {
  479. for ( i = 0; i < itemCount; i++ )
  480. {
  481. if ( items[i]->getState() != aListItem::DISABLED )
  482. {
  483. SelectItem( i );
  484. bDisabledSel = 0;
  485. break;
  486. }
  487. }
  488. if ( bDisabledSel )
  489. SelectItem( -1 );
  490. }
  491. }
  492. void MechListBox::disableItemsThatCanNotGoInFG()
  493. {
  494. bool bDisabledSel = 0;
  495. for ( int i = 0; i < itemCount; i++ )
  496. {
  497. if ( !LogisticsData::instance->canAddMechToForceGroup( ((MechListBoxItem*)items[i])->pMech ) )
  498. {
  499. if ( itemSelected == i )
  500. bDisabledSel = true;
  501. items[i]->setState( aListItem::DISABLED );
  502. }
  503. else
  504. {
  505. if ( items[i]->getState() == aListItem::DISABLED )
  506. items[i]->setState( aListItem::ENABLED );
  507. }
  508. }
  509. if ( bDisabledSel )
  510. {
  511. for ( i = 0; i < itemCount; i++ )
  512. {
  513. if ( items[i]->getState() != aListItem::DISABLED )
  514. {
  515. SelectItem( i );
  516. bDisabledSel = 0;
  517. break;
  518. }
  519. }
  520. if ( bDisabledSel )
  521. SelectItem( -1 );
  522. }
  523. }
  524. void MechListBox::setOrange( bool bNewOrange )
  525. {
  526. bOrange = bNewOrange ? 1 : 0;
  527. for ( int i= 0; i < itemCount; i++ )
  528. {
  529. ((MechListBoxItem*)items[i])->bOrange = bOrange;
  530. }
  531. if ( bNewOrange )
  532. scrollBar->setOrange( );
  533. else
  534. scrollBar->setGreen();
  535. }
  536. //*************************************************************************************************
  537. // end of file ( MechListBox.cpp )