ControlBarStructureInventory.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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: ControlBarStructureInventory.cpp /////////////////////////////////////////////////////////
  24. // Author: Colin Day, March 2002
  25. // Desc: Methods specific to the control bar garrison display
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/NameKeyGenerator.h"
  30. #include "Common/ThingTemplate.h"
  31. #include "Common/Player.h"
  32. #include "Common/PlayerList.h"
  33. #include "GameLogic/Object.h"
  34. #include "GameLogic/Module/OpenContain.h"
  35. #include "GameClient/InGameUI.h"
  36. #include "GameClient/Drawable.h"
  37. #include "GameClient/ControlBar.h"
  38. #include "GameClient/GameWindow.h"
  39. #include "GameClient/GameWindowManager.h"
  40. #include "GameClient/GadgetPushButton.h"
  41. #include "GameClient/Hotkey.h"
  42. #ifdef _INTERNAL
  43. // for occasional debugging...
  44. //#pragma optimize("", off)
  45. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  46. #endif
  47. #define STOP_ID 10
  48. #define EVACUATE_ID 11
  49. //-------------------------------------------------------------------------------------------------
  50. //-------------------------------------------------------------------------------------------------
  51. struct PopulateButtonInfo
  52. {
  53. Object *source;
  54. Int buttonIndex;
  55. ControlBar* self;
  56. GameWindow** inventoryButtons;
  57. };
  58. //-------------------------------------------------------------------------------------------------
  59. //-------------------------------------------------------------------------------------------------
  60. void ControlBar::populateButtonProc( Object *obj, void *userData )
  61. {
  62. PopulateButtonInfo* info = (PopulateButtonInfo*)userData;
  63. // sanity
  64. DEBUG_ASSERTCRASH( info->buttonIndex < MAX_STRUCTURE_INVENTORY_BUTTONS,
  65. ("Too many objects inside '%s' for the inventory buttons to hold",
  66. info->source->getTemplate()->getName().str()) );
  67. // put object in inventory data
  68. info->self->m_containData[ info->buttonIndex ].control = info->inventoryButtons[ info->buttonIndex ];
  69. info->self->m_containData[ info->buttonIndex ].objectID = obj->getID();
  70. // set the UI button that will allow us to press it and cause the object to exit the container
  71. const Image *image;
  72. image = obj->getTemplate()->getButtonImage();
  73. GadgetButtonSetEnabledImage( info->inventoryButtons[ info->buttonIndex ], image );
  74. //Show the auto-contained object's veterancy symbol!
  75. image = calculateVeterancyOverlayForObject( obj );
  76. GadgetButtonDrawOverlayImage( info->inventoryButtons[ info->buttonIndex ], image );
  77. // Enable the button
  78. info->inventoryButtons[ info->buttonIndex ]->winEnable( TRUE );
  79. // move to the next button index
  80. info->buttonIndex++;
  81. }
  82. //-------------------------------------------------------------------------------------------------
  83. //-------------------------------------------------------------------------------------------------
  84. void ControlBar::populateStructureInventory( Object *building )
  85. {
  86. Int i;
  87. // reset the inventory data
  88. resetContainData();
  89. // reset hotkeys -- seeing it only is reset in switching contexts. This is a special case
  90. // because we are building the hotkeys on the fly sort of... and it changes as guys enter
  91. // and leave. Taking this call out will cause multiple hotkeys to be added.
  92. if(TheHotKeyManager)
  93. TheHotKeyManager->reset();
  94. // Start by hiding all the buttons. Otherwise buttons we don't use will have the buttons
  95. // the last thing selected left behind.
  96. for( Int commandIndex = 0; commandIndex < MAX_COMMANDS_PER_SET; commandIndex++ )
  97. {
  98. if( m_commandWindows[commandIndex] )
  99. {
  100. m_commandWindows[commandIndex]->winHide(TRUE);
  101. }
  102. }
  103. // get the contain module of the object
  104. ContainModuleInterface *contain = building->getContain();
  105. DEBUG_ASSERTCRASH( contain, ("Object in structure inventory does not contain a Contain Module\n") );
  106. if (!contain)
  107. return;
  108. /// @todo srj -- remove hard-coding here, please
  109. const CommandButton *evacuateCommand = findCommandButton( "Command_Evacuate" );
  110. setControlCommand( m_commandWindows[ EVACUATE_ID ], evacuateCommand );
  111. m_commandWindows[ EVACUATE_ID ]->winEnable( FALSE );
  112. /// @todo srj -- remove hard-coding here, please
  113. const CommandButton *stopCommand = findCommandButton( "Command_Stop" );
  114. setControlCommand( m_commandWindows[ STOP_ID ], stopCommand );
  115. m_commandWindows[ STOP_ID ]->winEnable( FALSE );
  116. // get the inventory exit command to assign into the button
  117. /// @todo srj -- remove hard-coding here, please
  118. const CommandButton *exitCommand = findCommandButton( "Command_StructureExit" );
  119. // get window handles for each of the inventory buttons
  120. AsciiString windowName;
  121. for( i = 0; i < MAX_STRUCTURE_INVENTORY_BUTTONS; i++ )
  122. {
  123. // show the window
  124. m_commandWindows[ i ]->winHide( FALSE );
  125. //
  126. // disable the button for now, it will be enabled if there is something there
  127. // for its contents
  128. //
  129. m_commandWindows[ i ]->winEnable( FALSE );
  130. m_commandWindows[ i ]->winSetStatus( WIN_STATUS_ALWAYS_COLOR );
  131. m_commandWindows[ i ]->winClearStatus( WIN_STATUS_NOT_READY );
  132. // set an inventory command into the game window UI element
  133. setControlCommand( m_commandWindows[ i ], exitCommand );
  134. // Clear any veterancy icon incase the unit leaves!
  135. GadgetButtonDrawOverlayImage( m_commandWindows[ i ], NULL );
  136. //
  137. // if the structure can hold a lesser amount inside it than what the GUI displays
  138. // we will completely hide the buttons that can't contain anything
  139. //
  140. if( i + 1 > contain->getContainMax() )
  141. m_commandWindows[ i ]->winHide( TRUE );
  142. } // end for i
  143. // show the window
  144. m_commandWindows[ EVACUATE_ID ]->winHide( FALSE );
  145. m_commandWindows[ STOP_ID ]->winHide( FALSE );
  146. // if there is at least one item in there enable the evacuate and stop buttons
  147. if( contain->getContainCount() != 0 )
  148. {
  149. m_commandWindows[ EVACUATE_ID ]->winEnable( TRUE );
  150. m_commandWindows[ STOP_ID ]->winEnable( TRUE );
  151. }
  152. //
  153. // iterate each of the objects inside the container and put them in a button, note
  154. // we're iterating in reverse order here
  155. //
  156. PopulateButtonInfo info;
  157. info.source = building;
  158. info.buttonIndex = 0;
  159. info.self = this;
  160. info.inventoryButtons = m_commandWindows;
  161. contain->iterateContained(populateButtonProc, &info, FALSE );
  162. //
  163. // save how many items were contained by the object at this time so that we can update
  164. // it if they change in the future while selected
  165. //
  166. m_lastRecordedInventoryCount = contain->getContainCount();
  167. } // end populateStructureInventory
  168. //-------------------------------------------------------------------------------------------------
  169. //-------------------------------------------------------------------------------------------------
  170. void ControlBar::updateContextStructureInventory( void )
  171. {
  172. Object *source = m_currentSelectedDrawable->getObject();
  173. //
  174. // we're visible, so there is something selected. It is possible that we had a building
  175. // selected that can be garrisoned, and while it was selected the enemy occupied it.
  176. // in that case we want to unselect the building so that we can't see the contents
  177. //
  178. Player *localPlayer = ThePlayerList->getLocalPlayer();
  179. if( source->isLocallyControlled() == FALSE &&
  180. localPlayer->getRelationship( source->getTeam() ) != NEUTRAL )
  181. {
  182. Drawable *draw = source->getDrawable();
  183. if( draw )
  184. TheInGameUI->deselectDrawable( draw );
  185. return;
  186. } // end if
  187. //
  188. // if the object being displayed in the interface has a different count than we last knew
  189. // about we need to repopulate the buttons of the interface
  190. //
  191. ContainModuleInterface *contain = source->getContain();
  192. DEBUG_ASSERTCRASH( contain, ("No contain module defined for object in the iventory bar\n") );
  193. if (!contain)
  194. return;
  195. if( m_lastRecordedInventoryCount != contain->getContainCount() )
  196. populateStructureInventory( source );
  197. } // end updateContextStructureInventory