ControlBarStructureInventory.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. ** Command & Conquer Generals(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. // get the contain module of the object
  95. ContainModuleInterface *contain = building->getContain();
  96. DEBUG_ASSERTCRASH( contain, ("Object in structure inventory does not contain a Contain Module\n") );
  97. if (!contain)
  98. return;
  99. /// @todo srj -- remove hard-coding here, please
  100. const CommandButton *evacuateCommand = findCommandButton( "Command_Evacuate" );
  101. setControlCommand( m_commandWindows[ EVACUATE_ID ], evacuateCommand );
  102. m_commandWindows[ EVACUATE_ID ]->winEnable( FALSE );
  103. /// @todo srj -- remove hard-coding here, please
  104. const CommandButton *stopCommand = findCommandButton( "Command_Stop" );
  105. setControlCommand( m_commandWindows[ STOP_ID ], stopCommand );
  106. m_commandWindows[ STOP_ID ]->winEnable( FALSE );
  107. // get the inventory exit command to assign into the button
  108. /// @todo srj -- remove hard-coding here, please
  109. const CommandButton *exitCommand = findCommandButton( "Command_StructureExit" );
  110. // get window handles for each of the inventory buttons
  111. AsciiString windowName;
  112. for( i = 0; i < MAX_STRUCTURE_INVENTORY_BUTTONS; i++ )
  113. {
  114. // show the window
  115. m_commandWindows[ i ]->winHide( FALSE );
  116. //
  117. // disable the button for now, it will be enabled if there is something there
  118. // for its contents
  119. //
  120. m_commandWindows[ i ]->winEnable( FALSE );
  121. m_commandWindows[ i ]->winSetStatus( WIN_STATUS_ALWAYS_COLOR );
  122. m_commandWindows[ i ]->winClearStatus( WIN_STATUS_NOT_READY );
  123. // set an inventory command into the game window UI element
  124. setControlCommand( m_commandWindows[ i ], exitCommand );
  125. // Clear any veterancy icon incase the unit leaves!
  126. GadgetButtonDrawOverlayImage( m_commandWindows[ i ], NULL );
  127. //
  128. // if the structure can hold a lesser amount inside it than what the GUI displays
  129. // we will completely hide the buttons that can't contain anything
  130. //
  131. if( i + 1 > contain->getContainMax() )
  132. m_commandWindows[ i ]->winHide( TRUE );
  133. } // end for i
  134. // show the window
  135. m_commandWindows[ EVACUATE_ID ]->winHide( FALSE );
  136. m_commandWindows[ STOP_ID ]->winHide( FALSE );
  137. // if there is at least one item in there enable the evacuate and stop buttons
  138. if( contain->getContainCount() != 0 )
  139. {
  140. m_commandWindows[ EVACUATE_ID ]->winEnable( TRUE );
  141. m_commandWindows[ STOP_ID ]->winEnable( TRUE );
  142. }
  143. //
  144. // iterate each of the objects inside the container and put them in a button, note
  145. // we're iterating in reverse order here
  146. //
  147. PopulateButtonInfo info;
  148. info.source = building;
  149. info.buttonIndex = 0;
  150. info.self = this;
  151. info.inventoryButtons = m_commandWindows;
  152. contain->iterateContained(populateButtonProc, &info, FALSE );
  153. //
  154. // save how many items were contained by the object at this time so that we can update
  155. // it if they change in the future while selected
  156. //
  157. m_lastRecordedInventoryCount = contain->getContainCount();
  158. } // end populateStructureInventory
  159. //-------------------------------------------------------------------------------------------------
  160. //-------------------------------------------------------------------------------------------------
  161. void ControlBar::updateContextStructureInventory( void )
  162. {
  163. Object *source = m_currentSelectedDrawable->getObject();
  164. //
  165. // we're visible, so there is something selected. It is possible that we had a building
  166. // selected that can be garrisoned, and while it was selected the enemy occupied it.
  167. // in that case we want to unselect the building so that we can't see the contents
  168. //
  169. Player *localPlayer = ThePlayerList->getLocalPlayer();
  170. if( source->isLocallyControlled() == FALSE &&
  171. localPlayer->getRelationship( source->getTeam() ) != NEUTRAL )
  172. {
  173. Drawable *draw = source->getDrawable();
  174. if( draw )
  175. TheInGameUI->deselectDrawable( draw );
  176. return;
  177. } // end if
  178. //
  179. // if the object being displayed in the interface has a different count than we last knew
  180. // about we need to repopulate the buttons of the interface
  181. //
  182. ContainModuleInterface *contain = source->getContain();
  183. DEBUG_ASSERTCRASH( contain, ("No contain module defined for object in the iventory bar\n") );
  184. if (!contain)
  185. return;
  186. if( m_lastRecordedInventoryCount != contain->getContainCount() )
  187. populateStructureInventory( source );
  188. } // end updateContextStructureInventory