ControlBar.cpp 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: ControlBar.cpp ///////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, March 2002
  25. // Desc: Context sensitive command interface
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #define DEFINE_GUI_COMMMAND_NAMES
  30. #define DEFINE_COMMAND_OPTION_NAMES
  31. #define DEFINE_WEAPONSLOTTYPE_NAMES
  32. #define DEFINE_RADIUSCURSOR_NAMES
  33. #include "Common/ActionManager.h"
  34. #include "Common/GameType.h"
  35. #include "Common/MultiplayerSettings.h"
  36. #include "Common/NameKeyGenerator.h"
  37. #include "Common/OVERRIDE.h"
  38. #include "Common/PlayerTemplate.h"
  39. #include "Common/Player.h"
  40. #include "Common/PlayerList.h"
  41. #include "Common/ProductionPrerequisite.h"
  42. #include "Common/SpecialPower.h"
  43. #include "Common/ThingTemplate.h"
  44. #include "Common/ThingFactory.h"
  45. #include "Common/Upgrade.h"
  46. #include "Common/Recorder.h"
  47. #include "GameLogic/GameLogic.h"
  48. #include "GameLogic/Object.h"
  49. #include "GameLogic/Module/ProductionUpdate.h"
  50. #include "GameLogic/Module/OCLUpdate.h"
  51. #include "GameLogic/Module/ContainModule.h"
  52. #include "GameLogic/Module/SpecialPowerModule.h"
  53. #include "GameLogic/Module/StealthUpdate.h"
  54. #include "GameLogic/Module/RebuildHoleBehavior.h"
  55. #include "GameLogic/ScriptEngine.h"
  56. #include "GameClient/AnimateWindowManager.h"
  57. #include "GameClient/ControlBar.h"
  58. #include "GameClient/ControlBarScheme.h"
  59. #include "GameClient/Drawable.h"
  60. #include "GameClient/Display.h"
  61. #include "GameClient/DisplayStringManager.h"
  62. #include "GameClient/GameClient.h"
  63. #include "GameClient/GameWindowManager.h"
  64. #include "GameClient/GameText.h"
  65. #include "GameClient/GadgetPushButton.h"
  66. #include "GameClient/GadgetProgressBar.h"
  67. #include "GameClient/GadgetStaticText.h"
  68. #include "GameClient/GadgetTextEntry.h"
  69. #include "GameClient/InGameUI.h"
  70. #include "GameClient/WindowVideoManager.h"
  71. #include "GameClient/ControlBarResizer.h"
  72. #include "GameClient/GadgetListBox.h"
  73. #include "GameClient/HotKey.h"
  74. #include "GameClient/GameWindowTransitions.h"
  75. #include "GameClient/GUICallbacks.h"
  76. #include "GameNetwork/GameInfo.h"
  77. #ifdef _INTERNAL
  78. // for occasional debugging...
  79. //#pragma optimize("", off)
  80. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  81. #endif
  82. // PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
  83. ControlBar *TheControlBar = NULL;
  84. const Image* ControlBar::m_rankVeteranIcon = NULL;
  85. const Image* ControlBar::m_rankEliteIcon = NULL;
  86. const Image* ControlBar::m_rankHeroicIcon = NULL;
  87. ///////////////////////////////////////////////////////////////////////////////////////////////////
  88. // CommandButton //////////////////////////////////////////////////////////////////////////////////
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////
  90. //-------------------------------------------------------------------------------------------------
  91. //-------------------------------------------------------------------------------------------------
  92. const FieldParse CommandButton::s_commandButtonFieldParseTable[] =
  93. {
  94. { "Command", CommandButton::parseCommand, NULL, offsetof( CommandButton, m_command ) },
  95. { "Options", INI::parseBitString32, TheCommandOptionNames, offsetof( CommandButton, m_options ) },
  96. { "Object", INI::parseThingTemplate, NULL, offsetof( CommandButton, m_thingTemplate ) },
  97. { "Upgrade", INI::parseUpgradeTemplate, NULL, offsetof( CommandButton, m_upgradeTemplate ) },
  98. { "WeaponSlot", INI::parseLookupList, TheWeaponSlotTypeNamesLookupList, offsetof( CommandButton, m_weaponSlot ) },
  99. { "MaxShotsToFire", INI::parseInt, NULL, offsetof( CommandButton, m_maxShotsToFire ) },
  100. { "Science", INI::parseScienceVector, NULL, offsetof( CommandButton, m_science ) },
  101. { "SpecialPower", INI::parseSpecialPowerTemplate, NULL, offsetof( CommandButton, m_specialPower ) },
  102. { "TextLabel", INI::parseAsciiString, NULL, offsetof( CommandButton, m_textLabel ) },
  103. { "DescriptLabel", INI::parseAsciiString, NULL, offsetof( CommandButton, m_descriptionLabel ) },
  104. { "PurchasedLabel", INI::parseAsciiString, NULL, offsetof( CommandButton, m_purchasedLabel ) },
  105. { "ConflictingLabel", INI::parseAsciiString, NULL, offsetof( CommandButton, m_conflictingLabel ) },
  106. { "ButtonImage", INI::parseAsciiString, NULL, offsetof( CommandButton, m_buttonImageName ) },
  107. { "CursorName", INI::parseAsciiString, NULL, offsetof( CommandButton, m_cursorName ) },
  108. { "InvalidCursorName", INI::parseAsciiString, NULL, offsetof( CommandButton, m_invalidCursorName ) },
  109. { "ButtonBorderType", INI::parseLookupList, CommandButtonMappedBorderTypeNames, offsetof( CommandButton, m_commandButtonBorder ) },
  110. { "RadiusCursorType", INI::parseIndexList, TheRadiusCursorNames, offsetof( CommandButton, m_radiusCursor ) },
  111. { "UnitSpecificSound", INI::parseAudioEventRTS, NULL, offsetof( CommandButton, m_unitSpecificSound ) },
  112. { NULL, NULL, NULL, 0 } // keep this last
  113. };
  114. static void commandButtonTooltip(GameWindow *window,
  115. WinInstanceData *instData,
  116. UnsignedInt mouse)
  117. {
  118. TheControlBar->showBuildTooltipLayout(window);
  119. }
  120. /// mark the UI as dirty so the context of everything is re-evaluated
  121. void ControlBar::markUIDirty( void )
  122. {
  123. m_UIDirty = TRUE;
  124. #if defined( _INTERNAL ) || defined( _DEBUG )
  125. UnsignedInt now = TheGameLogic->getFrame();
  126. if( now == m_lastFrameMarkedDirty )
  127. {
  128. //Do nothing.
  129. }
  130. else if( now == m_lastFrameMarkedDirty + 1 )
  131. {
  132. m_consecutiveDirtyFrames++;
  133. }
  134. else
  135. {
  136. m_consecutiveDirtyFrames = 1;
  137. }
  138. m_lastFrameMarkedDirty = now;
  139. if( m_consecutiveDirtyFrames > 20 )
  140. {
  141. DEBUG_CRASH( ("Serious flaw in interface system! Either new code or INI has caused the interface to be marked dirty every frame. This problem actually causes the interface to completely lockup not allowing you to click normal game buttons.") );
  142. }
  143. #endif
  144. }
  145. void ControlBar::populatePurchaseScience( Player* player )
  146. {
  147. // TheInGameUI->deselectAllDrawables();
  148. const CommandSet *commandSet1;
  149. const CommandSet *commandSet3;
  150. const CommandSet *commandSet8;
  151. Int i;
  152. if(TheScriptEngine->isGameEnding())
  153. return;
  154. // get command set
  155. if(!player ||!player->getPlayerTemplate() || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1().isEmpty() ||
  156. player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3().isEmpty() ||
  157. player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8().isEmpty())
  158. return;
  159. commandSet1 = TheControlBar->findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING
  160. commandSet3 = TheControlBar->findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING
  161. commandSet8 = TheControlBar->findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING
  162. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ )
  163. m_sciencePurchaseWindowsRank1[i]->winHide(TRUE);
  164. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ )
  165. m_sciencePurchaseWindowsRank3[i]->winHide(TRUE);
  166. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ )
  167. m_sciencePurchaseWindowsRank8[i]->winHide(TRUE);
  168. // if no command set match is found hide all the buttons
  169. if( commandSet1 == NULL ||
  170. commandSet3 == NULL ||
  171. commandSet8 == NULL )
  172. return;
  173. // populate the button with commands defined
  174. const CommandButton *commandButton;
  175. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ )
  176. {
  177. // get command button
  178. commandButton = commandSet1->getCommandButton(i);
  179. // if button is not present, just hide the window
  180. if( commandButton == NULL || BitTest( commandButton->getOptions(), SCRIPT_ONLY ) )
  181. {
  182. // hide window on interface
  183. m_sciencePurchaseWindowsRank1[ i ]->winHide( TRUE );
  184. } // end if
  185. else
  186. {
  187. // make sure the window is not hidden
  188. m_sciencePurchaseWindowsRank1[ i ]->winHide( FALSE );
  189. // Disable by default
  190. m_sciencePurchaseWindowsRank1[ i ]->winEnable( FALSE );
  191. // populate the visible button with data from the command button
  192. setControlCommand( m_sciencePurchaseWindowsRank1[ i ], commandButton );
  193. if (!commandButton->getScienceVec().empty())
  194. {
  195. ScienceType st = commandButton->getScienceVec()[ 0 ];
  196. if( player->isScienceDisabled( st ) )
  197. {
  198. //A script has deemed this science disabled.
  199. m_sciencePurchaseWindowsRank1[ i ]->winEnable( FALSE );
  200. }
  201. else if( player->isScienceHidden( st ) )
  202. {
  203. //A script has deemed this science unavailable, thus hidden
  204. m_sciencePurchaseWindowsRank1[ i ]->winHide( TRUE );
  205. }
  206. else
  207. {
  208. //Handle normal game logic cases!
  209. if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints())
  210. {
  211. m_sciencePurchaseWindowsRank1[ i ]->winEnable( TRUE );
  212. }
  213. if(player->hasScience(st))
  214. {
  215. m_sciencePurchaseWindowsRank1[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR);
  216. }
  217. else
  218. {
  219. m_sciencePurchaseWindowsRank1[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR);
  220. }
  221. if(!TheScienceStore->playerHasRootPrereqsForScience(player, st))
  222. m_sciencePurchaseWindowsRank1[ i ]->winHide(TRUE);
  223. }
  224. }
  225. } // end else
  226. } // end for
  227. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ )
  228. {
  229. // get command button
  230. commandButton = commandSet3->getCommandButton(i);
  231. // if button is not present, just hide the window
  232. if( commandButton == NULL || BitTest( commandButton->getOptions(), SCRIPT_ONLY ) )
  233. {
  234. // hide window on interface
  235. m_sciencePurchaseWindowsRank3[ i ]->winHide( TRUE );
  236. } // end if
  237. else
  238. {
  239. // make sure the window is not hidden
  240. m_sciencePurchaseWindowsRank3[ i ]->winHide( FALSE );
  241. // Disable by default
  242. m_sciencePurchaseWindowsRank3[ i ]->winEnable( FALSE );
  243. // populate the visible button with data from the command button
  244. setControlCommand( m_sciencePurchaseWindowsRank3[ i ], commandButton );
  245. ScienceType st = SCIENCE_INVALID;
  246. ScienceVec sv = commandButton->getScienceVec();
  247. if (! sv.empty())
  248. {
  249. st = sv[ 0 ];
  250. }
  251. if( player->isScienceDisabled( st ) )
  252. {
  253. //A script has deemed this science disabled.
  254. m_sciencePurchaseWindowsRank3[ i ]->winEnable( FALSE );
  255. }
  256. else if( player->isScienceHidden( st ) )
  257. {
  258. //A script has deemed this science unavailable, thus hidden
  259. m_sciencePurchaseWindowsRank3[ i ]->winHide( TRUE );
  260. }
  261. else
  262. {
  263. //Handle normal game logic cases!
  264. if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints())
  265. {
  266. m_sciencePurchaseWindowsRank3[ i ]->winEnable( TRUE );
  267. }
  268. if(player->hasScience(st))
  269. {
  270. m_sciencePurchaseWindowsRank3[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR);
  271. }
  272. else
  273. {
  274. m_sciencePurchaseWindowsRank3[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR);
  275. }
  276. if(!TheScienceStore->playerHasRootPrereqsForScience(player, st))
  277. m_sciencePurchaseWindowsRank3[ i ]->winHide(TRUE);
  278. }
  279. } // end else
  280. } // end for
  281. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ )
  282. {
  283. // get command button
  284. commandButton = commandSet8->getCommandButton(i);
  285. // if button is not present, just hide the window
  286. if( commandButton == NULL || BitTest( commandButton->getOptions(), SCRIPT_ONLY ) )
  287. {
  288. // hide window on interface
  289. m_sciencePurchaseWindowsRank8[ i ]->winHide( TRUE );
  290. } // end if
  291. else
  292. {
  293. // make sure the window is not hidden
  294. m_sciencePurchaseWindowsRank8[ i ]->winHide( FALSE );
  295. // Disable by default
  296. m_sciencePurchaseWindowsRank8[ i ]->winEnable( FALSE );
  297. // populate the visible button with data from the command button
  298. setControlCommand( m_sciencePurchaseWindowsRank8[ i ], commandButton );
  299. ScienceType st = SCIENCE_INVALID;
  300. st = commandButton->getScienceVec()[ 0 ];
  301. if( player->isScienceDisabled( st ) )
  302. {
  303. //A script has deemed this science disabled.
  304. m_sciencePurchaseWindowsRank8[ i ]->winEnable( FALSE );
  305. }
  306. else if( player->isScienceHidden( st ) )
  307. {
  308. //A script has deemed this science unavailable, thus hidden
  309. m_sciencePurchaseWindowsRank8[ i ]->winHide( TRUE );
  310. }
  311. else
  312. {
  313. //Handle normal game logic cases!
  314. if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints())
  315. {
  316. m_sciencePurchaseWindowsRank8[ i ]->winEnable( TRUE );
  317. }
  318. if(player->hasScience(st))
  319. {
  320. m_sciencePurchaseWindowsRank8[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR);
  321. }
  322. else
  323. {
  324. m_sciencePurchaseWindowsRank8[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR);
  325. }
  326. if(!TheScienceStore->playerHasRootPrereqsForScience(player, st))
  327. m_sciencePurchaseWindowsRank8[ i ]->winHide(TRUE);
  328. }
  329. } // end else
  330. } // end for
  331. GameWindow *win = NULL;
  332. UnicodeString tempUS;
  333. win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextRankPointsAvailable" ) );
  334. if(win)
  335. {
  336. tempUS.format(L"%d", player->getSciencePurchasePoints());
  337. GadgetStaticTextSetText(win, tempUS);
  338. }
  339. // redundant to StaticTextTitle in the Zero Hour context
  340. /*
  341. win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextLevel" ) );
  342. if(win)
  343. {
  344. tempUS.format(TheGameText->fetch("SCIENCE:Rank"), player->getRankLevel());
  345. GadgetStaticTextSetText(win, tempUS);
  346. }
  347. */
  348. win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:ProgressBarExperience" ) );
  349. if(win)
  350. {
  351. Int progress;
  352. progress = ((player->getSkillPoints() - player->getSkillPointsLevelDown()) * 100) /(player->getSkillPointsLevelUp() - player->getSkillPointsLevelDown());
  353. GadgetProgressBarSetProgress(win, progress);
  354. }
  355. win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextTitle" ) );
  356. if(win)
  357. {
  358. AsciiString tempAs;
  359. tempAs.format("SCIENCE:Rank%d", player->getRankLevel());
  360. GadgetStaticTextSetText(win, TheGameText->fetch(tempAs));
  361. }
  362. //
  363. // to avoid a one frame delay where windows may become enabled/disabled, run the update
  364. // at once to get it all in the correct state immediately
  365. //
  366. updateContextPurchaseScience();
  367. /*
  368. // get the side select buttons
  369. GameWindow* win = m_contextParent[ CP_PURCHASE_SCIENCE ];
  370. Color color = GameMakeColor(255, 255, 255, 255);
  371. /// @todo srj -- evil hack testing code. do not imitate.
  372. ScienceVec purchasable, potential;
  373. TheScienceStore->getPurchasableSciences(player, purchasable, potential);
  374. GadgetListBoxReset(win);
  375. for (ScienceVec::const_iterator it = purchasable.begin(); it != purchasable.end(); ++it)
  376. {
  377. ScienceType st = *it;
  378. UnicodeString u;
  379. u.translate(TheScienceStore->getInternalNameForScience(st));
  380. GadgetListBoxAddEntryText(win, u, color, -1, -1);
  381. }
  382. for (ScienceVec::const_iterator it2 = potential.begin(); it2 != potential.end(); ++it2)
  383. {
  384. ScienceType st = *it2;
  385. AsciiString foo = "(Not Yet)";
  386. foo.concat(TheScienceStore->getInternalNameForScience(st));
  387. UnicodeString u;
  388. u.translate(foo);
  389. GadgetListBoxAddEntryText(win, u, color, -1, -1);
  390. }
  391. GadgetListBoxAddEntryText(win, UnicodeString(L"Cancel"), color, -1, -1);*/
  392. }
  393. //-------------------------------------------------------------------------------------------------
  394. //-------------------------------------------------------------------------------------------------
  395. void ControlBar::updateContextPurchaseScience( void )
  396. {
  397. GameWindow *win =NULL;
  398. Player *player = ThePlayerList->getLocalPlayer();
  399. win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:ProgressBarExperience" ) );
  400. if(win)
  401. {
  402. Int progress;
  403. progress = ((player->getSkillPoints() - player->getSkillPointsLevelDown()) * 100) /(player->getSkillPointsLevelUp() - player->getSkillPointsLevelDown());
  404. GadgetProgressBarSetProgress(win, progress);
  405. }
  406. // win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "ControlBar.wnd:TextEntryGeneralName" ) );
  407. // if(win)
  408. // {
  409. // UnicodeString temp = GadgetTextEntryGetText(win);
  410. // if(temp.compare(player->getGeneralName()) != 0)
  411. // player->setGeneralName(temp);
  412. // }
  413. /*
  414. /// @todo srj -- evil hack testing code. do not imitate.
  415. Object *obj = m_currentSelectedDrawable->getObject();
  416. if( obj == NULL )
  417. return;
  418. // sanity
  419. if( obj->isKindOf( KINDOF_COMMANDCENTER ) == FALSE )
  420. switchToContext( CB_CONTEXT_NONE, NULL );
  421. GameWindow* win = m_contextParent[ CP_PURCHASE_SCIENCE ];
  422. Int selected;
  423. GadgetListBoxGetSelected( win, &selected );
  424. if( selected != -1 )
  425. {
  426. UnicodeString usci = GadgetListBoxGetText( win, selected, 0 );
  427. AsciiString sci;
  428. sci.translate(usci);
  429. ScienceType st = usci.getCharAt(0) == '(' ? SCIENCE_INVALID : TheScienceStore->getScienceFromInternalName(sci);
  430. if (st != SCIENCE_INVALID)
  431. {
  432. GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PURCHASE_SCIENCE );
  433. msg->appendIntegerArgument( st );
  434. }
  435. switchToContext( CB_CONTEXT_NONE, NULL );
  436. }
  437. */
  438. }
  439. //-------------------------------------------------------------------------------------------------
  440. /** parse command definition */
  441. //-------------------------------------------------------------------------------------------------
  442. void CommandButton::parseCommand( INI* ini, void *instance, void *store, const void *userData )
  443. {
  444. const char *token = ini->getNextToken();
  445. Int i;
  446. for( i = 0; TheGuiCommandNames[ i ]; i++ )
  447. {
  448. if( stricmp( TheGuiCommandNames[ i ], token ) == 0 )
  449. {
  450. GUICommandType *command = (GUICommandType *)store;
  451. *command = (GUICommandType)i;
  452. return;
  453. } // end if
  454. } // end for i
  455. // if we're here the command was not found
  456. throw INI_INVALID_DATA;
  457. } // end parseCommand
  458. //-------------------------------------------------------------------------------------------------
  459. //-------------------------------------------------------------------------------------------------
  460. CommandButton::CommandButton( void )
  461. {
  462. m_command = GUI_COMMAND_NONE;
  463. m_thingTemplate = NULL;
  464. m_upgradeTemplate = NULL;
  465. m_weaponSlot = PRIMARY_WEAPON;
  466. m_maxShotsToFire = 0x7fffffff; // huge number
  467. m_science.clear();
  468. m_specialPower = NULL;
  469. m_buttonImage = NULL;
  470. //Code renderer handles these states now.
  471. //m_disabledImage = NULL;
  472. //m_hiliteImage = NULL;
  473. //m_pushedImage = NULL;
  474. m_flashCount = 0;
  475. // Added by Sadullah Nader
  476. // The purpose is to initialize these variable to values that are zero or empty
  477. m_conflictingLabel.clear();
  478. m_cursorName.clear();
  479. m_descriptionLabel.clear();
  480. m_invalidCursorName.clear();
  481. m_name.clear();
  482. m_options = 0;
  483. m_purchasedLabel.clear();
  484. m_textLabel.clear();
  485. // End Add
  486. m_window = NULL;
  487. m_commandButtonBorder = COMMAND_BUTTON_BORDER_NONE;
  488. //m_prev = NULL;
  489. m_next = NULL;
  490. m_radiusCursor = RADIUSCURSOR_NONE;
  491. }
  492. //-------------------------------------------------------------------------------------------------
  493. //-------------------------------------------------------------------------------------------------
  494. CommandButton::~CommandButton( void )
  495. {
  496. }
  497. //-------------------------------------------------------------------------------------------------
  498. Bool CommandButton::isValidRelationshipTarget(Relationship r) const
  499. {
  500. UnsignedInt mask = 0;
  501. if (r == ENEMIES) mask |= NEED_TARGET_ENEMY_OBJECT;
  502. else if (r == ALLIES) mask |= NEED_TARGET_ALLY_OBJECT;
  503. else if (r == NEUTRAL) mask |= NEED_TARGET_NEUTRAL_OBJECT;
  504. return (m_options & mask) != 0;
  505. }
  506. //-------------------------------------------------------------------------------------------------
  507. Bool CommandButton::isValidObjectTarget(const Player* sourcePlayer, const Object* targetObj) const
  508. {
  509. if (!sourcePlayer || !targetObj)
  510. return false;
  511. Relationship r = sourcePlayer->getRelationship(targetObj->getTeam());
  512. return isValidRelationshipTarget(r);
  513. }
  514. //-------------------------------------------------------------------------------------------------
  515. Bool CommandButton::isValidObjectTarget(const Object* sourceObj, const Object* targetObj) const
  516. {
  517. if (!sourceObj || !targetObj)
  518. return false;
  519. Relationship r = sourceObj->getRelationship(targetObj);
  520. return isValidRelationshipTarget(r);
  521. }
  522. //-------------------------------------------------------------------------------------------------
  523. Bool CommandButton::isValidToUseOn(const Object *sourceObj, const Object *targetObj, const Coord3D *targetLocation, CommandSourceType commandSource) const
  524. {
  525. if (m_upgradeTemplate) {
  526. // @todo: Make a const version of pui. We're not altering the production queue, so this const-cast
  527. // is okay.
  528. ProductionUpdateInterface *pui = const_cast<Object*>(sourceObj)->getProductionUpdateInterface();
  529. if (pui) {
  530. const ProductionEntry *pe = pui->firstProduction();
  531. while (pe) {
  532. if (pe->getProductionUpgrade() != NULL)
  533. return false;
  534. pe = pui->nextProduction(pe);
  535. }
  536. return sourceObj->affectedByUpgrade(m_upgradeTemplate) && !sourceObj->hasUpgrade(m_upgradeTemplate);
  537. }
  538. // No ProductionUpdateInterface means we can't do this.
  539. return false;
  540. }
  541. if( BitTest( m_options, COMMAND_OPTION_NEED_OBJECT_TARGET ) && !targetObj )
  542. {
  543. return false;
  544. }
  545. Coord3D pos;
  546. if( targetLocation )
  547. {
  548. pos.set( targetLocation );
  549. }
  550. if( BitTest( m_options, NEED_TARGET_POS ) && !targetLocation )
  551. {
  552. if( targetObj )
  553. {
  554. pos.set( targetObj->getPosition() );
  555. }
  556. else
  557. {
  558. return false;
  559. }
  560. }
  561. if( BitTest( m_options, COMMAND_OPTION_NEED_OBJECT_TARGET ) )
  562. {
  563. return TheActionManager->canDoSpecialPowerAtObject( sourceObj, targetObj, commandSource, m_specialPower, m_options, false );
  564. }
  565. if( BitTest( m_options, NEED_TARGET_POS ) )
  566. {
  567. return TheActionManager->canDoSpecialPowerAtLocation( sourceObj, &pos, commandSource, m_specialPower, NULL, m_options, false );
  568. }
  569. return TheActionManager->canDoSpecialPower( sourceObj, m_specialPower, commandSource, m_options, false );
  570. }
  571. //-------------------------------------------------------------------------------------------------
  572. Bool CommandButton::isReady(const Object *sourceObj) const
  573. {
  574. SpecialPowerModuleInterface *mod = sourceObj->getSpecialPowerModule( m_specialPower );
  575. if( mod && mod->getPercentReady() == 1.0f )
  576. return true;
  577. if (m_upgradeTemplate && sourceObj->affectedByUpgrade(m_upgradeTemplate) && !sourceObj->hasUpgrade(m_upgradeTemplate))
  578. return true;
  579. return false;
  580. }
  581. //-------------------------------------------------------------------------------------------------
  582. Bool CommandButton::isValidObjectTarget(const Drawable* source, const Drawable* target) const
  583. {
  584. return isValidObjectTarget(source ? source->getObject() : NULL, target ? target->getObject() : NULL);
  585. }
  586. ///////////////////////////////////////////////////////////////////////////////////////////////////
  587. // CommandSet /////////////////////////////////////////////////////////////////////////////////////
  588. ///////////////////////////////////////////////////////////////////////////////////////////////////
  589. //-------------------------------------------------------------------------------------------------
  590. /** These are the fields you can define in a command set, they correspond to physical
  591. * buttons in the GUI */
  592. //-------------------------------------------------------------------------------------------------
  593. const FieldParse CommandSet::m_commandSetFieldParseTable[] =
  594. {
  595. { "1", CommandSet::parseCommandButton, (void *)0, offsetof( CommandSet, m_command ) },
  596. { "2", CommandSet::parseCommandButton, (void *)1, offsetof( CommandSet, m_command ) },
  597. { "3", CommandSet::parseCommandButton, (void *)2, offsetof( CommandSet, m_command ) },
  598. { "4", CommandSet::parseCommandButton, (void *)3, offsetof( CommandSet, m_command ) },
  599. { "5", CommandSet::parseCommandButton, (void *)4, offsetof( CommandSet, m_command ) },
  600. { "6", CommandSet::parseCommandButton, (void *)5, offsetof( CommandSet, m_command ) },
  601. { "7", CommandSet::parseCommandButton, (void *)6, offsetof( CommandSet, m_command ) },
  602. { "8", CommandSet::parseCommandButton, (void *)7, offsetof( CommandSet, m_command ) },
  603. { "9", CommandSet::parseCommandButton, (void *)8, offsetof( CommandSet, m_command ) },
  604. { "10", CommandSet::parseCommandButton, (void *)9, offsetof( CommandSet, m_command ) },
  605. { "11", CommandSet::parseCommandButton, (void *)10, offsetof( CommandSet, m_command ) },
  606. { "12", CommandSet::parseCommandButton, (void *)11, offsetof( CommandSet, m_command ) },
  607. { "13", CommandSet::parseCommandButton, (void *)12, offsetof( CommandSet, m_command ) },
  608. { "14", CommandSet::parseCommandButton, (void *)13, offsetof( CommandSet, m_command ) },
  609. { "15", CommandSet::parseCommandButton, (void *)14, offsetof( CommandSet, m_command ) },
  610. { "16", CommandSet::parseCommandButton, (void *)15, offsetof( CommandSet, m_command ) },
  611. { "17", CommandSet::parseCommandButton, (void *)16, offsetof( CommandSet, m_command ) },
  612. { "18", CommandSet::parseCommandButton, (void *)17, offsetof( CommandSet, m_command ) },
  613. { NULL, NULL, NULL, 0 } // keep this last
  614. };
  615. //-------------------------------------------------------------------------------------------------
  616. Bool CommandButton::isContextCommand() const
  617. {
  618. return BitTest( m_options, CONTEXTMODE_COMMAND );
  619. }
  620. //-------------------------------------------------------------------------------------------------
  621. // bleah. shouldn't be const, but is. sue me. (srj)
  622. void CommandButton::copyImagesFrom( const CommandButton *button, Bool markUIDirtyIfChanged ) const
  623. {
  624. if( m_buttonImage != button->getButtonImage() )
  625. {
  626. m_buttonImage = button->getButtonImage();
  627. //Code renderer handles these states now.
  628. //m_disabledImage = button->getDisabledImage();
  629. //m_hiliteImage = button->getHiliteImage();
  630. //m_pushedImage = button->getPushedImage();
  631. if( markUIDirtyIfChanged )
  632. {
  633. TheControlBar->markUIDirty();
  634. }
  635. }
  636. }
  637. //-------------------------------------------------------------------------------------------------
  638. // bleah. shouldn't be const, but is. sue me. (Kris) -snork!
  639. void CommandButton::copyButtonTextFrom( const CommandButton *button, Bool shortcutButton, Bool markUIDirtyIfChanged ) const
  640. {
  641. //This function was added to change the strings when you upgrade from a DaisyCutter to a MOAB. All other special
  642. //powers are the same.
  643. Bool change = FALSE;
  644. if( shortcutButton )
  645. {
  646. //Not the best code, but conflicting label means shortcut label (most won't have any string specified).
  647. if( button->getConflictingLabel().isNotEmpty() && m_textLabel.compare( button->getConflictingLabel() ) )
  648. {
  649. m_textLabel = button->getConflictingLabel();
  650. change = TRUE;
  651. }
  652. }
  653. else
  654. {
  655. //Copy the text from the purchase science button if it exists (most won't).
  656. if( button->getTextLabel().isNotEmpty() && m_textLabel.compare( button->getTextLabel() ) )
  657. {
  658. m_textLabel = button->getTextLabel();
  659. change = TRUE;
  660. }
  661. }
  662. if( button->getDescriptionLabel().isNotEmpty() && m_descriptionLabel.compare( button->getDescriptionLabel() ) )
  663. {
  664. m_descriptionLabel = button->getDescriptionLabel();
  665. change = TRUE;
  666. }
  667. if( markUIDirtyIfChanged && change )
  668. {
  669. TheControlBar->markUIDirty();
  670. }
  671. }
  672. //-------------------------------------------------------------------------------------------------
  673. /** Parse a single command button definition */
  674. //-------------------------------------------------------------------------------------------------
  675. void CommandSet::parseCommandButton( INI* ini, void *instance, void *store, const void *userData )
  676. {
  677. const char *token = ini->getNextToken();
  678. // get find the command button from this name
  679. const CommandButton *commandButton = TheControlBar->findCommandButton( AsciiString( token ) );
  680. if( commandButton == NULL )
  681. {
  682. DEBUG_CRASH(( "[LINE: %d - FILE: '%s'] Unknown command '%s' found in command set\n",
  683. ini->getLineNum(), ini->getFilename().str(), token ));
  684. throw INI_INVALID_DATA;
  685. } // end if
  686. // get the index to store the command at, and the command array itself
  687. const CommandButton **buttonArray = (const CommandButton **)store;
  688. Int buttonIndex = (Int)userData;
  689. // sanity
  690. DEBUG_ASSERTCRASH( buttonIndex < MAX_COMMANDS_PER_SET, ("parseCommandButton: button index '%d' out of range\n",
  691. buttonIndex) );
  692. // save it
  693. buttonArray[ buttonIndex ] = commandButton;
  694. } // end parseCommand
  695. //-------------------------------------------------------------------------------------------------
  696. //-------------------------------------------------------------------------------------------------
  697. CommandSet::CommandSet(const AsciiString& name) :
  698. m_name(name),
  699. m_next(NULL)
  700. {
  701. for( Int i = 0; i < MAX_COMMANDS_PER_SET; i++ )
  702. m_command[ i ] = NULL;
  703. }
  704. //-------------------------------------------------------------------------------------------------
  705. //-------------------------------------------------------------------------------------------------
  706. const CommandButton* CommandSet::getCommandButton(Int i) const
  707. {
  708. const CommandButton* button;
  709. // Check for TheGameLogic == null, cause it is in Worldbuilder, and wb gets command bar info. jba.
  710. if (TheGameLogic && TheGameLogic->findControlBarOverride(m_name, i, button))
  711. return button;
  712. return m_command[i];
  713. }
  714. //-------------------------------------------------------------------------------------------------
  715. //-------------------------------------------------------------------------------------------------
  716. void CommandSet::friend_addToList(CommandSet** listHead)
  717. {
  718. m_next = *listHead;
  719. *listHead = this;
  720. }
  721. //-------------------------------------------------------------------------------------------------
  722. //-------------------------------------------------------------------------------------------------
  723. CommandSet::~CommandSet( void )
  724. {
  725. } // end ~CommandSet
  726. ///////////////////////////////////////////////////////////////////////////////////////////////////
  727. // ControlBar /////////////////////////////////////////////////////////////////////////////////////
  728. ///////////////////////////////////////////////////////////////////////////////////////////////////
  729. //-------------------------------------------------------------------------------------------------
  730. //-------------------------------------------------------------------------------------------------
  731. ControlBar::ControlBar( void )
  732. {
  733. Int i;
  734. m_commandButtons = NULL;
  735. m_commandSets = NULL;
  736. m_controlBarSchemeManager = NULL;
  737. m_isObserverCommandBar = FALSE;
  738. m_observerLookAtPlayer = NULL;
  739. m_buildToolTipLayout = NULL;
  740. m_showBuildToolTipLayout = FALSE;
  741. // Added By Sadullah Nader
  742. // initializing vars to zero
  743. m_animateDownWin1Pos.x = m_animateDownWin1Pos.y = 0;
  744. m_animateDownWin1Size.x = m_animateDownWin1Size.y = 0;
  745. m_animateDownWin2Pos.x = m_animateDownWin2Pos.y = 0;
  746. m_animateDownWin2Size.x = m_animateDownWin2Size.y = 0;
  747. m_animateDownWindow = NULL;
  748. m_animTime = 0;
  749. for( i = 0; i < MAX_COMMANDS_PER_SET; i++)
  750. {
  751. m_commonCommands[i] = 0;
  752. }
  753. m_currContext = CB_CONTEXT_NONE;
  754. m_defaultControlBarPosition.x = m_defaultControlBarPosition.y = 0;
  755. m_genStarFlash = FALSE;
  756. m_genStarOff = NULL;
  757. m_genStarOn = NULL;
  758. m_UIDirty = FALSE;
  759. //
  760. // m_controlBarResizer = NULL;
  761. m_buildUpClockColor = GameMakeColor(0,0,0,100);
  762. m_commandBarBorderColor = GameMakeColor(0,0,0,100);
  763. for( i = 0; i < NUM_CONTEXT_PARENTS; i++ )
  764. m_contextParent[ i ] = NULL;
  765. for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
  766. {
  767. m_commandWindows[ i ] = NULL;
  768. // removed from multiplayer branch
  769. //m_commandMarkers[ i ] = NULL;
  770. }
  771. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ )
  772. m_sciencePurchaseWindowsRank1[i] = NULL;
  773. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ )
  774. m_sciencePurchaseWindowsRank3[i] = NULL;
  775. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ )
  776. m_sciencePurchaseWindowsRank8[i] = NULL;
  777. for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ )
  778. {
  779. m_specialPowerShortcutButtons[i] = NULL;
  780. m_specialPowerShortcutButtonParents[i] = NULL;
  781. }
  782. m_specialPowerShortcutParent = NULL;
  783. m_specialPowerLayout = NULL;
  784. m_scienceLayout = NULL;
  785. m_rightHUDWindow = NULL;
  786. m_rightHUDCameoWindow = NULL;
  787. for( i = 0; i < MAX_RIGHT_HUD_UPGRADE_CAMEOS; i++ )
  788. m_rightHUDUpgradeCameos[i];
  789. m_rightHUDUnitSelectParent = NULL;
  790. m_communicatorButton = NULL;
  791. m_currentSelectedDrawable = NULL;
  792. m_currContext = CB_CONTEXT_NONE;
  793. m_rallyPointDrawableID = INVALID_DRAWABLE_ID;
  794. m_displayedConstructPercent = -1.0f;
  795. m_displayedOCLTimerSeconds = 0;
  796. m_displayedQueueCount = 0;
  797. resetBuildQueueData();
  798. resetContainData();
  799. m_lastRecordedInventoryCount = 0;
  800. m_videoManager = NULL;
  801. m_animateWindowManager = NULL;
  802. m_generalsScreenAnimate = NULL;
  803. m_animateWindowManagerForGenShortcuts = NULL;
  804. m_flash = FALSE;
  805. m_toggleButtonUpIn = NULL;
  806. m_toggleButtonUpOn = NULL;
  807. m_toggleButtonUpPushed = NULL;
  808. m_toggleButtonDownIn = NULL;
  809. m_toggleButtonDownOn = NULL;
  810. m_toggleButtonDownPushed = NULL;
  811. m_generalButtonEnable = NULL;
  812. m_generalButtonHighlight = NULL;
  813. m_genArrow = NULL;
  814. m_sideSelectAnimateDown = FALSE;
  815. updateCommanBarBorderColors(GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED);
  816. m_radarAttackGlowOn = FALSE;
  817. m_remainingRadarAttackGlowFrames = 0;
  818. m_radarAttackGlowWindow = NULL;
  819. #if defined( _INTERNAL ) || defined( _DEBUG )
  820. m_lastFrameMarkedDirty = 0;
  821. m_consecutiveDirtyFrames = 0;
  822. #endif
  823. } // end ControlBar
  824. //-------------------------------------------------------------------------------------------------
  825. //-------------------------------------------------------------------------------------------------
  826. ControlBar::~ControlBar( void )
  827. {
  828. if(m_scienceLayout)
  829. {
  830. m_scienceLayout->destroyWindows();
  831. m_scienceLayout->deleteInstance();
  832. }
  833. m_scienceLayout = NULL;
  834. m_genArrow = NULL;
  835. if(m_videoManager)
  836. delete m_videoManager;
  837. m_videoManager = NULL;
  838. if(m_animateWindowManagerForGenShortcuts)
  839. delete m_animateWindowManagerForGenShortcuts;
  840. m_animateWindowManagerForGenShortcuts = NULL;
  841. if(m_animateWindowManager)
  842. delete m_animateWindowManager;
  843. m_animateWindowManager = NULL;
  844. if(m_generalsScreenAnimate)
  845. delete m_generalsScreenAnimate;
  846. m_generalsScreenAnimate = NULL;
  847. if( m_controlBarSchemeManager )
  848. delete m_controlBarSchemeManager;
  849. m_controlBarSchemeManager = NULL;
  850. // if(m_controlBarResizer)
  851. // delete m_controlBarResizer;
  852. // m_controlBarResizer = NULL;
  853. // destroy all the command set definitions
  854. CommandSet *set;
  855. while( m_commandSets )
  856. {
  857. set = m_commandSets->friend_getNext();
  858. m_commandSets->deleteInstance();
  859. m_commandSets = set;
  860. } // end while
  861. // destroy all our command button definitions
  862. CommandButton *button;
  863. while( m_commandButtons )
  864. {
  865. button = m_commandButtons->friend_getNext();
  866. m_commandButtons->deleteInstance();
  867. m_commandButtons = button;
  868. } // end while
  869. if(m_buildToolTipLayout)
  870. {
  871. m_buildToolTipLayout->destroyWindows();
  872. m_buildToolTipLayout->deleteInstance();
  873. m_buildToolTipLayout = NULL;
  874. }
  875. if(m_specialPowerLayout)
  876. {
  877. m_specialPowerLayout->destroyWindows();
  878. m_specialPowerLayout->deleteInstance();
  879. m_specialPowerLayout = NULL;
  880. }
  881. m_radarAttackGlowWindow = NULL;
  882. if (m_rightHUDCameoWindow && m_rightHUDCameoWindow->winGetUserData())
  883. delete m_rightHUDCameoWindow->winGetUserData();
  884. } // end ~ControlBar
  885. void ControlBarPopupDescriptionUpdateFunc( WindowLayout *layout, void *param );
  886. //-------------------------------------------------------------------------------------------------
  887. /** Initialzie the control bar, this is our interface to the context sinsitive GUI */
  888. //-------------------------------------------------------------------------------------------------
  889. void ControlBar::init( void )
  890. {
  891. INI ini;
  892. m_sideSelectAnimateDown = FALSE;
  893. // load the command buttons
  894. ini.load( AsciiString( "Data\\INI\\Default\\CommandButton.ini" ), INI_LOAD_OVERWRITE, NULL );
  895. ini.load( AsciiString( "Data\\INI\\CommandButton.ini" ), INI_LOAD_OVERWRITE, NULL );
  896. // load the command sets
  897. ini.load( AsciiString( "Data\\INI\\CommandSet.ini" ), INI_LOAD_OVERWRITE, NULL );
  898. // post process step after loading the command buttons and command sets
  899. postProcessCommands();
  900. // Init the scheme manager, this will call it's won INI init funciton.
  901. m_controlBarSchemeManager = NEW ControlBarSchemeManager;
  902. m_controlBarSchemeManager->init();
  903. //Added this check because the builder uses the ControlBar, but doesn't care about
  904. //the GUI.
  905. if( TheWindowManager )
  906. {
  907. //
  908. // the control bar has several windows that make up our context sensitive interface, we
  909. // want those parent windows so that we can easily hide and show them to make the
  910. // interface context sensitive
  911. //
  912. NameKeyType id;
  913. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ControlBarParent" );
  914. m_contextParent[ CP_MASTER ] = TheWindowManager->winGetWindowFromId( NULL, id );
  915. m_contextParent[ CP_MASTER ]->winGetPosition(&m_defaultControlBarPosition.x, &m_defaultControlBarPosition.y);
  916. m_scienceLayout = TheWindowManager->winCreateLayout("GeneralsExpPoints.wnd");
  917. m_scienceLayout->hide(TRUE);
  918. id = TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:GenExpParent" );
  919. m_contextParent[ CP_PURCHASE_SCIENCE ] = TheWindowManager->winGetWindowFromId( NULL, id );//m_scienceLayout->getFirstWindow();
  920. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:UnderConstructionWindow" );
  921. m_contextParent[ CP_UNDER_CONSTRUCTION ] = TheWindowManager->winGetWindowFromId( NULL, id );
  922. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerWindow" );
  923. m_contextParent[ CP_OCL_TIMER ] = TheWindowManager->winGetWindowFromId( NULL, id );
  924. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BeaconWindow" );
  925. m_contextParent[ CP_BEACON ] = TheWindowManager->winGetWindowFromId( NULL, id );
  926. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:CommandWindow" );
  927. m_contextParent[ CP_COMMAND ] = TheWindowManager->winGetWindowFromId( NULL, id );
  928. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ProductionQueueWindow" );
  929. m_contextParent[ CP_BUILD_QUEUE ] = TheWindowManager->winGetWindowFromId( NULL, id );
  930. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ObserverPlayerListWindow" );
  931. m_contextParent[ CP_OBSERVER_LIST ] = TheWindowManager->winGetWindowFromId( NULL, id );
  932. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ObserverPlayerInfoWindow" );
  933. m_contextParent[ CP_OBSERVER_INFO ] = TheWindowManager->winGetWindowFromId( NULL, id );
  934. // get the command windows and save for easy access later
  935. Int i;
  936. ICoord2D commandSize, commandPos;
  937. AsciiString windowName;
  938. for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
  939. {
  940. windowName.format( "ControlBar.wnd:ButtonCommand%02d", i + 1 );
  941. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  942. m_commandWindows[ i ] =
  943. TheWindowManager->winGetWindowFromId( m_contextParent[ CP_COMMAND ], id );
  944. if (m_commandWindows[ i ])
  945. {
  946. m_commandWindows[ i ]->winGetPosition(&commandPos.x, &commandPos.y);
  947. m_commandWindows[ i ]->winGetSize(&commandSize.x, &commandSize.y);
  948. m_commandWindows[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  949. }
  950. // removed from multiplayer branch
  951. // windowName.format( "ControlBar.wnd:CommandMarker%02d", i + 1 );
  952. // id = TheNameKeyGenerator->nameToKey( windowName.str() );
  953. // m_commandMarkers[ i ] =
  954. // TheWindowManager->winGetWindowFromId( m_contextParent[ CP_COMMAND ], id );
  955. // // set the size and position to make sure their in the same place as the buttons.
  956. // m_commandMarkers[i]->winSetPosition(commandPos.x -2, commandPos.y - 2);
  957. // m_commandMarkers[i]->winSetSize(commandSize.x + 2, commandSize.y + 2);
  958. } // end for i
  959. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ )
  960. {
  961. windowName.format( "GeneralsExpPoints.wnd:ButtonRank1Number%d", i );
  962. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  963. m_sciencePurchaseWindowsRank1[ i ] =
  964. TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id );
  965. m_sciencePurchaseWindowsRank1[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  966. } // end for i
  967. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ )
  968. {
  969. windowName.format( "GeneralsExpPoints.wnd:ButtonRank3Number%d", i );
  970. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  971. m_sciencePurchaseWindowsRank3[ i ] =
  972. TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id );
  973. m_sciencePurchaseWindowsRank3[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  974. } // end for i
  975. for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ )
  976. {
  977. windowName.format( "GeneralsExpPoints.wnd:ButtonRank8Number%d", i );
  978. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  979. m_sciencePurchaseWindowsRank8[ i ] =
  980. TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id );
  981. m_sciencePurchaseWindowsRank8[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  982. } // end for i
  983. // keep a pointer to the window making up the right HUD display
  984. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:RightHUD" );
  985. m_rightHUDWindow = TheWindowManager->winGetWindowFromId( NULL, id );
  986. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:WinUnitSelected" );
  987. m_rightHUDUnitSelectParent = TheWindowManager->winGetWindowFromId( NULL, id );
  988. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:CameoWindow" );
  989. m_rightHUDCameoWindow = TheWindowManager->winGetWindowFromId( NULL, id );
  990. for( i = 0; i < MAX_RIGHT_HUD_UPGRADE_CAMEOS; i++ )
  991. {
  992. windowName.format( "ControlBar.wnd:UnitUpgrade%d", i+1 );
  993. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  994. m_rightHUDUpgradeCameos[ i ] =
  995. TheWindowManager->winGetWindowFromId( m_rightHUDWindow, id );
  996. m_rightHUDUpgradeCameos[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  997. }
  998. // m_transitionHandler = NEW GameWindowTransitionsHandler;
  999. // m_transitionHandler->load();
  1000. // m_transitionHandler->init();
  1001. // don't forget about the communicator button CCB
  1002. id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PopupCommunicator" );
  1003. m_communicatorButton = TheWindowManager->winGetWindowFromId( NULL, id );
  1004. setControlCommand(m_communicatorButton, findCommandButton("NonCommand_Communicator") );
  1005. m_communicatorButton->winSetTooltipFunc(commandButtonTooltip);
  1006. GameWindow *win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonOptions"));
  1007. if(win)
  1008. {
  1009. setControlCommand(win, findCommandButton("NonCommand_Options") );
  1010. win->winSetTooltipFunc(commandButtonTooltip);
  1011. }
  1012. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonIdleWorker"));
  1013. if(win)
  1014. {
  1015. setControlCommand(win, findCommandButton("NonCommand_IdleWorker") );
  1016. win->winSetTooltipFunc(commandButtonTooltip);
  1017. }
  1018. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonPlaceBeacon"));
  1019. if(win)
  1020. {
  1021. setControlCommand(win, findCommandButton("NonCommand_Beacon") );
  1022. win->winSetTooltipFunc(commandButtonTooltip);
  1023. }
  1024. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonGeneral"));
  1025. if(win)
  1026. {
  1027. setControlCommand(win, findCommandButton("NonCommand_GeneralsExperience") );
  1028. win->winSetTooltipFunc(commandButtonTooltip);
  1029. }
  1030. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonLarge"));
  1031. if(win)
  1032. {
  1033. setControlCommand(win, findCommandButton("NonCommand_UpDown") );
  1034. win->winSetTooltipFunc(commandButtonTooltip);
  1035. }
  1036. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:PowerWindow"));
  1037. if(win)
  1038. {
  1039. win->winSetTooltipFunc(commandButtonTooltip);
  1040. }
  1041. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey("ControlBar.wnd:MoneyDisplay"));
  1042. if(win)
  1043. {
  1044. win->winSetTooltipFunc(commandButtonTooltip);
  1045. }
  1046. win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:GeneralsExp"));
  1047. if(win)
  1048. {
  1049. win->winSetTooltipFunc(commandButtonTooltip);
  1050. }
  1051. m_radarAttackGlowWindow = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinUAttack"));
  1052. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey( AsciiString( "ControlBar.wnd:BackgroundMarker" ) ));
  1053. win->winGetScreenPosition(&m_controlBarForegroundMarkerPos.x, &m_controlBarForegroundMarkerPos.y);
  1054. win = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey( AsciiString( "ControlBar.wnd:BackgroundMarker" ) ));
  1055. win->winGetScreenPosition(&m_controlBarBackgroundMarkerPos.x,&m_controlBarBackgroundMarkerPos.y);
  1056. if(!m_videoManager)
  1057. m_videoManager = NEW WindowVideoManager;
  1058. if(!m_animateWindowManager)
  1059. m_animateWindowManager = NEW AnimateWindowManager;
  1060. if(!m_generalsScreenAnimate)
  1061. m_generalsScreenAnimate = NEW AnimateWindowManager;
  1062. if(!m_animateWindowManagerForGenShortcuts)
  1063. m_animateWindowManagerForGenShortcuts = NEW AnimateWindowManager;
  1064. m_buildToolTipLayout = TheWindowManager->winCreateLayout( "ControlBarPopupDescription.wnd" );
  1065. if(m_buildToolTipLayout)
  1066. {
  1067. m_buildToolTipLayout->hide(TRUE);
  1068. m_buildToolTipLayout->setUpdate(ControlBarPopupDescriptionUpdateFunc);
  1069. }
  1070. m_genStarOn = TheMappedImageCollection ? (Image *)TheMappedImageCollection->findImageByName("BarButtonGenStarON") : NULL;
  1071. m_genStarOff = TheMappedImageCollection ? (Image *)TheMappedImageCollection->findImageByName("BarButtonGenStarOFF") : NULL;
  1072. m_genStarFlash = TRUE;
  1073. m_lastFlashedAtPointValue = -1;
  1074. m_rankVeteranIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron1L" ) : NULL;
  1075. m_rankEliteIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron2L" ) : NULL;
  1076. m_rankHeroicIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron3L" ) : NULL;
  1077. // if(!m_controlBarResizer)
  1078. // m_controlBarResizer = NEW ControlBarResizer;
  1079. // m_controlBarResizer->init();
  1080. // Initialize the Observer controls
  1081. initObserverControls();
  1082. // by default switch to the none context
  1083. switchToContext( CB_CONTEXT_NONE, NULL );
  1084. }
  1085. } // end init
  1086. //-------------------------------------------------------------------------------------------------
  1087. /** Reset the context sensitive control bar GUI */
  1088. //-------------------------------------------------------------------------------------------------
  1089. void ControlBar::reset( void )
  1090. {
  1091. hideSpecialPowerShortcut();
  1092. // do not destroy the rally drawable, it will get destroyed with everythign else during a reset
  1093. m_rallyPointDrawableID = INVALID_DRAWABLE_ID;
  1094. if(m_radarAttackGlowWindow)
  1095. m_radarAttackGlowWindow->winEnable(TRUE);
  1096. m_radarAttackGlowOn = FALSE;
  1097. m_remainingRadarAttackGlowFrames = 0;
  1098. m_displayedConstructPercent = -1.0f;
  1099. m_displayedOCLTimerSeconds = 0;
  1100. m_isObserverCommandBar = FALSE; // reset us to use a normal command bar
  1101. m_observerLookAtPlayer = NULL;
  1102. if(m_buildToolTipLayout)
  1103. m_buildToolTipLayout->hide(TRUE);
  1104. m_showBuildToolTipLayout = FALSE;
  1105. if(m_animateWindowManager)
  1106. m_animateWindowManager->reset();
  1107. if(m_animateWindowManagerForGenShortcuts)
  1108. m_animateWindowManagerForGenShortcuts->reset();
  1109. if(m_generalsScreenAnimate)
  1110. m_generalsScreenAnimate->reset();
  1111. if(m_videoManager)
  1112. m_videoManager->reset();
  1113. // go back to default context
  1114. switchToContext( CB_CONTEXT_NONE, NULL );
  1115. m_sideSelectAnimateDown = FALSE;
  1116. if(m_animateDownWindow)
  1117. {
  1118. TheWindowManager->winDestroy( m_animateDownWindow );
  1119. m_animateDownWindow = NULL;
  1120. }
  1121. // Remove any overridden sets.
  1122. CommandSet *set, *nextSet;
  1123. set = m_commandSets;
  1124. while (set) {
  1125. Bool possibleAdjustment = FALSE;
  1126. nextSet = set->friend_getNext();
  1127. if (set == m_commandSets) {
  1128. possibleAdjustment = TRUE;
  1129. }
  1130. Overridable *stillValid = set->deleteOverrides();
  1131. if (stillValid == NULL && possibleAdjustment) {
  1132. m_commandSets = nextSet;
  1133. }
  1134. set = nextSet;
  1135. }
  1136. // Remove any overridden command buttons.
  1137. CommandButton *button, *nextButton;
  1138. button = m_commandButtons;
  1139. while (button) {
  1140. Bool possibleAdjustment = FALSE;
  1141. nextButton = button->friend_getNext();
  1142. if (button == m_commandButtons) {
  1143. possibleAdjustment = TRUE;
  1144. }
  1145. Overridable *stillValid = button->deleteOverrides();
  1146. if (stillValid == NULL && possibleAdjustment) {
  1147. m_commandButtons = nextButton;
  1148. }
  1149. button = nextButton;
  1150. }
  1151. if(TheTransitionHandler)
  1152. TheTransitionHandler->remove("ControlBarArrow");
  1153. m_genArrow = NULL;
  1154. m_lastFlashedAtPointValue = -1;
  1155. m_genStarFlash = TRUE;
  1156. } // end reset
  1157. //-------------------------------------------------------------------------------------------------
  1158. /** Update phase, we can track if our selected object is destroyed, update button
  1159. * percentages, status, enabled status etc */
  1160. //-------------------------------------------------------------------------------------------------
  1161. void ControlBar::update( void )
  1162. {
  1163. getStarImage();
  1164. updateRadarAttackGlow();
  1165. if(m_controlBarSchemeManager)
  1166. m_controlBarSchemeManager->update();
  1167. // Update our video manager
  1168. if( m_videoManager )
  1169. m_videoManager->update();
  1170. if (m_animateWindowManager)
  1171. m_animateWindowManager->update();
  1172. if (m_animateWindowManager)
  1173. {
  1174. if (m_animateWindowManager->isFinished() && m_animateWindowManager->isReversed())
  1175. {
  1176. Int id = (Int)TheNameKeyGenerator->nameToKey(AsciiString("ControlBar.wnd:ControlBarParent"));
  1177. GameWindow *window = TheWindowManager->winGetWindowFromId(NULL, id);
  1178. if (window && !window->winIsHidden())
  1179. window->winHide(TRUE);
  1180. }
  1181. }
  1182. if(m_animateWindowManagerForGenShortcuts)
  1183. m_animateWindowManagerForGenShortcuts->update();
  1184. if (m_animateWindowManagerForGenShortcuts && m_specialPowerShortcutParent)
  1185. {
  1186. if (m_animateWindowManagerForGenShortcuts->isFinished() && m_animateWindowManagerForGenShortcuts->isReversed())
  1187. {
  1188. if (m_specialPowerShortcutParent && !m_specialPowerShortcutParent->winIsHidden())
  1189. m_specialPowerShortcutParent->winHide(TRUE);
  1190. }
  1191. }
  1192. if( !m_buildToolTipLayout->isHidden())
  1193. {
  1194. m_buildToolTipLayout->runUpdate();
  1195. m_showBuildToolTipLayout = FALSE;
  1196. }
  1197. /*
  1198. else if( m_buildToolTipLayout )
  1199. {
  1200. hideBuildTooltipLayout();
  1201. }*/
  1202. updateSpecialPowerShortcut();
  1203. // if we're an observer, don't do the complete update
  1204. if( m_isObserverCommandBar)
  1205. {
  1206. if((TheGameLogic->getFrame() % (LOGICFRAMES_PER_SECOND/2)) == 0)
  1207. populateObserverInfoWindow();
  1208. Drawable *drawToEvaluateFor = NULL;
  1209. Bool multiSelect = FALSE;
  1210. if( TheInGameUI->getSelectCount() > 1 )
  1211. {
  1212. // Attempt to isolate a Drawable here to evaluate
  1213. // The need arises when selected is an AngryMob,
  1214. // whose selection actually consists of varied units
  1215. // but is represented in the UI as a single unit,
  1216. // so we must isolate and evaluate only the Nexus
  1217. drawToEvaluateFor = TheGameClient->findDrawableByID( TheInGameUI->getSoloNexusSelectedDrawableID() ) ;
  1218. multiSelect = ( drawToEvaluateFor == NULL );
  1219. }
  1220. else // get the first and only drawble in the selection list
  1221. drawToEvaluateFor = TheInGameUI->getAllSelectedDrawables()->front();
  1222. Object *obj = drawToEvaluateFor ? drawToEvaluateFor->getObject() : NULL;
  1223. setPortraitByObject( obj );
  1224. return;
  1225. }
  1226. // check flashing
  1227. if( m_flash )
  1228. {
  1229. // go through all the command buttons to see which one needs to flash
  1230. for( Int i = 0; i < MAX_COMMANDS_PER_SET; ++i )
  1231. {
  1232. GameWindow *button = m_commandWindows[ i ];
  1233. if( button != NULL)
  1234. {
  1235. const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(button);
  1236. if( commandButton != NULL )
  1237. {
  1238. if( commandButton->getFlashCount() > 0 && TheGameClient->getFrame() % 10 == 0 )
  1239. {
  1240. if( commandButton->getFlashCount() % 2 == 0 )
  1241. {
  1242. commandButton->setFlashCount(commandButton->getFlashCount() - 1);
  1243. button->winSetStatus( WIN_STATUS_FLASHING );
  1244. }
  1245. else
  1246. {
  1247. commandButton->setFlashCount(commandButton->getFlashCount() - 1);
  1248. button->winClearStatus( WIN_STATUS_FLASHING );
  1249. if( commandButton->getFlashCount() == 0 )
  1250. {
  1251. setFlash( FALSE );
  1252. }
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. }
  1259. if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden())
  1260. updateContextPurchaseScience();
  1261. //
  1262. // first, if the UI is dirty repopulate the UI with what the user should see for all the
  1263. // selected drawables
  1264. //
  1265. if( m_UIDirty )
  1266. {
  1267. evaluateContextUI();
  1268. populateSpecialPowerShortcut(ThePlayerList->getLocalPlayer());
  1269. // if we have a build tooltip layout, update it with the new data.
  1270. repopulateBuildTooltipLayout();
  1271. }
  1272. // enable/disable the beacon button depending on if the max has been reached
  1273. if (ThePlayerList && ThePlayerList->getLocalPlayer() && ThePlayerList->getLocalPlayer()->getPlayerTemplate())
  1274. {
  1275. Int count;
  1276. const ThingTemplate *thing = TheThingFactory->findTemplate( ThePlayerList->getLocalPlayer()->getPlayerTemplate()->getBeaconTemplate() );
  1277. ThePlayerList->getLocalPlayer()->countObjectsByThingTemplate( 1, &thing, false, &count );
  1278. static NameKeyType beaconPlacementButtonID = NAMEKEY("ControlBar.wnd:ButtonPlaceBeacon");
  1279. GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, beaconPlacementButtonID);
  1280. if (win)
  1281. {
  1282. if (count < TheMultiplayerSettings->getMaxBeaconsPerPlayer())
  1283. {
  1284. win->winEnable(TRUE);
  1285. }
  1286. else
  1287. {
  1288. win->winEnable(FALSE);
  1289. }
  1290. }
  1291. }
  1292. //
  1293. // most control bar contexts have one selected thing that we switch on and update
  1294. // based on if that thing changed in some way ... the exception is when multi selected
  1295. //
  1296. if( m_currContext == CB_CONTEXT_MULTI_SELECT )
  1297. {
  1298. updateContextMultiSelect();
  1299. return;
  1300. } // end if
  1301. // if nothing is selected get out of here except if we're in the Purchase science context... that requires
  1302. // us to not have anything selected
  1303. if( m_currentSelectedDrawable == NULL )
  1304. {
  1305. // we better be in the default none context
  1306. DEBUG_ASSERTCRASH( m_currContext == CB_CONTEXT_NONE, ("ControlBar::update no selection, but not we're not showing the default NONE context\n") );
  1307. return;
  1308. } // end if
  1309. // if our selected drawable has no object get out of here
  1310. Object *obj = NULL;
  1311. if(m_currentSelectedDrawable)
  1312. obj = m_currentSelectedDrawable->getObject();
  1313. if( obj == NULL )
  1314. {
  1315. switchToContext( CB_CONTEXT_NONE, NULL );
  1316. return;
  1317. } // end if
  1318. switch( m_currContext )
  1319. {
  1320. //---------------------------------------------------------------------------------------------
  1321. case CB_CONTEXT_NONE:
  1322. break;
  1323. //---------------------------------------------------------------------------------------------
  1324. case CB_CONTEXT_COMMAND:
  1325. updateContextCommand();
  1326. break;
  1327. //---------------------------------------------------------------------------------------------
  1328. case CB_CONTEXT_STRUCTURE_INVENTORY:
  1329. updateContextStructureInventory();
  1330. break;
  1331. //---------------------------------------------------------------------------------------------
  1332. case CB_CONTEXT_BEACON:
  1333. updateContextBeacon();
  1334. break;
  1335. //---------------------------------------------------------------------------------------------
  1336. case CB_CONTEXT_UNDER_CONSTRUCTION:
  1337. updateContextUnderConstruction();
  1338. break;
  1339. //---------------------------------------------------------------------------------------------
  1340. case CB_CONTEXT_OCL_TIMER:
  1341. updateContextOCLTimer();
  1342. break;
  1343. } // end switch
  1344. } // end update
  1345. //-------------------------------------------------------------------------------------------------
  1346. //-------------------------------------------------------------------------------------------------
  1347. void ControlBar::onDrawableSelected( Drawable *draw )
  1348. {
  1349. // set a dirty flag so next time we update we can reconstruct the UI
  1350. markUIDirty();
  1351. // cancel any pending GUI commands
  1352. TheInGameUI->setGUICommand( NULL );
  1353. } // end onDrawableSelected
  1354. //-------------------------------------------------------------------------------------------------
  1355. //-------------------------------------------------------------------------------------------------
  1356. void ControlBar::onDrawableDeselected( Drawable *draw )
  1357. {
  1358. // set a dirty flag so next time we update we can reconstruct the UI
  1359. markUIDirty();
  1360. if (TheInGameUI->getSelectCount() == 0)
  1361. {
  1362. // we just deselected everything - cancel any pending GUI commands
  1363. TheInGameUI->setGUICommand( NULL );
  1364. }
  1365. //
  1366. // always when becoming unselected should we remove any build placement icons because if
  1367. // we have some and are in the middle of a build process, it must obiously be over now
  1368. // because we are no longer selecting the dozer or worker
  1369. //
  1370. TheInGameUI->placeBuildAvailable( NULL, NULL );
  1371. } // end onDrawableDeselected
  1372. //-------------------------------------------------------------------------------------------------
  1373. const Image *ControlBar::getStarImage(void )
  1374. {
  1375. if(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints() || ThePlayerList->getLocalPlayer()->getSciencePurchasePoints() <= 0)
  1376. m_genStarFlash = FALSE;
  1377. else
  1378. m_lastFlashedAtPointValue = ThePlayerList->getLocalPlayer()->getSciencePurchasePoints();
  1379. GameWindow *win= TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonGeneral" ) );
  1380. if(!win)
  1381. return NULL;
  1382. if(!m_genStarFlash)
  1383. {
  1384. GadgetButtonSetEnabledImage(win, m_generalButtonEnable);
  1385. return NULL;
  1386. }
  1387. if(TheGameLogic->getFrame()% LOGICFRAMES_PER_SECOND > LOGICFRAMES_PER_SECOND/2)
  1388. {
  1389. GadgetButtonSetEnabledImage(win, m_generalButtonHighlight);
  1390. return NULL;
  1391. }
  1392. GadgetButtonSetEnabledImage(win, m_generalButtonEnable);
  1393. return NULL;
  1394. }
  1395. //-------------------------------------------------------------------------------------------------
  1396. void ControlBar::onPlayerRankChanged(const Player *p)
  1397. {
  1398. if (!p->isLocalPlayer())
  1399. return;
  1400. if(!(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints()))
  1401. {
  1402. if(TheTransitionHandler && TheInGameUI->getInputEnabled())
  1403. TheTransitionHandler->setGroup("ControlBarArrow");
  1404. }
  1405. // populateSpecialPowerShortcut((Player *)p);
  1406. m_genStarFlash = TRUE;
  1407. /// @todo implement me
  1408. markUIDirty();
  1409. }
  1410. //-------------------------------------------------------------------------------------------------
  1411. //-------------------------------------------------------------------------------------------------
  1412. void ControlBar::onPlayerSciencePurchasePointsChanged(const Player *p)
  1413. {
  1414. if (!p->isLocalPlayer())
  1415. return;
  1416. if(!(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints()))
  1417. {
  1418. if(TheTransitionHandler && TheInGameUI->getInputEnabled())
  1419. TheTransitionHandler->setGroup("ControlBarArrow");
  1420. }
  1421. // populateSpecialPowerShortcut((Player *)p);
  1422. m_genStarFlash = TRUE;
  1423. /// @todo implement me
  1424. markUIDirty();
  1425. }
  1426. //-------------------------------------------------------------------------------------------------
  1427. /** Given the drawables that we have selected into our context sensitive UI, evaluate
  1428. * and perform all UI manipulations to make the GUI show to the user what we want them
  1429. * to see */
  1430. //-------------------------------------------------------------------------------------------------
  1431. void ControlBar::evaluateContextUI( void )
  1432. {
  1433. //
  1434. // the UI has been "evaluated" and is now displaying the most current and correct
  1435. // information to the player
  1436. //
  1437. m_UIDirty = FALSE;
  1438. // if our purchase science window is up, we will want to update it by repopulating it.
  1439. if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden())
  1440. showPurchaseScience();
  1441. // erase any current state of the GUI by switching out to the empty context
  1442. switchToContext( CB_CONTEXT_NONE, NULL );
  1443. // sanity, nothing selected
  1444. if( TheInGameUI->getSelectCount() == 0 )
  1445. return;
  1446. // get the list of drawable IDs from the in game UI
  1447. const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables();
  1448. // sanity
  1449. if( selectedDrawables->empty() == TRUE )
  1450. return;
  1451. //Make sure the selected objects are in fact, controllable! If not, then
  1452. //we don't show any GUI commands for them!!!
  1453. //This is used when we select enemy objects or objects on another team.
  1454. //@todo we may want to show their portrait
  1455. if( !TheInGameUI->areSelectedObjectsControllable() )
  1456. {
  1457. //Also make sure the unit isn't a garrisonable neutral civ team building!
  1458. Drawable *draw = selectedDrawables->front();
  1459. //sanity
  1460. if( !draw )
  1461. {
  1462. return;
  1463. }
  1464. Object *obj = draw->getObject();
  1465. if( !obj )
  1466. {
  1467. return;
  1468. }
  1469. if (obj->getControllingPlayer()
  1470. && obj->getControllingPlayer()->getPlayerTemplate()
  1471. && obj->getControllingPlayer()->getPlayerTemplate()->getBeaconTemplate().compare(obj->getTemplate()->getName()) == 0
  1472. )
  1473. {
  1474. switchToContext( CB_CONTEXT_BEACON, draw );
  1475. }
  1476. else
  1477. {
  1478. switchToContext( CB_CONTEXT_NONE, draw );
  1479. }
  1480. //Check for a contain interface and a enemy relationship and reject that!
  1481. ContainModuleInterface *contain = obj->getContain();
  1482. if( contain && contain->getContainMax() > 0 )
  1483. {
  1484. const Player *otherPlayer = contain->getApparentControllingPlayer(ThePlayerList->getLocalPlayer());
  1485. if (!otherPlayer)
  1486. otherPlayer = obj->getControllingPlayer();
  1487. Player *player = ThePlayerList->getLocalPlayer();
  1488. if( !player || !otherPlayer )
  1489. {
  1490. //Sanity.
  1491. return;
  1492. }
  1493. Relationship relation = player->getRelationship( otherPlayer->getDefaultTeam() );
  1494. //Note: All following checks already account for the fact that this object
  1495. //isn't ours.
  1496. //The only case we can actually see a non-controlled controlbar is a neutral garrisonable structure.
  1497. if( !contain->isGarrisonable() || relation != NEUTRAL )
  1498. {
  1499. //Can't peek inside enemy/allied containers period!
  1500. return;
  1501. }
  1502. }
  1503. else
  1504. {
  1505. return;
  1506. }
  1507. }
  1508. //
  1509. // when we have multiple things selected, we will only display the common commands
  1510. // in the center command bar that can be displayed with multi-units selected
  1511. //
  1512. Drawable *drawToEvaluateFor = NULL;
  1513. Bool multiSelect = FALSE;
  1514. if( TheInGameUI->getSelectCount() > 1 )
  1515. {
  1516. // Attempt to isolate a Drawable here to evaluate
  1517. // The need arises when selected is an AngryMob,
  1518. // whose selection actually consists of varied units
  1519. // but is represented in the UI as a single unit,
  1520. // so we must isolate and evaluate only the Nexus
  1521. drawToEvaluateFor = TheGameClient->findDrawableByID( TheInGameUI->getSoloNexusSelectedDrawableID() ) ;
  1522. multiSelect = ( drawToEvaluateFor == NULL );
  1523. }
  1524. else // get the first and only drawble in the selection list
  1525. drawToEvaluateFor = selectedDrawables->front();
  1526. if( multiSelect )
  1527. {
  1528. switchToContext( CB_CONTEXT_MULTI_SELECT, NULL );
  1529. }
  1530. else if ( drawToEvaluateFor )// either we have exactly one drawable, or we have isolated one to evaluate for...
  1531. {
  1532. // get the first and only drawble in the selection list
  1533. //Drawable *draw = selectedDrawables->front();
  1534. // sanity
  1535. //if( draw == NULL )
  1536. // return;
  1537. // get object
  1538. Object *obj = drawToEvaluateFor->getObject();
  1539. if( obj == NULL )
  1540. return;
  1541. // we show no interface for objects being sold
  1542. if( obj->getStatusBits().test( OBJECT_STATUS_SOLD ) )
  1543. return;
  1544. static const NameKeyType key_OCLUpdate = NAMEKEY( "OCLUpdate" );
  1545. OCLUpdate *update = (OCLUpdate*)obj->findUpdateModule( key_OCLUpdate );
  1546. //
  1547. // a command center is context sensitive itself, if a side has *NOT* been chosen we display
  1548. // the side select interface for command centers only, but note how under construction is
  1549. // more important than anything
  1550. //
  1551. Bool contextSelected = FALSE;
  1552. if( obj->getStatusBits().test( OBJECT_STATUS_UNDER_CONSTRUCTION ) )
  1553. {
  1554. switchToContext( CB_CONTEXT_UNDER_CONSTRUCTION, drawToEvaluateFor );
  1555. contextSelected = TRUE;
  1556. } // end else if
  1557. // check for a regular switch to the appropriate context
  1558. if( contextSelected == FALSE )
  1559. {
  1560. ContainModuleInterface *cmi = obj->getContain();
  1561. if( cmi && cmi->isGarrisonable() && obj->getCommandSetString().isEmpty() )
  1562. {
  1563. //Kris: This is a convenient section to graft an inventory commandset for
  1564. //garrisoned troops. However, we only want to use this if we DON'T have
  1565. //a commandset defined. If we do, then trust that the commandset will
  1566. //handle it!
  1567. Player *localPlayer = ThePlayerList->getLocalPlayer();
  1568. Relationship relationship;
  1569. // we cannot select objects that are controlled by our enemies
  1570. relationship = localPlayer->getRelationship( obj->getTeam() );
  1571. if( obj->isLocallyControlled() == TRUE || relationship == NEUTRAL )
  1572. switchToContext( CB_CONTEXT_STRUCTURE_INVENTORY, drawToEvaluateFor );
  1573. } // end else if
  1574. else if( update )
  1575. {
  1576. switchToContext( CB_CONTEXT_OCL_TIMER, drawToEvaluateFor );
  1577. }
  1578. else if( obj->getCommandSetString().isEmpty() == FALSE )
  1579. {
  1580. switchToContext( CB_CONTEXT_COMMAND, drawToEvaluateFor );
  1581. } // end else if
  1582. else if (obj->getControllingPlayer()->getPlayerTemplate()->getBeaconTemplate().compare(obj->getTemplate()->getName()) == 0)
  1583. {
  1584. switchToContext( CB_CONTEXT_BEACON, drawToEvaluateFor );
  1585. }
  1586. else
  1587. switchToContext( CB_CONTEXT_NONE, drawToEvaluateFor );
  1588. } // end else
  1589. } // end else
  1590. } // end evaluateContextUI
  1591. //-------------------------------------------------------------------------------------------------
  1592. /** Find a command button of the given name if present */
  1593. //-------------------------------------------------------------------------------------------------
  1594. CommandButton *ControlBar::findNonConstCommandButton( const AsciiString& name )
  1595. {
  1596. for( const CommandButton *command = m_commandButtons; command; command = command->getNext() )
  1597. if( command->getName() == name )
  1598. return const_cast<CommandButton*>((const CommandButton*)command->getFinalOverride());
  1599. return NULL; // not found
  1600. } // end findCommandButton
  1601. //-------------------------------------------------------------------------------------------------
  1602. /** Allocate a new command button, assign name, and tie to list */
  1603. //-------------------------------------------------------------------------------------------------
  1604. CommandButton *ControlBar::newCommandButton( const AsciiString& name )
  1605. {
  1606. CommandButton *newButton;
  1607. // allocate new button
  1608. newButton = newInstance(CommandButton);
  1609. // assign name
  1610. newButton->setName(name);
  1611. // link to list
  1612. newButton->friend_addToList(&m_commandButtons);
  1613. // return the new button
  1614. return newButton;
  1615. } // end newCommandButton
  1616. //-------------------------------------------------------------------------------------------------
  1617. //-------------------------------------------------------------------------------------------------
  1618. CommandButton *ControlBar::newCommandButtonOverride( CommandButton *buttonToOverride )
  1619. {
  1620. if (!buttonToOverride) {
  1621. return NULL;
  1622. }
  1623. CommandButton *newOverride;
  1624. // allocate new button
  1625. newOverride = newInstance(CommandButton);
  1626. *newOverride = *buttonToOverride;
  1627. newOverride->markAsOverride();
  1628. buttonToOverride->setNextOverride(newOverride);
  1629. return newOverride;
  1630. }
  1631. //-------------------------------------------------------------------------------------------------
  1632. /** Parse a command set */
  1633. //-------------------------------------------------------------------------------------------------
  1634. /*static*/ void ControlBar::parseCommandSetDefinition( INI *ini )
  1635. {
  1636. AsciiString name;
  1637. CommandSet *commandSet;
  1638. // read the name
  1639. const char* c = ini->getNextToken();
  1640. name.set( c );
  1641. // find existing item if present
  1642. commandSet = TheControlBar->findNonConstCommandSet( name );
  1643. if( commandSet == NULL )
  1644. {
  1645. // allocate a new item
  1646. commandSet = TheControlBar->newCommandSet( name );
  1647. if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) {
  1648. commandSet->markAsOverride();
  1649. }
  1650. } // end if
  1651. else if( ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES )
  1652. {
  1653. //Holy crap, this sucks to debug!!!
  1654. //If you have two different command sets, the previous
  1655. //code would simply allow you to define multiple command set
  1656. //with the same name, and just nuke the old button with the new one.
  1657. //So, I (KM) have added this assert to notify in case of two same-name
  1658. //command set.
  1659. DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate commandset %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
  1660. throw INI_INVALID_DATA;
  1661. //@todo SUPPORT OVERRIDES -- JM
  1662. } else {
  1663. commandSet = TheControlBar->newCommandSetOverride(commandSet);
  1664. }
  1665. // sanity
  1666. DEBUG_ASSERTCRASH( commandSet, ("parseCommandSetDefinition: Unable to allocate set '%s'\n", name.str()) );
  1667. // parse the ini definition
  1668. ini->initFromINI( commandSet, commandSet->friend_getFieldParse() );
  1669. } // end parseCommandSetDefinition
  1670. //-------------------------------------------------------------------------------------------------
  1671. /** Find existing command set by name */
  1672. //-------------------------------------------------------------------------------------------------
  1673. CommandSet* ControlBar::findNonConstCommandSet( const AsciiString& name )
  1674. {
  1675. CommandSet* set;
  1676. for( set = m_commandSets; set != NULL; set = set->friend_getNext() )
  1677. if( set->getName() == name )
  1678. return const_cast<CommandSet*>((const CommandSet *) set);
  1679. return NULL; // set not found
  1680. }
  1681. //-------------------------------------------------------------------------------------------------
  1682. /** find existing command button if present */
  1683. //-------------------------------------------------------------------------------------------------
  1684. const CommandButton *ControlBar::findCommandButton( const AsciiString& name )
  1685. {
  1686. CommandButton *btn = findNonConstCommandButton(name);
  1687. if( btn )
  1688. {
  1689. btn = (CommandButton *)btn->friend_getFinalOverride();
  1690. }
  1691. return btn;
  1692. }
  1693. //-------------------------------------------------------------------------------------------------
  1694. /** Find existing command set by name */
  1695. //-------------------------------------------------------------------------------------------------
  1696. const CommandSet *ControlBar::findCommandSet( const AsciiString& name )
  1697. {
  1698. CommandSet *set = findNonConstCommandSet(name);
  1699. if (set)
  1700. set = (CommandSet*)set->friend_getFinalOverride();
  1701. return set;
  1702. }
  1703. //-------------------------------------------------------------------------------------------------
  1704. /** Allocate a new command set, link to list, initialize to default, and return it */
  1705. //-------------------------------------------------------------------------------------------------
  1706. CommandSet *ControlBar::newCommandSet( const AsciiString& name )
  1707. {
  1708. // allocate a new set
  1709. CommandSet* set = newInstance(CommandSet)(name);
  1710. // add it to the list.
  1711. set->friend_addToList(&m_commandSets);
  1712. // return the newly created set
  1713. return set;
  1714. } // end newCommandSet
  1715. //-------------------------------------------------------------------------------------------------
  1716. /** Create an overridden command set. */
  1717. //-------------------------------------------------------------------------------------------------
  1718. CommandSet *ControlBar::newCommandSetOverride( CommandSet *setToOverride )
  1719. {
  1720. if (!setToOverride) {
  1721. return NULL;
  1722. }
  1723. // allocate a new set
  1724. CommandSet* set = newInstance(CommandSet)(setToOverride->getName());
  1725. // it's an override; DON'T add it to the main list.
  1726. // !!! DO NOT DO THIS !!! -- > set->friend_addToList(&m_commandSets); <-- !!! DO NOT DO THIS !!!
  1727. *set = *setToOverride;
  1728. set->markAsOverride();
  1729. setToOverride->setNextOverride(set);
  1730. return set;
  1731. }
  1732. //-------------------------------------------------------------------------------------------------
  1733. /** Process a button click for the context sensitive GUI */
  1734. //-------------------------------------------------------------------------------------------------
  1735. CBCommandStatus ControlBar::processContextSensitiveButtonClick( GameWindow *button,
  1736. GadgetGameMessage gadgetMessage )
  1737. {
  1738. // call command processing method
  1739. return processCommandUI( button, gadgetMessage );
  1740. } // end processContextSensitiveButtonClick
  1741. //-------------------------------------------------------------------------------------------------
  1742. /** Process a button click for the context sensitive GUI */
  1743. //-------------------------------------------------------------------------------------------------
  1744. CBCommandStatus ControlBar::processContextSensitiveButtonTransition( GameWindow *button,
  1745. GadgetGameMessage gadgetMessage )
  1746. {
  1747. // call command processing method
  1748. return processCommandTransitionUI( button, gadgetMessage );
  1749. } // end processContextSensitiveButtonClick
  1750. //-------------------------------------------------------------------------------------------------
  1751. /** Switch the user interface to the new context specified and fill out any of the
  1752. * art and/or buttons that we need to for the new context using data from the object
  1753. * passed in */
  1754. //-------------------------------------------------------------------------------------------------
  1755. void ControlBar::switchToContext( ControlBarContext context, Drawable *draw )
  1756. {
  1757. // restore the right hud to a plain window
  1758. setPortraitByObject( NULL );
  1759. Object *obj = draw ? draw->getObject() : NULL;
  1760. setPortraitByObject( obj );
  1761. // if we're switching context, we have to repopulate the hotkey manager
  1762. if(TheHotKeyManager)
  1763. TheHotKeyManager->reset();
  1764. // ... and also remove any radius cursor that is active.
  1765. TheInGameUI->setRadiusCursorNone();
  1766. // save a pointer for the currently selected drawable
  1767. m_currentSelectedDrawable = draw;
  1768. if (IsInGameChatActive() == FALSE && TheGameLogic && !TheGameLogic->isInShellGame()) {
  1769. TheWindowManager->winSetFocus( NULL );
  1770. }
  1771. // hide/un-hide the appropriate windows for the context
  1772. switch( context )
  1773. {
  1774. //-------------------------------------------------------------------------------------------------
  1775. case CB_CONTEXT_NONE:
  1776. {
  1777. // show or hide the right window groups
  1778. //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1779. m_contextParent[ CP_COMMAND ]->winHide( TRUE );
  1780. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1781. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1782. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1783. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1784. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1785. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1786. //Clear any potentially flashing buttons!
  1787. for( int i = 0; i < MAX_COMMANDS_PER_SET; i++ )
  1788. {
  1789. // the implementation won't necessarily use the max number of windows possible
  1790. if (m_commandWindows[ i ])
  1791. {
  1792. m_commandWindows[ i ]->winClearStatus( WIN_STATUS_FLASHING );
  1793. }
  1794. }
  1795. // if there is a current selected drawable then we wil display a selection portrait if present
  1796. if( draw )
  1797. {
  1798. //Get the current thing template.
  1799. const ThingTemplate *thing = draw->getTemplate();
  1800. //Special case -- if we are a GLA hole, then get the rebuild building template
  1801. Object *obj = draw->getObject();
  1802. if( obj && obj->isKindOf( KINDOF_REBUILD_HOLE ) )
  1803. {
  1804. RebuildHoleBehaviorInterface *rhbi = RebuildHoleBehavior::getRebuildHoleBehaviorInterfaceFromObject( obj );
  1805. if( rhbi )
  1806. {
  1807. thing = rhbi->getRebuildTemplate();
  1808. }
  1809. }
  1810. //Set the correct portrait.
  1811. setPortraitByObject( obj );
  1812. }
  1813. // do not show any rally point marker
  1814. showRallyPoint( NULL );
  1815. break;
  1816. } // end none
  1817. //---------------------------------------------------------------------------------------------
  1818. case CB_CONTEXT_COMMAND:
  1819. {
  1820. // show or hide the right window groups
  1821. //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1822. m_contextParent[ CP_COMMAND ]->winHide( FALSE );
  1823. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1824. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1825. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1826. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1827. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1828. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1829. // fill the specific UI info
  1830. populateCommand( draw->getObject() );
  1831. //
  1832. // for objects that are able to create units, we show a build queue if we actually
  1833. // actually have something in production, otherwise we show the selection portrait
  1834. //
  1835. if( obj )
  1836. {
  1837. ProductionUpdateInterface *pu = obj->getProductionUpdateInterface();
  1838. if( pu && pu->firstProduction() != NULL )
  1839. {
  1840. m_contextParent[ CP_BUILD_QUEUE ]->winHide( FALSE );
  1841. populateBuildQueue( obj );
  1842. setPortraitByObject( NULL );
  1843. } // end if
  1844. else
  1845. {
  1846. setPortraitByObject( obj );
  1847. }
  1848. } // end if
  1849. break;
  1850. } // end command
  1851. //---------------------------------------------------------------------------------------------
  1852. case CB_CONTEXT_STRUCTURE_INVENTORY:
  1853. {
  1854. // show or hide the right window groups
  1855. //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1856. m_contextParent[ CP_COMMAND ]->winHide( FALSE );
  1857. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1858. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1859. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1860. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1861. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1862. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1863. // fill the specific UI info
  1864. populateStructureInventory( draw->getObject() );
  1865. break;
  1866. } // end inventory
  1867. //---------------------------------------------------------------------------------------------
  1868. case CB_CONTEXT_BEACON:
  1869. {
  1870. // show or hide the right window groups
  1871. //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1872. m_contextParent[ CP_COMMAND ]->winHide( TRUE );
  1873. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1874. m_contextParent[ CP_BEACON ]->winHide( FALSE );
  1875. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1876. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1877. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1878. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1879. // fill the specific UI info
  1880. populateBeacon( draw->getObject() );
  1881. break;
  1882. } // end beacon
  1883. //---------------------------------------------------------------------------------------------
  1884. case CB_CONTEXT_UNDER_CONSTRUCTION:
  1885. {
  1886. // show or hide the right window groups
  1887. //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1888. m_contextParent[ CP_COMMAND ]->winHide( TRUE );
  1889. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1890. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1891. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( FALSE );
  1892. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1893. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1894. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1895. // fill the specific UI info
  1896. populateUnderConstruction( draw->getObject() );
  1897. break;
  1898. } // end under construction
  1899. //---------------------------------------------------------------------------------------------
  1900. case CB_CONTEXT_OCL_TIMER:
  1901. {
  1902. // show or hide the right window groups
  1903. // m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1904. m_contextParent[ CP_COMMAND ]->winHide( TRUE );
  1905. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1906. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1907. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1908. m_contextParent[ CP_OCL_TIMER ]->winHide( FALSE );
  1909. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1910. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1911. // fill the specific UI info
  1912. populateOCLTimer( draw->getObject() );
  1913. break;
  1914. } // end under construction
  1915. //---------------------------------------------------------------------------------------------
  1916. case CB_CONTEXT_MULTI_SELECT:
  1917. {
  1918. // show or hide the right window groups
  1919. // m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1920. m_contextParent[ CP_COMMAND ]->winHide( FALSE ); // multi select shows common commands
  1921. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1922. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1923. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1924. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1925. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1926. m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE );
  1927. // fill the specific UI info
  1928. populateMultiSelect();
  1929. break;
  1930. } // end multi select
  1931. case CB_CONTEXT_OBSERVER_LIST:
  1932. {
  1933. // show or hide the right window groups
  1934. // m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  1935. m_contextParent[ CP_COMMAND ]->winHide( TRUE );
  1936. m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE );
  1937. m_contextParent[ CP_BEACON ]->winHide( TRUE );
  1938. m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE );
  1939. m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE );
  1940. m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE );
  1941. m_contextParent[ CP_OBSERVER_LIST ]->winHide( FALSE );
  1942. // fill the specific UI info
  1943. populateObserverList();
  1944. break;
  1945. } // end multi select
  1946. //---------------------------------------------------------------------------------------------
  1947. default:
  1948. {
  1949. DEBUG_ASSERTCRASH( 0, ("ControlBar::switchToContext, unknown context '%d'\n", context) );
  1950. break;
  1951. } // end default
  1952. } // end switch
  1953. // save our context
  1954. m_currContext = context;
  1955. } // end switchToContext
  1956. void ControlBar::setCommandBarBorder( GameWindow *button, CommandButtonMappedBorderType type)
  1957. {
  1958. if(!button)
  1959. return;
  1960. switch( type )
  1961. {
  1962. case COMMAND_BUTTON_BORDER_BUILD:
  1963. {
  1964. GadgetButtonSetBorder(button, m_commandButtonBorderBuildColor);
  1965. break;
  1966. }
  1967. //-------------------------------------------------------------------------------------------------
  1968. case COMMAND_BUTTON_BORDER_UPGRADE:
  1969. {
  1970. GadgetButtonSetBorder(button, m_commandButtonBorderUpgradeColor );
  1971. break;
  1972. }
  1973. //-------------------------------------------------------------------------------------------------
  1974. case COMMAND_BUTTON_BORDER_ACTION:
  1975. {
  1976. GadgetButtonSetBorder(button, m_commandButtonBorderActionColor);
  1977. break;
  1978. }
  1979. //-------------------------------------------------------------------------------------------------
  1980. case COMMAND_BUTTON_BORDER_SYSTEM:
  1981. {
  1982. GadgetButtonSetBorder(button, m_commandButtonBorderSystemColor);
  1983. break;
  1984. }
  1985. //-------------------------------------------------------------------------------------------------
  1986. case COMMAND_BUTTON_BORDER_NONE:
  1987. default:
  1988. GadgetButtonSetBorder(button, GAME_COLOR_UNDEFINED, FALSE);
  1989. }
  1990. }
  1991. //-------------------------------------------------------------------------------------------------
  1992. /** Set the command data into the control */
  1993. //-------------------------------------------------------------------------------------------------
  1994. void ControlBar::setControlCommand( GameWindow *button, const CommandButton *commandButton )
  1995. {
  1996. // the window must be a gadget button
  1997. if( button->winGetInputFunc() != GadgetPushButtonInput )
  1998. {
  1999. DEBUG_ASSERTCRASH( 0, ("setControlCommand: Window is not a button\n") );
  2000. return;
  2001. } // end if
  2002. // sanity
  2003. if( commandButton == NULL )
  2004. {
  2005. DEBUG_ASSERTCRASH( 0, ("setControlCommand: NULL commandButton passed in\n") );
  2006. return;
  2007. } // end if
  2008. //
  2009. // set the button gadget control to be a normal button or a check like button if
  2010. // the command says it needs one
  2011. //
  2012. if( BitTest( commandButton->getOptions(), CHECK_LIKE ))
  2013. GadgetButtonEnableCheckLike( button, TRUE, FALSE );
  2014. else
  2015. GadgetButtonEnableCheckLike( button, FALSE, FALSE );
  2016. //
  2017. // set the imagry ... note that for 99% of the command buttons it's sufficient to specify
  2018. // only the disabled, enabled, hilite, and hilite pushed images. For push-like buttons
  2019. // we actually utilize all the state available to a GameWindow. We will replicate the
  2020. // hilite pushed image to be the enabled pushed image ... and we will also replicate
  2021. // the disabled image to be the disabled pushed image. For complete control over all
  2022. // the states of these buttons we would add additional lines to the INI for a command
  2023. // button and store those additional images in the command button
  2024. //
  2025. if( commandButton->getButtonImage() )
  2026. GadgetButtonSetEnabledImage( button, commandButton->getButtonImage() );
  2027. //if( commandButton->getDisabledImage() )
  2028. //{
  2029. // GadgetButtonSetDisabledImage( button, commandButton->getDisabledImage() );
  2030. // GadgetButtonSetDisabledSelectedImage( button, commandButton->getDisabledImage() );
  2031. //} //end if
  2032. //if( commandButton->getHiliteImage() )
  2033. // GadgetButtonSetHiliteImage( button, commandButton->getHiliteImage() );
  2034. //if( commandButton->getPushedImage() )
  2035. //{
  2036. // GadgetButtonSetHiliteSelectedImage( button, commandButton->getPushedImage() );
  2037. // GadgetButtonSetEnabledSelectedImage( button, commandButton->getPushedImage() );
  2038. //} // end if
  2039. // set the text
  2040. if( commandButton->getTextLabel().isEmpty() == FALSE || !commandButton->getScienceVec().empty())
  2041. {
  2042. button->winSetTooltipFunc(commandButtonTooltip);
  2043. }
  2044. else
  2045. GadgetButtonSetText( button, UnicodeString( L"" ) );
  2046. // save the command in the user data of the window
  2047. GadgetButtonSetData(button, (void*)commandButton);
  2048. //button->winSetUserData( commandButton );
  2049. setCommandBarBorder(button, commandButton->getCommandButtonMappedBorderType());
  2050. if (TheHotKeyManager)
  2051. {
  2052. AsciiString hotKey = TheHotKeyManager->searchHotKey(commandButton->getTextLabel());
  2053. if(hotKey.isNotEmpty())
  2054. TheHotKeyManager->addHotKey(button, hotKey);
  2055. }
  2056. GadgetButtonSetAltSound(button, "GUICommandBarClick");
  2057. } // end setControlCommand
  2058. //-------------------------------------------------------------------------------------------------
  2059. void CommandButton::cacheButtonImage()
  2060. {
  2061. if (!TheMappedImageCollection) {
  2062. return;
  2063. }
  2064. if( m_buttonImageName.isNotEmpty() )
  2065. {
  2066. m_buttonImage = TheMappedImageCollection->findImageByName( m_buttonImageName );
  2067. DEBUG_ASSERTCRASH( m_buttonImage, ("CommandButton: %s is looking for button image %s but can't find it. Skipping...", m_name.str(), m_buttonImageName.str() ) );
  2068. m_buttonImageName.clear(); // we're done with this, so nuke it
  2069. }
  2070. }
  2071. //-------------------------------------------------------------------------------------------------
  2072. /** post process step, after all commands and command sets are loaded */
  2073. //-------------------------------------------------------------------------------------------------
  2074. void ControlBar::postProcessCommands( void )
  2075. {
  2076. for ( CommandButton *button = m_commandButtons; button; button = button->friend_getNext() )
  2077. {
  2078. button->cacheButtonImage();
  2079. }
  2080. }
  2081. //-------------------------------------------------------------------------------------------------
  2082. /** set the command for the button identified by the window name
  2083. * NOTE that parent may be NULL, it only helps to speed up the search for a particular
  2084. * window ID */
  2085. //-------------------------------------------------------------------------------------------------
  2086. void ControlBar::setControlCommand( const AsciiString& buttonWindowName, GameWindow *parent,
  2087. const CommandButton *commandButton )
  2088. {
  2089. UnsignedInt winID = TheNameKeyGenerator->nameToKey( buttonWindowName );
  2090. GameWindow *win = TheWindowManager->winGetWindowFromId( parent, winID );
  2091. if( win == NULL )
  2092. {
  2093. DEBUG_ASSERTCRASH( 0, ("setControlCommand: Unable to find window '%s'\n", buttonWindowName.str()) );
  2094. return;
  2095. } // end if
  2096. // call the workhorse
  2097. setControlCommand( win, commandButton );
  2098. } // end setControlCommand
  2099. //-------------------------------------------------------------------------------------------------
  2100. /** show/hide the portrait window image */
  2101. //-------------------------------------------------------------------------------------------------
  2102. void ControlBar::setPortraitByImage( const Image *image )
  2103. {
  2104. if( image )
  2105. {
  2106. m_rightHUDUnitSelectParent->winHide(FALSE);
  2107. m_rightHUDCameoWindow->winSetEnabledImage( 0, image );
  2108. //m_rightHUDWindow->winSetEnabledImage( 0, image );
  2109. m_rightHUDWindow->winClearStatus( WIN_STATUS_IMAGE );
  2110. m_rightHUDCameoWindow->winSetStatus( WIN_STATUS_IMAGE );
  2111. for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i)
  2112. m_rightHUDUpgradeCameos[i]->winHide(TRUE);
  2113. } // end if
  2114. else
  2115. {
  2116. m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE );
  2117. m_rightHUDCameoWindow->winClearStatus( WIN_STATUS_IMAGE );
  2118. m_rightHUDUnitSelectParent->winHide(TRUE);
  2119. for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i)
  2120. m_rightHUDUpgradeCameos[i]->winHide(TRUE);
  2121. //m_rightHUDWindow->winSetEnabledImage( 0, image );
  2122. //m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE );
  2123. }
  2124. } // end setPortraitByImage
  2125. //-------------------------------------------------------------------------------------------------
  2126. /** show/hide the portrait image by object. We like to use this method as opposed to the
  2127. * plain image one above so that we can build more intelligence into what portrait to
  2128. * show for an object given its current state or object type */
  2129. //-------------------------------------------------------------------------------------------------
  2130. void ControlBar::setPortraitByObject( Object *obj )
  2131. {
  2132. if( obj )
  2133. {
  2134. if( obj->isKindOf( KINDOF_SHOW_PORTRAIT_WHEN_CONTROLLED ) && !obj->isLocallyControlled() )
  2135. {
  2136. //Handles civ vehicles without terrorists in them
  2137. setPortraitByObject( NULL );
  2138. return;
  2139. }
  2140. const ThingTemplate *thing = obj->getTemplate();
  2141. Player *player = obj->getControllingPlayer();
  2142. //If we have an enemy stealth disguised unit, swap portraits!
  2143. Drawable *draw = obj->getDrawable();
  2144. if( draw && draw->getStealthLook() == STEALTHLOOK_DISGUISED_ENEMY )
  2145. {
  2146. thing = draw->getTemplate();
  2147. if( thing->isKindOf( KINDOF_SHOW_PORTRAIT_WHEN_CONTROLLED ) )
  2148. {
  2149. //If a bomb truck disguises as a civ vehicle, don't use it's portrait (or else you'll see the terrorist).
  2150. setPortraitByObject( NULL );
  2151. return;
  2152. }
  2153. StealthUpdate *stealth = obj->getStealth();
  2154. if( stealth && stealth->isDisguised() )
  2155. {
  2156. //Fake player upgrades too!
  2157. player = ThePlayerList->getNthPlayer( stealth->getDisguisedPlayerIndex() );
  2158. }
  2159. }
  2160. const Image* portrait = thing->getSelectedPortraitImage();
  2161. m_rightHUDUnitSelectParent->winHide(FALSE);
  2162. // enable the window window as an image window and set the image
  2163. m_rightHUDCameoWindow->winSetEnabledImage( 0, portrait );
  2164. //Display the veterancy rank of the object on the portrait.
  2165. const Image *image = calculateVeterancyOverlayForObject( obj );
  2166. GadgetButtonDrawOverlayImage( m_rightHUDCameoWindow, image );
  2167. //m_rightHUDWindow->winSetEnabledImage( 0, portrait );
  2168. m_rightHUDWindow->winClearStatus( WIN_STATUS_IMAGE );
  2169. m_rightHUDCameoWindow->winSetStatus( WIN_STATUS_IMAGE );
  2170. for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i)
  2171. {
  2172. AsciiString upgradeName = thing->getUpgradeCameoName(i);
  2173. if(upgradeName.isEmpty())
  2174. {
  2175. m_rightHUDUpgradeCameos[i]->winHide(TRUE);
  2176. continue;
  2177. }
  2178. const UpgradeTemplate *ut = TheUpgradeCenter->findUpgrade(upgradeName);
  2179. if(!ut)
  2180. {
  2181. m_rightHUDUpgradeCameos[i]->winHide(TRUE);
  2182. continue;
  2183. }
  2184. m_rightHUDUpgradeCameos[i]->winHide(FALSE);
  2185. m_rightHUDUpgradeCameos[i]->winSetEnabledImage( 0, ut->getButtonImage() );
  2186. if( obj->hasUpgrade(ut) )
  2187. {
  2188. //Object level upgrades
  2189. m_rightHUDUpgradeCameos[i]->winEnable( TRUE );
  2190. }
  2191. else if( player && player->hasUpgradeComplete( ut ) )
  2192. {
  2193. //Player level upgrades
  2194. m_rightHUDUpgradeCameos[i]->winEnable( TRUE );
  2195. }
  2196. else
  2197. {
  2198. //Failure
  2199. m_rightHUDUpgradeCameos[i]->winEnable( FALSE );
  2200. }
  2201. }
  2202. } // end if
  2203. else
  2204. {
  2205. m_rightHUDUnitSelectParent->winHide(TRUE);
  2206. m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE );
  2207. m_rightHUDCameoWindow->winClearStatus( WIN_STATUS_IMAGE );
  2208. for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i)
  2209. m_rightHUDUpgradeCameos[i]->winHide(TRUE);
  2210. //Clear any overlay the portrait had on it.
  2211. GadgetButtonDrawOverlayImage( m_rightHUDCameoWindow, NULL );
  2212. }
  2213. } // end setPortraitByObject
  2214. // ------------------------------------------------------------------------------------------------
  2215. /** Show a rally point marker at the world location specified. If no location is specified
  2216. * any marker that we might have visible is hidden */
  2217. // ------------------------------------------------------------------------------------------------
  2218. void ControlBar::showRallyPoint( const Coord3D *loc )
  2219. {
  2220. // if loc is NULL, destroy any rally point drawble we have shown
  2221. if( loc == NULL )
  2222. {
  2223. // destroy rally point drawable if present
  2224. if( m_rallyPointDrawableID != INVALID_DRAWABLE_ID )
  2225. TheGameClient->destroyDrawable( TheGameClient->findDrawableByID( m_rallyPointDrawableID ) );
  2226. m_rallyPointDrawableID = INVALID_DRAWABLE_ID;
  2227. } // end if
  2228. else
  2229. {
  2230. Drawable *marker = NULL;
  2231. // create a rally point drawble if necessary
  2232. if( m_rallyPointDrawableID == INVALID_DRAWABLE_ID )
  2233. {
  2234. const ThingTemplate* ttn = TheThingFactory->findTemplate("RallyPointMarker");
  2235. marker = TheThingFactory->newDrawable( ttn );
  2236. DEBUG_ASSERTCRASH( marker, ("showRallyPoint: Unable to create rally point drawable\n") );
  2237. if (marker)
  2238. {
  2239. marker->setDrawableStatus(DRAWABLE_STATUS_NO_SAVE);
  2240. m_rallyPointDrawableID = marker->getID();
  2241. }
  2242. } // end if
  2243. else
  2244. marker = TheGameClient->findDrawableByID( m_rallyPointDrawableID );
  2245. // sanity
  2246. DEBUG_ASSERTCRASH( marker, ("showRallyPoint: No rally point marker found\n" ) );
  2247. // set the position of the rally point drawble to the position passed in
  2248. marker->setPosition( loc );
  2249. marker->setOrientation( TheGlobalData->m_downwindAngle );//To blow down wind -- ML
  2250. // set the marker colors to that of the local player
  2251. Player *player = ThePlayerList->getLocalPlayer();
  2252. if (TheGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT)
  2253. marker->setIndicatorColor( player->getPlayerNightColor() );
  2254. else
  2255. marker->setIndicatorColor( player->getPlayerColor() );
  2256. } // end else
  2257. } // end showRallyPoint
  2258. // ------------------------------------------------------------------------------------------------
  2259. /** Show a rally point marker at the world location specified. If no location is specified
  2260. * any marker that we might have visible is hidden */
  2261. // ------------------------------------------------------------------------------------------------
  2262. void ControlBar::setControlBarSchemeByPlayer(Player *p)
  2263. {
  2264. if(m_controlBarSchemeManager)
  2265. m_controlBarSchemeManager->setControlBarSchemeByPlayer(p);
  2266. static NameKeyType buttonPlaceBeaconID = NAMEKEY( "ControlBar.wnd:ButtonPlaceBeacon" );
  2267. static NameKeyType buttonIdleWorkerID = NAMEKEY("ControlBar.wnd:ButtonIdleWorker");
  2268. static NameKeyType buttonGeneralID = NAMEKEY("ControlBar.wnd:ButtonGeneral");
  2269. GameWindow *buttonPlaceBeacon = TheWindowManager->winGetWindowFromId( NULL, buttonPlaceBeaconID );
  2270. GameWindow *buttonIdleWorker = TheWindowManager->winGetWindowFromId( NULL, buttonIdleWorkerID );
  2271. GameWindow *buttonGeneral = TheWindowManager->winGetWindowFromId( NULL, buttonGeneralID );
  2272. if( !p->isPlayerActive() )
  2273. {
  2274. m_isObserverCommandBar = TRUE;
  2275. switchToContext( CB_CONTEXT_OBSERVER_LIST, NULL );
  2276. DEBUG_LOG(("We're loading the Observer Command Bar\n"));
  2277. if (buttonPlaceBeacon)
  2278. buttonPlaceBeacon->winHide(TRUE);
  2279. if (buttonIdleWorker)
  2280. buttonIdleWorker->winHide(TRUE);
  2281. if (buttonGeneral)
  2282. buttonGeneral->winEnable(FALSE);
  2283. }
  2284. else
  2285. {
  2286. switchToContext( CB_CONTEXT_NONE, NULL );
  2287. m_isObserverCommandBar = FALSE;
  2288. if (buttonPlaceBeacon)
  2289. buttonPlaceBeacon->winHide(
  2290. (TheGameLogic->getGameMode() != GAME_LAN && TheGameLogic->getGameMode() != GAME_INTERNET) ||
  2291. !TheGameInfo->isMultiPlayer());
  2292. if (buttonIdleWorker)
  2293. buttonIdleWorker->winHide(FALSE);
  2294. if (buttonGeneral)
  2295. {
  2296. buttonGeneral->winHide(FALSE);
  2297. buttonGeneral->winEnable(TRUE);
  2298. }
  2299. }
  2300. switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
  2301. }
  2302. void ControlBar::setControlBarSchemeByPlayerTemplate( const PlayerTemplate *pt)
  2303. {
  2304. if(m_controlBarSchemeManager)
  2305. m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(pt);
  2306. static NameKeyType buttonPlaceBeaconID = NAMEKEY( "ControlBar.wnd:ButtonPlaceBeacon" );
  2307. static NameKeyType buttonIdleWorkerID = NAMEKEY("ControlBar.wnd:ButtonIdleWorker");
  2308. static NameKeyType buttonGeneralID = NAMEKEY("ControlBar.wnd:ButtonGeneral");
  2309. GameWindow *buttonPlaceBeacon = TheWindowManager->winGetWindowFromId( NULL, buttonPlaceBeaconID );
  2310. GameWindow *buttonIdleWorker = TheWindowManager->winGetWindowFromId( NULL, buttonIdleWorkerID );
  2311. GameWindow *buttonGeneral = TheWindowManager->winGetWindowFromId( NULL, buttonGeneralID );
  2312. if(pt == ThePlayerTemplateStore->findPlayerTemplate(TheNameKeyGenerator->nameToKey("FactionObserver")))
  2313. {
  2314. m_isObserverCommandBar = TRUE;
  2315. switchToContext( CB_CONTEXT_OBSERVER_LIST, NULL );
  2316. DEBUG_LOG(("We're loading the Observer Command Bar\n"));
  2317. if (buttonPlaceBeacon)
  2318. buttonPlaceBeacon->winHide(TRUE);
  2319. if (buttonIdleWorker)
  2320. buttonIdleWorker->winHide(TRUE);
  2321. if (buttonGeneral)
  2322. buttonGeneral->winEnable(FALSE);
  2323. }
  2324. else
  2325. {
  2326. switchToContext( CB_CONTEXT_NONE, NULL );
  2327. m_isObserverCommandBar = FALSE;
  2328. if (buttonPlaceBeacon)
  2329. buttonPlaceBeacon->winHide(
  2330. (TheGameLogic->getGameMode() != GAME_LAN && TheGameLogic->getGameMode() != GAME_INTERNET) ||
  2331. !TheGameInfo->isMultiPlayer());
  2332. if (buttonIdleWorker)
  2333. buttonIdleWorker->winHide(FALSE);
  2334. if (buttonGeneral)
  2335. {
  2336. buttonGeneral->winHide(FALSE);
  2337. buttonGeneral->winEnable(TRUE);
  2338. }
  2339. }
  2340. switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
  2341. hidePurchaseScience();
  2342. }
  2343. void ControlBar::setControlBarSchemeByName(const AsciiString& name)
  2344. {
  2345. if(m_controlBarSchemeManager)
  2346. m_controlBarSchemeManager->setControlBarScheme( name );
  2347. switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
  2348. }
  2349. void ControlBar::preloadAssets( TimeOfDay timeOfDay )
  2350. {
  2351. if (m_controlBarSchemeManager)
  2352. m_controlBarSchemeManager->preloadAssets( timeOfDay );
  2353. }
  2354. void ControlBar::updateBuildQueueDisabledImages( const Image *image )
  2355. {
  2356. if(!image)
  2357. return;
  2358. // We have to do this because the build queue data might have been reset
  2359. static NameKeyType buildQueueIDs[ MAX_BUILD_QUEUE_BUTTONS ];
  2360. static Bool idsInitialized = FALSE;
  2361. Int i;
  2362. // get name key ids for the build queue buttons
  2363. if( idsInitialized == FALSE )
  2364. {
  2365. AsciiString buttonName;
  2366. for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ )
  2367. {
  2368. buttonName.format( "ControlBar.wnd:ButtonQueue%02d", i + 1 );
  2369. buildQueueIDs[ i ] = TheNameKeyGenerator->nameToKey( buttonName );
  2370. } // end for i
  2371. idsInitialized = TRUE;
  2372. } // end if
  2373. // get window pointers to all the buttons for the build queue
  2374. for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ )
  2375. {
  2376. // get window commented out cause I believe we already set this. We'll see in a few minutes
  2377. m_queueData[ i ].control = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_BUILD_QUEUE ],
  2378. buildQueueIDs[ i ] );
  2379. GadgetButtonSetDisabledImage( m_queueData[ i ].control, image );
  2380. } // end for i
  2381. }
  2382. void ControlBar::updateRightHUDImage( const Image *image )
  2383. {
  2384. if(!m_rightHUDWindow || !image)
  2385. return;
  2386. m_rightHUDWindow->winSetEnabledImage(0, image);
  2387. }
  2388. void ControlBar::updateBuildUpClockColor( Color color)
  2389. {
  2390. m_buildUpClockColor = color;
  2391. }
  2392. void ControlBar::updateCommanBarBorderColors(Color build, Color action, Color upgrade, Color system )
  2393. {
  2394. m_commandButtonBorderBuildColor = build;
  2395. m_commandButtonBorderActionColor = action;
  2396. m_commandButtonBorderUpgradeColor = upgrade;
  2397. m_commandButtonBorderSystemColor = system;
  2398. }
  2399. // ---------------------------------------------------------------------------------------
  2400. // hides the communicator button
  2401. void ControlBar::hideCommunicator( Bool b )
  2402. {
  2403. //sanity
  2404. if( m_communicatorButton != NULL )
  2405. m_communicatorButton->winHide( b );
  2406. }
  2407. // ---------------------------------------------------------------------------------------
  2408. // Outside hook so when the genera's head is pushed, we can switch to the purchase science
  2409. // context
  2410. void ControlBar::updatePurchaseScience( void )
  2411. {
  2412. // if(m_generalsScreenAnimate && TheGlobalData->m_animateWindows)
  2413. // {
  2414. // Bool wasFinished = m_generalsScreenAnimate->isFinished();
  2415. // m_generalsScreenAnimate->update();
  2416. // if (m_generalsScreenAnimate->isFinished() && !wasFinished && m_generalsScreenAnimate->isReversed())
  2417. // m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide(TRUE);
  2418. // }
  2419. }
  2420. void ControlBar::showPurchaseScience( void )
  2421. {
  2422. if(TheScriptEngine->isGameEnding())
  2423. return;
  2424. populatePurchaseScience(ThePlayerList->getLocalPlayer());
  2425. m_genStarFlash = FALSE;
  2426. if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden())
  2427. return;
  2428. //switchToContext(CB_CONTEXT_PURCHASE_SCIENCE, NULL);
  2429. m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide(FALSE);
  2430. if (TheGlobalData->m_animateWindows)
  2431. TheTransitionHandler->setGroup("GenExpFade");
  2432. //m_generalsScreenAnimate->registerGameWindow( m_contextParent[ CP_PURCHASE_SCIENCE ], WIN_ANIMATION_SLIDE_TOP, TRUE, 200 );
  2433. }
  2434. void ControlBar::hidePurchaseScience( void )
  2435. {
  2436. if(m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden())
  2437. return;
  2438. if( m_contextParent[ CP_PURCHASE_SCIENCE ] )
  2439. {
  2440. m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  2441. }
  2442. // if (!TheGlobalData->m_animateWindows)
  2443. // {
  2444. // if( m_contextParent[ CP_PURCHASE_SCIENCE ] )
  2445. // {
  2446. // m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE );
  2447. // }
  2448. // }
  2449. // else
  2450. // {
  2451. // //if (m_generalsScreenAnimate->isFinished())
  2452. // if(TheTransitionHandler->isFinished())
  2453. // TheTransitionHandler->reverse("GenExpFade");
  2454. // //m_generalsScreenAnimate->reverseAnimateWindow();
  2455. // }
  2456. }
  2457. void ControlBar::togglePurchaseScience( void )
  2458. {
  2459. if(m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden())
  2460. showPurchaseScience();
  2461. else
  2462. hidePurchaseScience();
  2463. }
  2464. void ControlBar::toggleControlBarStage( void )
  2465. {
  2466. if(m_currentControlBarStage == CONTROL_BAR_STAGE_DEFAULT )
  2467. switchControlBarStage(CONTROL_BAR_STAGE_LOW);
  2468. else
  2469. switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
  2470. }
  2471. // Functions for repositioning/resizing the control bar
  2472. void ControlBar::switchControlBarStage( ControlBarStages stage )
  2473. {
  2474. if(stage < CONTROL_BAR_STAGE_DEFAULT || stage >= MAX_CONTROL_BAR_STAGES)
  2475. return;
  2476. if (TheRecorder && TheRecorder->getMode() == RECORDERMODETYPE_PLAYBACK)
  2477. return;
  2478. switch (stage) {
  2479. case CONTROL_BAR_STAGE_DEFAULT:
  2480. setDefaultControlBarConfig();
  2481. break;
  2482. // case CONTROL_BAR_STAGE_SQUISHED:
  2483. // setSquishedControlBarConfig();
  2484. // break;
  2485. case CONTROL_BAR_STAGE_LOW:
  2486. setLowControlBarConfig();
  2487. break;
  2488. case CONTROL_BAR_STAGE_HIDDEN:
  2489. setHiddenControlBar();
  2490. break;
  2491. default:
  2492. DEBUG_ASSERTCRASH(FALSE,("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage));
  2493. }
  2494. }
  2495. void ControlBar::setDefaultControlBarConfig( void )
  2496. {
  2497. // if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED)
  2498. // {
  2499. // m_controlBarResizer->sizeWindowsDefault();
  2500. // m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), FALSE);
  2501. // }
  2502. m_currentControlBarStage = CONTROL_BAR_STAGE_DEFAULT;
  2503. TheTacticalView->setHeight((Int)(TheDisplay->getHeight() * 0.80f));
  2504. m_contextParent[ CP_MASTER ]->winSetPosition(m_defaultControlBarPosition.x, m_defaultControlBarPosition.y);
  2505. m_contextParent[ CP_MASTER ]->winHide(FALSE);
  2506. repopulateBuildTooltipLayout();
  2507. setUpDownImages();
  2508. }
  2509. void ControlBar::setSquishedControlBarConfig( void )
  2510. {
  2511. if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED)
  2512. return;
  2513. m_currentControlBarStage = CONTROL_BAR_STAGE_SQUISHED;
  2514. m_contextParent[ CP_MASTER ]->winSetPosition(m_defaultControlBarPosition.x, m_defaultControlBarPosition.y);
  2515. // m_controlBarResizer->sizeWindowsAlt();
  2516. repopulateBuildTooltipLayout();
  2517. TheTacticalView->setHeight((Int)(TheDisplay->getHeight()));
  2518. m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), TRUE);
  2519. }
  2520. void ControlBar::setLowControlBarConfig( void )
  2521. {
  2522. // if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED)
  2523. // {
  2524. // m_controlBarResizer->sizeWindowsDefault();
  2525. // m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), FALSE);
  2526. // }
  2527. m_currentControlBarStage = CONTROL_BAR_STAGE_LOW;
  2528. ICoord2D pos;
  2529. pos.x = m_defaultControlBarPosition.x;
  2530. pos.y = TheDisplay->getHeight() - .1 * TheDisplay->getHeight();
  2531. TheTacticalView->setHeight((Int)(TheDisplay->getHeight()));
  2532. m_contextParent[ CP_MASTER ]->winSetPosition(pos.x, pos.y);
  2533. m_contextParent[ CP_MASTER ]->winHide(FALSE);
  2534. setUpDownImages();
  2535. }
  2536. void ControlBar::setHiddenControlBar( void )
  2537. {
  2538. m_currentControlBarStage = CONTROL_BAR_STAGE_HIDDEN;
  2539. m_contextParent[ CP_MASTER ]->winHide(TRUE);
  2540. }
  2541. // removed from multiplayer test
  2542. //void ControlBar::showCommandMarkers( void )
  2543. //{
  2544. // for(Int i =0; i < MAX_COMMANDS_PER_SET; ++i)
  2545. // {
  2546. // if(m_commandWindows[i]->winIsHidden())
  2547. // m_commandMarkers[i]->winHide(FALSE);
  2548. // else
  2549. // m_commandMarkers[i]->winHide(TRUE);
  2550. // }
  2551. //}
  2552. //
  2553. void ControlBar::updateCommandMarkerImage( const Image *image )
  2554. {
  2555. // removed from multiplayer branch
  2556. // // we don't mind if the image is null, that way we can not draw anything
  2557. // for(Int i =0; i < MAX_COMMANDS_PER_SET; ++i)
  2558. // {
  2559. // m_commandMarkers[i]->winSetEnabledImage(0, image);
  2560. // }
  2561. }
  2562. void ControlBar::updateSlotExitImage( const Image *image )
  2563. {
  2564. //Hardcoding values here Not a good thing but there's no other way right now.
  2565. if(!image)
  2566. return;
  2567. //Kris:
  2568. //Other than this being a completely ridiculously retarded idea, I'm not inclined
  2569. //to recode this in a better way, yikes! Btw, I DID NOT CODE THIS! But this is
  2570. //what this does: The button images are overridden by a faction specific icon.
  2571. //The proper way to fix this would be to make a commandbutton option and loop
  2572. //through all buttons on init to replace the icon. We need a system like this
  2573. //for neutral buildings which can have a different empty inventory icon based
  2574. //on the faction player.
  2575. CommandButton *cmdButton = findNonConstCommandButton( "Command_StructureExit" );
  2576. if(cmdButton)
  2577. cmdButton->setButtonImage(image);
  2578. cmdButton = findNonConstCommandButton( "Command_TransportExit" );
  2579. if(cmdButton)
  2580. cmdButton->setButtonImage(image);
  2581. cmdButton = findNonConstCommandButton( "Command_BunkerExit" );
  2582. if(cmdButton)
  2583. cmdButton->setButtonImage(image);
  2584. cmdButton = findNonConstCommandButton( "Command_FireBaseExit" );
  2585. if(cmdButton)
  2586. cmdButton->setButtonImage(image);
  2587. }
  2588. void ControlBar::updateUpDownImages( const Image *toggleButtonUpIn, const Image *toggleButtonUpOn, const Image *toggleButtonUpPushed,
  2589. const Image *toggleButtonDownIn, const Image *toggleButtonDownOn, const Image *toggleButtonDownPushed,
  2590. const Image *generalButtonEnable, const Image *generalButtonHighlight )
  2591. {
  2592. m_toggleButtonUpIn = toggleButtonUpIn;
  2593. m_toggleButtonUpOn = toggleButtonUpOn;
  2594. m_toggleButtonUpPushed = toggleButtonUpPushed;
  2595. m_toggleButtonDownIn = toggleButtonDownIn;
  2596. m_toggleButtonDownOn = toggleButtonDownOn;
  2597. m_toggleButtonDownPushed = toggleButtonDownPushed;
  2598. m_generalButtonEnable = generalButtonEnable;
  2599. m_generalButtonHighlight = generalButtonHighlight;
  2600. setUpDownImages();
  2601. }
  2602. void ControlBar::setUpDownImages( void )
  2603. {
  2604. GameWindow *win= TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonLarge" ) );
  2605. if(!win)
  2606. return;
  2607. // we only care if it's in it's low state, else we put the default images up
  2608. if(m_currentControlBarStage == CONTROL_BAR_STAGE_LOW)
  2609. {
  2610. GadgetButtonSetEnabledImage(win, m_toggleButtonUpOn);
  2611. GadgetButtonSetHiliteImage(win, m_toggleButtonUpIn);
  2612. GadgetButtonSetHiliteSelectedImage(win, m_toggleButtonUpPushed);
  2613. return;
  2614. }
  2615. GadgetButtonSetEnabledImage(win, m_toggleButtonDownOn);
  2616. GadgetButtonSetHiliteImage(win, m_toggleButtonDownIn);
  2617. GadgetButtonSetHiliteSelectedImage(win, m_toggleButtonDownPushed);
  2618. }
  2619. void ControlBar::getForegroundMarkerPos(Int *x, Int *y)
  2620. {
  2621. *x = m_controlBarForegroundMarkerPos.x;
  2622. *y = m_controlBarForegroundMarkerPos.y;
  2623. }
  2624. void ControlBar::getBackgroundMarkerPos(Int *x, Int *y)
  2625. {
  2626. *x = m_controlBarBackgroundMarkerPos.x;
  2627. *y = m_controlBarBackgroundMarkerPos.y;
  2628. }
  2629. void ControlBar::drawTransitionHandler( void )
  2630. {
  2631. // if(m_transitionHandler)
  2632. // m_transitionHandler->draw();
  2633. }
  2634. enum{
  2635. RADAR_ATTACK_GLOW_FRAMES = 150,
  2636. RADAR_ATTACK_GLOW_NUM_TIMES = 15 ///< number of times we'll flash
  2637. };
  2638. void ControlBar::triggerRadarAttackGlow( void )
  2639. {
  2640. if(!m_radarAttackGlowWindow)
  2641. return;
  2642. m_radarAttackGlowOn = TRUE;
  2643. m_remainingRadarAttackGlowFrames = RADAR_ATTACK_GLOW_FRAMES;
  2644. if(BitTest(m_radarAttackGlowWindow->winGetStatus(),WIN_STATUS_ENABLED) == TRUE)
  2645. m_radarAttackGlowWindow->winEnable(FALSE);
  2646. }
  2647. void ControlBar::updateRadarAttackGlow ( void )
  2648. {
  2649. if(!m_radarAttackGlowOn || !m_radarAttackGlowWindow)
  2650. return;
  2651. m_remainingRadarAttackGlowFrames--;
  2652. if(m_remainingRadarAttackGlowFrames <= 0)
  2653. {
  2654. m_radarAttackGlowOn = FALSE;
  2655. m_radarAttackGlowWindow->winEnable(TRUE);
  2656. return;
  2657. }
  2658. if(m_remainingRadarAttackGlowFrames % RADAR_ATTACK_GLOW_NUM_TIMES == 0)
  2659. {
  2660. m_radarAttackGlowWindow->winEnable(!BitTest(m_radarAttackGlowWindow->winGetStatus(),WIN_STATUS_ENABLED));
  2661. }
  2662. }
  2663. void ControlBar::initSpecialPowershortcutBar( Player *player)
  2664. {
  2665. for( Int i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; ++i )
  2666. {
  2667. m_specialPowerShortcutButtonParents[i] = NULL;
  2668. m_specialPowerShortcutButtons[i] = NULL;
  2669. }
  2670. if(m_specialPowerLayout)
  2671. {
  2672. m_specialPowerLayout->destroyWindows();
  2673. m_specialPowerLayout->deleteInstance();
  2674. m_specialPowerLayout = NULL;
  2675. }
  2676. m_specialPowerShortcutParent = NULL;
  2677. m_currentlyUsedSpecialPowersButtons = 0;
  2678. const PlayerTemplate *pt = player->getPlayerTemplate();
  2679. if(!player || !pt|| !player->isLocalPlayer()
  2680. || pt->getSpecialPowerShortcutButtonCount() == 0
  2681. || pt->getSpecialPowerShortcutWinName().isEmpty()
  2682. || !player->isPlayerActive())
  2683. return;
  2684. m_currentlyUsedSpecialPowersButtons = pt->getSpecialPowerShortcutButtonCount();
  2685. AsciiString layoutName, tempName, windowName, parentName;
  2686. layoutName = pt->getSpecialPowerShortcutWinName();
  2687. m_specialPowerLayout = TheWindowManager->winCreateLayout(layoutName);
  2688. m_specialPowerLayout->hide(TRUE);
  2689. tempName = layoutName;
  2690. tempName.concat(":GenPowersShortcutBarParent");
  2691. NameKeyType id = TheNameKeyGenerator->nameToKey( tempName );
  2692. m_specialPowerShortcutParent = TheWindowManager->winGetWindowFromId( NULL, id );//m_scienceLayout->getFirstWindow();
  2693. tempName = layoutName;
  2694. tempName.concat(":ButtonCommand%d");
  2695. parentName = layoutName;
  2696. parentName.concat(":ButtonParent%d");
  2697. m_currentlyUsedSpecialPowersButtons = MIN(pt->getSpecialPowerShortcutButtonCount(), MAX_SPECIAL_POWER_SHORTCUTS);
  2698. for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ )
  2699. {
  2700. windowName.format( tempName, i+1 );
  2701. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  2702. m_specialPowerShortcutButtons[ i ] =
  2703. TheWindowManager->winGetWindowFromId( m_specialPowerShortcutParent, id );
  2704. m_specialPowerShortcutButtons[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
  2705. // Oh god... this is a total hack for shortcut buttons to handle rendering text top left corner...
  2706. m_specialPowerShortcutButtons[ i ]->winSetStatus( WIN_STATUS_SHORTCUT_BUTTON );
  2707. windowName.format( parentName, i+1 );
  2708. id = TheNameKeyGenerator->nameToKey( windowName.str() );
  2709. m_specialPowerShortcutButtonParents[ i ] =
  2710. TheWindowManager->winGetWindowFromId( m_specialPowerShortcutParent, id );
  2711. } // end for i
  2712. }
  2713. void ControlBar::populateSpecialPowerShortcut( Player *player)
  2714. {
  2715. const CommandSet *commandSet;
  2716. Int i;
  2717. if(!player || !player->getPlayerTemplate()
  2718. || !player->isLocalPlayer() || m_currentlyUsedSpecialPowersButtons == 0
  2719. || m_specialPowerShortcutButtons == NULL || m_specialPowerShortcutButtonParents == NULL)
  2720. return;
  2721. for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; ++i )
  2722. {
  2723. if (m_specialPowerShortcutButtons[i])
  2724. m_specialPowerShortcutButtons[i]->winHide(TRUE);
  2725. if (m_specialPowerShortcutButtonParents[i])
  2726. m_specialPowerShortcutButtonParents[i]->winHide(TRUE);
  2727. }
  2728. // get command set
  2729. if(player->getPlayerTemplate()->getSpecialPowerShortcutCommandSet().isEmpty() )
  2730. return;
  2731. commandSet = TheControlBar->findCommandSet(player->getPlayerTemplate()->getSpecialPowerShortcutCommandSet()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING
  2732. if(!commandSet)
  2733. return;
  2734. // populate the button with commands defined
  2735. Int currentButton = 0;
  2736. const CommandButton *commandButton;
  2737. for( i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ )
  2738. {
  2739. // get command button
  2740. commandButton = commandSet->getCommandButton(i);
  2741. // if button is not present, just hide the window
  2742. if( commandButton == NULL )
  2743. {
  2744. continue;
  2745. // hide window on interface
  2746. //m_specialPowerShortcutButtons[ i ]->winHide( TRUE );
  2747. } // end if
  2748. else
  2749. {
  2750. if( BitTest( commandButton->getOptions(), NEED_UPGRADE ) )
  2751. {
  2752. const UpgradeTemplate *upgrade = commandButton->getUpgradeTemplate();
  2753. if( upgrade && !ThePlayerList->getLocalPlayer()->hasUpgradeComplete( upgrade->getUpgradeMask() ) )
  2754. {
  2755. //Kris: 8/13/03 - Don't show shortcut buttons that require upgrades we don't have. As far as
  2756. //I know, only the radar van scan has this. The MOAB is handled differently (sciences).
  2757. continue;
  2758. }
  2759. }
  2760. //
  2761. // commands that require sciences we don't have are hidden so they never show up
  2762. // cause we can never pick "another" general technology throughout the game
  2763. //
  2764. if( BitTest( commandButton->getOptions(), NEED_SPECIAL_POWER_SCIENCE ) )
  2765. {
  2766. const SpecialPowerTemplate *power = commandButton->getSpecialPowerTemplate();
  2767. if( !power )
  2768. {
  2769. //Should have the power.. button is probably missing the SpecialPower = xxx entry.
  2770. DEBUG_CRASH( ("CommandButton %s needs a SpecialPower entry, but it's either incorrect or missing.", commandButton->getName().str()) );
  2771. continue;
  2772. }
  2773. //We just need to find something that has the power.
  2774. Object *obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( commandButton->getSpecialPowerTemplate()->getSpecialPowerType() );
  2775. if( !obj )
  2776. {
  2777. continue;
  2778. }
  2779. if( power->getRequiredScience() != SCIENCE_INVALID )
  2780. {
  2781. if( player->hasScience( power->getRequiredScience() ) == FALSE )
  2782. {
  2783. //Hide the power
  2784. //m_specialPowerShortcutButtons[ i ]->winHide( TRUE );
  2785. continue;
  2786. }
  2787. else
  2788. {
  2789. //The player does have the special power! Now determine if the images require
  2790. //enhancement based on upgraded versions. This is determined by the command
  2791. //button specifying a vector of sciences in the command button.
  2792. Int bestIndex = -1;
  2793. ScienceType science;
  2794. for( Int scienceIndex = 0; scienceIndex < commandButton->getScienceVec().size(); ++scienceIndex )
  2795. {
  2796. science = commandButton->getScienceVec()[ scienceIndex ];
  2797. //Keep going until we reach the end or don't have the required science!
  2798. if( player->hasScience( science ) )
  2799. {
  2800. bestIndex = scienceIndex;
  2801. }
  2802. else
  2803. {
  2804. break;
  2805. }
  2806. }
  2807. if( bestIndex != -1 )
  2808. {
  2809. //Now get the best sciencetype.
  2810. science = commandButton->getScienceVec()[ bestIndex ];
  2811. const CommandSet *commandSet1;
  2812. const CommandSet *commandSet3;
  2813. const CommandSet *commandSet8;
  2814. Int i;
  2815. // get command set
  2816. if( !player || !player->getPlayerTemplate()
  2817. || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1().isEmpty()
  2818. || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3().isEmpty()
  2819. || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8().isEmpty() )
  2820. {
  2821. continue;
  2822. }
  2823. commandSet1 = TheControlBar->findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1() );
  2824. commandSet3 = TheControlBar->findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3() );
  2825. commandSet8 = TheControlBar->findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8() );
  2826. if( !commandSet1 || !commandSet3 || !commandSet8 )
  2827. {
  2828. continue;
  2829. }
  2830. Bool found = FALSE;
  2831. for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_1; i++ )
  2832. {
  2833. const CommandButton *command = commandSet1->getCommandButton( i );
  2834. if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE )
  2835. {
  2836. //All purchase sciences specify a single science.
  2837. if( command->getScienceVec().empty() )
  2838. {
  2839. DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) );
  2840. }
  2841. else if( command->getScienceVec()[0] == science )
  2842. {
  2843. commandButton->copyImagesFrom( command, TRUE );
  2844. commandButton->copyButtonTextFrom( command, TRUE, TRUE );
  2845. found = TRUE;
  2846. break;
  2847. }
  2848. }
  2849. }
  2850. for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_3; i++ )
  2851. {
  2852. const CommandButton *command = commandSet3->getCommandButton( i );
  2853. if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE )
  2854. {
  2855. //All purchase sciences specify a single science.
  2856. if( command->getScienceVec().empty() )
  2857. {
  2858. DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) );
  2859. }
  2860. else if( command->getScienceVec()[0] == science )
  2861. {
  2862. commandButton->copyImagesFrom( command, TRUE );
  2863. commandButton->copyButtonTextFrom( command, TRUE, TRUE );
  2864. found = TRUE;
  2865. break;
  2866. }
  2867. }
  2868. }
  2869. for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_8; i++ )
  2870. {
  2871. const CommandButton *command = commandSet8->getCommandButton( i );
  2872. if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE )
  2873. {
  2874. //All purchase sciences specify a single science.
  2875. if( command->getScienceVec().empty() )
  2876. {
  2877. DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) );
  2878. }
  2879. else if( command->getScienceVec()[0] == science )
  2880. {
  2881. commandButton->copyImagesFrom( command, TRUE );
  2882. commandButton->copyButtonTextFrom( command, TRUE, TRUE );
  2883. found = TRUE;
  2884. break;
  2885. }
  2886. }
  2887. }
  2888. }
  2889. }
  2890. }
  2891. } // end if
  2892. else if( commandButton->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE )
  2893. {
  2894. //Make sure we actually have an object of type that we want to be able to select.
  2895. Object *obj = ThePlayerList->getLocalPlayer()->findAnyExistingObjectWithThingTemplate( commandButton->getThingTemplate() );
  2896. if( !obj )
  2897. {
  2898. continue;
  2899. }
  2900. }
  2901. // make sure the window is not hidden
  2902. m_specialPowerShortcutButtons[ currentButton ]->winHide( FALSE );
  2903. m_specialPowerShortcutButtonParents[ currentButton ]->winHide( FALSE );
  2904. // enable by default
  2905. m_specialPowerShortcutButtons[ currentButton ]->winEnable( TRUE );
  2906. m_specialPowerShortcutButtonParents[ currentButton ]->winEnable( TRUE );
  2907. // populate the visible button with data from the command button
  2908. setControlCommand( m_specialPowerShortcutButtons[ currentButton ], commandButton );
  2909. GadgetButtonSetAltSound(m_specialPowerShortcutButtons[ currentButton ], "GUIGenShortcutClick");
  2910. currentButton++;
  2911. } // end else
  2912. } // end for i
  2913. if(m_contextParent[ CP_MASTER ] && !m_contextParent[ CP_MASTER ]->winIsHidden() && m_specialPowerShortcutParent->winIsHidden())
  2914. {
  2915. showSpecialPowerShortcut();
  2916. animateSpecialPowerShortcut(TRUE);
  2917. }
  2918. updateSpecialPowerShortcut();
  2919. }
  2920. //-------------------------------------------------------------------------------------------------
  2921. Bool ControlBar::hasAnyShortcutSelection() const
  2922. {
  2923. for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ )
  2924. {
  2925. GameWindow *win;
  2926. const CommandButton *command;
  2927. win = m_specialPowerShortcutButtons[ i ];
  2928. if( win->winIsHidden() == TRUE )
  2929. continue;
  2930. // get the command from the control
  2931. command = (const CommandButton *)GadgetButtonGetData(win);
  2932. if( !command )
  2933. continue;
  2934. if( command->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE )
  2935. {
  2936. //We found one, so we'll always show shortcuts!
  2937. return TRUE;
  2938. }
  2939. }
  2940. return FALSE;
  2941. }
  2942. //-------------------------------------------------------------------------------------------------
  2943. void ControlBar::updateSpecialPowerShortcut( void )
  2944. {
  2945. if(!m_specialPowerShortcutParent || !m_specialPowerShortcutButtons
  2946. || !ThePlayerList || !ThePlayerList->getLocalPlayer())
  2947. return;
  2948. Bool hasShortcutSelectionButtons = hasAnyShortcutSelection();
  2949. Bool hasAnyShortcutSpecialPower = ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower();
  2950. Bool hasValidShortcutButton = hasShortcutSelectionButtons || hasAnyShortcutSpecialPower;
  2951. if( hasValidShortcutButton
  2952. && m_specialPowerShortcutParent->winIsHidden()
  2953. && m_contextParent[ CP_MASTER ]
  2954. && !m_contextParent[ CP_MASTER ]->winIsHidden() )
  2955. {
  2956. showSpecialPowerShortcut();
  2957. animateSpecialPowerShortcut(TRUE);
  2958. }
  2959. else if( !hasValidShortcutButton
  2960. && !m_specialPowerShortcutParent->winIsHidden()
  2961. && m_animateWindowManagerForGenShortcuts->isFinished() )
  2962. {
  2963. animateSpecialPowerShortcut(FALSE);
  2964. }
  2965. if(m_specialPowerShortcutParent->winIsHidden())
  2966. return;
  2967. if(!ThePlayerList->getLocalPlayer()->isPlayerActive())
  2968. {
  2969. hideSpecialPowerShortcut();
  2970. return;
  2971. }
  2972. if(m_contextParent[ CP_MASTER ] && !m_contextParent[ CP_MASTER ]->winIsHidden() && m_specialPowerShortcutParent->winIsHidden())
  2973. showSpecialPowerShortcut();
  2974. for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ )
  2975. {
  2976. GameWindow *win;
  2977. const CommandButton *command;
  2978. // get the window
  2979. win = m_specialPowerShortcutButtons[ i ];
  2980. if( win->winIsHidden() == TRUE )
  2981. continue;
  2982. // get the command from the control
  2983. command = (const CommandButton *)GadgetButtonGetData(win);
  2984. //command = (const CommandButton *)win->winGetUserData();
  2985. if( command == NULL )
  2986. continue;
  2987. win->winClearStatus( WIN_STATUS_NOT_READY );
  2988. win->winClearStatus( WIN_STATUS_ALWAYS_COLOR );
  2989. // is the command available
  2990. CommandAvailability availability = COMMAND_RESTRICTED;
  2991. const SpecialPowerTemplate *spTemplate = command->getSpecialPowerTemplate();
  2992. Object *obj = NULL;
  2993. if( spTemplate )
  2994. {
  2995. obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( command->getSpecialPowerTemplate()->getSpecialPowerType() );
  2996. availability = getCommandAvailability( command, obj, win );
  2997. }
  2998. else if( command->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE )
  2999. {
  3000. availability = COMMAND_HIDDEN;
  3001. Object *obj = ThePlayerList->getLocalPlayer()->findAnyExistingObjectWithThingTemplate( command->getThingTemplate() );
  3002. if( obj )
  3003. {
  3004. //Make command available if it isn't a special power template shortcut power.
  3005. availability = COMMAND_AVAILABLE;
  3006. UnsignedInt mostReadyPercentage;
  3007. obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerForThing( command->getThingTemplate(), mostReadyPercentage );
  3008. if( obj )
  3009. {
  3010. //Ugh... hacky.
  3011. //Look for a command button for a special power and if so, then get the command availability for it.
  3012. const CommandSet *commandSet = TheControlBar->findCommandSet( obj->getCommandSetString() );
  3013. if( commandSet )
  3014. {
  3015. for( Int commandIndex = 0; commandIndex < MAX_COMMANDS_PER_SET; commandIndex++ )
  3016. {
  3017. const CommandButton *evalButton = commandSet->getCommandButton( commandIndex );
  3018. GameWindow *evalButtonWin = m_commandWindows[ commandIndex ];
  3019. if( evalButton && evalButton->getCommandType() == GUI_COMMAND_SPECIAL_POWER )
  3020. {
  3021. //We want to evaluate the special powerbutton... but apply the clock overlay to our button!
  3022. availability = getCommandAvailability( evalButton, obj, evalButtonWin, win );
  3023. break;
  3024. }
  3025. }
  3026. }
  3027. }
  3028. }
  3029. }
  3030. // enable/disable the window control
  3031. switch( availability )
  3032. {
  3033. case COMMAND_HIDDEN:
  3034. win->winHide( TRUE );
  3035. break;
  3036. case COMMAND_RESTRICTED:
  3037. win->winEnable( FALSE );
  3038. break;
  3039. case COMMAND_NOT_READY:
  3040. win->winEnable( FALSE );
  3041. win->winSetStatus( WIN_STATUS_NOT_READY );
  3042. break;
  3043. case COMMAND_CANT_AFFORD:
  3044. win->winEnable( FALSE );
  3045. win->winSetStatus( WIN_STATUS_ALWAYS_COLOR );
  3046. break;
  3047. default:
  3048. win->winEnable( TRUE );
  3049. break;
  3050. }
  3051. }
  3052. }
  3053. //-------------------------------------------------------------------------------------------------
  3054. void ControlBar::drawSpecialPowerShortcutMultiplierText()
  3055. {
  3056. for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ )
  3057. {
  3058. GameWindow *win;
  3059. const CommandButton *command;
  3060. // get the window
  3061. win = m_specialPowerShortcutButtons[ i ];
  3062. if( win->winIsHidden() == TRUE )
  3063. continue;
  3064. // get the command from the control
  3065. command = (const CommandButton *)GadgetButtonGetData(win);
  3066. //command = (const CommandButton *)win->winGetUserData();
  3067. if( command == NULL )
  3068. continue;
  3069. //draw superweapon ready multipliers
  3070. for( int i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ )
  3071. {
  3072. if( !m_shortcutDisplayStrings[ i ] )
  3073. {
  3074. //m_shortcutDisplayStrings[ i ] = TheDisplayStringManager->newDisplayString();
  3075. //m_shortcutDisplayStrings[ i ]->setFont( TheFontLibrary->getFont( "Arial", 16, false ) );
  3076. }
  3077. const SpecialPowerTemplate *spTemplate = command->getSpecialPowerTemplate();
  3078. Int numReady = 0;
  3079. if( spTemplate )
  3080. {
  3081. numReady = ThePlayerList->getLocalPlayer()->countReadyShortcutSpecialPowersOfType( spTemplate->getSpecialPowerType() );
  3082. }
  3083. if( numReady > 1 ) // Lorenzen changed... Displaying a "1" is superfluous
  3084. {
  3085. UnicodeString unibuffer;
  3086. unibuffer.format( L"%d", numReady );
  3087. GadgetButtonSetText( win, unibuffer );
  3088. //m_shortcutDisplayStrings[ i ]->setText( unibuffer );
  3089. //TheControlBar->m_shortcutDisplayStrings[ i ]->draw( 600, i * 40 + 40, GameMakeColor(255,255,255,255), GameMakeColor(0,0,0,0), 0, 0 );
  3090. }
  3091. else
  3092. {
  3093. UnicodeString unibuffer;
  3094. GadgetButtonSetText( win, unibuffer );
  3095. //TheDisplayStringManager->freeDisplayString( m_shortcutDisplayStrings[ i ] );
  3096. //m_shortcutDisplayStrings[ i ] = NULL;
  3097. }
  3098. }
  3099. }
  3100. }
  3101. void ControlBar::animateSpecialPowerShortcut( Bool isOn )
  3102. {
  3103. if(!m_specialPowerShortcutParent || !m_animateWindowManagerForGenShortcuts || !m_currentlyUsedSpecialPowersButtons)
  3104. return;
  3105. Bool dontAnimate = TRUE;
  3106. for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; ++i )
  3107. {
  3108. if (m_specialPowerShortcutButtons[i]->winGetUserData())
  3109. {
  3110. dontAnimate = FALSE;
  3111. break;
  3112. }
  3113. }
  3114. if(dontAnimate)
  3115. return;
  3116. if(isOn)
  3117. {
  3118. m_animateWindowManagerForGenShortcuts->reset();
  3119. m_animateWindowManagerForGenShortcuts->registerGameWindow(m_specialPowerShortcutParent,WIN_ANIMATION_SLIDE_RIGHT,TRUE,500,0);
  3120. }
  3121. else
  3122. {
  3123. m_animateWindowManagerForGenShortcuts->reverseAnimateWindow();
  3124. }
  3125. }
  3126. void ControlBar::showSpecialPowerShortcut( void )
  3127. {
  3128. if(TheScriptEngine->isGameEnding() || !m_specialPowerShortcutParent
  3129. ||!m_specialPowerShortcutButtons || !ThePlayerList || !ThePlayerList->getLocalPlayer())
  3130. return;
  3131. Bool dontAnimate = TRUE;
  3132. for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; ++i )
  3133. {
  3134. if (m_specialPowerShortcutButtons[i]->winGetUserData())
  3135. {
  3136. dontAnimate = FALSE;
  3137. break;
  3138. }
  3139. }
  3140. if( dontAnimate || (!ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower() && !hasAnyShortcutSelection()) )
  3141. return;
  3142. m_specialPowerShortcutParent->winHide(FALSE);
  3143. populateSpecialPowerShortcut(ThePlayerList->getLocalPlayer());
  3144. }
  3145. void ControlBar::hideSpecialPowerShortcut( void )
  3146. {
  3147. if(!m_specialPowerShortcutParent)
  3148. return;
  3149. m_specialPowerShortcutParent->winHide(TRUE);
  3150. }