diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index 635563d957e..4a6528c1253 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -149,9 +149,9 @@ set(GAMEENGINE_SRC Include/GameClient/ClientRandomValue.h Include/GameClient/Color.h # Include/GameClient/CommandXlat.h -# Include/GameClient/ControlBar.h -# Include/GameClient/ControlBarResizer.h -# Include/GameClient/ControlBarScheme.h + Include/GameClient/ControlBar.h + Include/GameClient/ControlBarResizer.h + Include/GameClient/ControlBarScheme.h Include/GameClient/Credits.h Include/GameClient/DebugDisplay.h # Include/GameClient/Diplomacy.h @@ -711,18 +711,18 @@ set(GAMEENGINE_SRC Source/GameClient/GraphDraw.cpp # Source/GameClient/GUI/AnimateWindowManager.cpp Source/GameClient/GUI/ChallengeGenerals.cpp -# Source/GameClient/GUI/ControlBar/ControlBar.cpp -# Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp -# Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp -# Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp -# Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp -# Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp -# Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp -# Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp -# Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp -# Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp -# Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp -# Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp + Source/GameClient/GUI/ControlBar/ControlBar.cpp + Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp + Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp + Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp + Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp + Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp + Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp + Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp + Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp + Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp + Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp + Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp # Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp # Source/GameClient/GUI/EstablishConnectionsMenu/EstablishConnectionsMenu.cpp Source/GameClient/GUI/Gadget/GadgetCheckBox.cpp @@ -743,8 +743,8 @@ set(GAMEENGINE_SRC # Source/GameClient/GUI/GameWindowManagerScript.cpp Source/GameClient/GUI/GameWindowTransitions.cpp # Source/GameClient/GUI/GameWindowTransitionsStyles.cpp -# Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp -# Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp + Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp + Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp # Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp # Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp # Source/GameClient/GUI/GUICallbacks/GeneralsExpPoints.cpp diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/ControlBar.h b/Core/GameEngine/Include/GameClient/ControlBar.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/ControlBar.h rename to Core/GameEngine/Include/GameClient/ControlBar.h diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/ControlBarResizer.h b/Core/GameEngine/Include/GameClient/ControlBarResizer.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/ControlBarResizer.h rename to Core/GameEngine/Include/GameClient/ControlBarResizer.h diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/ControlBarScheme.h b/Core/GameEngine/Include/GameClient/ControlBarScheme.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/ControlBarScheme.h rename to Core/GameEngine/Include/GameClient/ControlBarScheme.h diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp similarity index 99% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp index 3109222ef64..815787536dd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp @@ -3561,10 +3561,16 @@ void ControlBar::updateSpecialPowerShortcut() || !ThePlayerList || !ThePlayerList->getLocalPlayer()) return; +#if RTS_GENERALS + // Base Generals just needs a Command Center to show the shortcut bar + Bool hasValidShortcutButton = (ThePlayerList->getLocalPlayer()->findNaturalCommandCenter() != nullptr); +#else + // Zero Hour looks for explicitly flagged shortcut powers or shortcut selection buttons Bool hasShortcutSelectionButtons = hasAnyShortcutSelection(); Bool hasAnyShortcutSpecialPower = ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower(); Bool hasValidShortcutButton = hasShortcutSelectionButtons || hasAnyShortcutSpecialPower; +#endif if( hasValidShortcutButton && m_specialPowerShortcutParent->winIsHidden() @@ -3776,8 +3782,13 @@ void ControlBar::showSpecialPowerShortcut() break; } } +#if RTS_GENERALS + if(dontAnimate || !ThePlayerList->getLocalPlayer()->findNaturalCommandCenter()) + return; +#else if( dontAnimate || (!ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower() && !hasAnyShortcutSelection()) ) return; +#endif m_specialPowerShortcutParent->winHide(FALSE); populateSpecialPowerShortcut(ThePlayerList->getLocalPlayer()); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp b/Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp rename to Core/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp b/Core/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp rename to Core/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp b/Core/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp rename to Core/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt index a7016b52e73..977c2736f94 100644 --- a/Core/GameEngineDevice/CMakeLists.txt +++ b/Core/GameEngineDevice/CMakeLists.txt @@ -130,7 +130,7 @@ set(GAMEENGINEDEVICE_SRC Source/W3DDevice/GameClient/GUI/Gadget/W3DTabControl.cpp Source/W3DDevice/GameClient/GUI/Gadget/W3DTextEntry.cpp Source/W3DDevice/GameClient/GUI/Gadget/W3DVerticalSlider.cpp -# Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp + Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp # Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp # Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMOTD.cpp # Source/W3DDevice/GameClient/GUI/W3DGameFont.cpp diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp similarity index 100% rename from GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp rename to Core/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt index f28e5c0552b..562f1bfe75a 100644 --- a/Generals/Code/GameEngine/CMakeLists.txt +++ b/Generals/Code/GameEngine/CMakeLists.txt @@ -136,9 +136,9 @@ set(GAMEENGINE_SRC # Include/GameClient/ClientRandomValue.h # Include/GameClient/Color.h Include/GameClient/CommandXlat.h - Include/GameClient/ControlBar.h - Include/GameClient/ControlBarResizer.h - Include/GameClient/ControlBarScheme.h +# Include/GameClient/ControlBar.h +# Include/GameClient/ControlBarResizer.h +# Include/GameClient/ControlBarScheme.h # Include/GameClient/Credits.h # Include/GameClient/DebugDisplay.h Include/GameClient/Diplomacy.h @@ -655,18 +655,18 @@ set(GAMEENGINE_SRC # Source/GameClient/GraphDraw.cpp Source/GameClient/GUI/AnimateWindowManager.cpp # Source/GameClient/GUI/ChallengeGenerals.cpp - Source/GameClient/GUI/ControlBar/ControlBar.cpp - Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp - Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp - Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp - Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp - Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp - Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp - Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp - Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp - Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp - Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp - Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp +# Source/GameClient/GUI/ControlBar/ControlBar.cpp +# Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp +# Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp +# Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp +# Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp +# Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp +# Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp +# Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp +# Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp +# Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp +# Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp +# Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp Source/GameClient/GUI/EstablishConnectionsMenu/EstablishConnectionsMenu.cpp # Source/GameClient/GUI/Gadget/GadgetCheckBox.cpp @@ -687,8 +687,8 @@ set(GAMEENGINE_SRC Source/GameClient/GUI/GameWindowManagerScript.cpp # Source/GameClient/GUI/GameWindowTransitions.cpp Source/GameClient/GUI/GameWindowTransitionsStyles.cpp - Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp - Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp +# Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp +# Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp Source/GameClient/GUI/GUICallbacks/GeneralsExpPoints.cpp diff --git a/Generals/Code/GameEngine/Include/GameClient/ControlBar.h b/Generals/Code/GameEngine/Include/GameClient/ControlBar.h deleted file mode 100644 index 88ae7d4abb0..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/ControlBar.h +++ /dev/null @@ -1,1050 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBar.h ///////////////////////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Context sensitive command interface -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#pragma once - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "Common/AudioEventRTS.h" -#include "Common/GameType.h" -#include "Common/Overridable.h" -#include "Common/Science.h" -#include "GameClient/Color.h" - -// FORWARD REFERENCES ///////////////////////////////////////////////////////////////////////////// -class Drawable; -class GameWindow; -class Image; -class Object; -class ThingTemplate; -class WeaponTemplate; -class SpecialPowerTemplate; -class WindowVideoManager; -class WindowVideoManager; -class AnimateWindowManager; -class GameWindow; -class WindowLayout; -class Player; -class PlayerTemplate; -class AudioEventRTS; -class ControlBarSchemeManager; -class UpgradeTemplate; -class ControlBarResizer; -class GameWindowTransitionsHandler; -class DisplayString; - -enum ProductionID CPP_11(: Int); - -enum CommandSourceType CPP_11(: Int); -enum ProductionType CPP_11(: Int); -enum GadgetGameMessage CPP_11(: Int); -enum ScienceType CPP_11(: Int); -enum TimeOfDay CPP_11(: Int); -enum RadiusCursorType CPP_11(: Int); - -//------------------------------------------------------------------------------------------------- -/** Command options */ -//------------------------------------------------------------------------------------------------- -enum CommandOption CPP_11(: Int) -{ - COMMAND_OPTION_NONE = 0x00000000, - NEED_TARGET_ENEMY_OBJECT = 0x00000001, // command now needs user to select enemy target - NEED_TARGET_NEUTRAL_OBJECT = 0x00000002, // command now needs user to select neutral target - NEED_TARGET_ALLY_OBJECT = 0x00000004, // command now needs user to select ally target -#ifdef ALLOW_SURRENDER - NEED_TARGET_PRISONER = 0x00000008, // needs user to now select prisoner object -#endif - ALLOW_SHRUBBERY_TARGET = 0x00000010, // allow neutral shrubbery as a target - NEED_TARGET_POS = 0x00000020, // command now needs user to select target position - NEED_UPGRADE = 0x00000040, // command requires upgrade to be enabled - NEED_SPECIAL_POWER_SCIENCE = 0x00000080, // command requires a science in the special power specified - OK_FOR_MULTI_SELECT = 0x00000100, // command is ok to show when multiple objects selected - CONTEXTMODE_COMMAND = 0x00000200, // a context sensitive command mode that requires code to determine whether cursor is valid or not. - CHECK_LIKE = 0x00000400, // dynamically change the UI element push button to be "check like" - ALLOW_MINE_TARGET = 0x00000800, // allow (land)mines as a target - ATTACK_OBJECTS_POSITION = 0x00001000, // for weapons that need an object target but attack the position indirectly (like burning trees) - OPTION_ONE = 0x00002000, // User data -- option 1 - OPTION_TWO = 0x00004000, // User data -- option 2 - OPTION_THREE = 0x00008000, // User data -- option 3 - NOT_QUEUEABLE = 0x00010000, // Option not build queueable meaning you can only build it when queue is empty! - SINGLE_USE_COMMAND = 0x00020000, // Once used, it can never be used again! - COMMAND_FIRED_BY_SCRIPT = 0x00040000, // Used only by code to tell special powers that they have been fired by a script. - SCRIPT_ONLY = 0x00080000, // Only a script can use this command (not by users) - IGNORES_UNDERPOWERED = 0x00100000, // this button isn't disabled if its object is merely underpowered - USES_MINE_CLEARING_WEAPONSET= 0x00200000, // uses the special mine-clearing weaponset, even if not current - CAN_USE_WAYPOINTS = 0x00400000, // button has option to use a waypoint path - MUST_BE_STOPPED = 0x00800000, // Unit must be stopped in order to be able to use button. -}; - -#ifdef DEFINE_COMMAND_OPTION_NAMES -static const char *const TheCommandOptionNames[] = -{ - "NEED_TARGET_ENEMY_OBJECT", - "NEED_TARGET_NEUTRAL_OBJECT", - "NEED_TARGET_ALLY_OBJECT", -#ifdef ALLOW_SURRENDER - "NEED_TARGET_PRISONER", -#else - "unused-reserved", -#endif - "ALLOW_SHRUBBERY_TARGET", - "NEED_TARGET_POS", - "NEED_UPGRADE", - "NEED_SPECIAL_POWER_SCIENCE", - "OK_FOR_MULTI_SELECT", - "CONTEXTMODE_COMMAND", - "CHECK_LIKE", - "ALLOW_MINE_TARGET", - "ATTACK_OBJECTS_POSITION", - "OPTION_ONE", - "OPTION_TWO", - "OPTION_THREE", - "NOT_QUEUEABLE", - "SINGLE_USE_COMMAND", - "---DO-NOT-USE---", //COMMAND_FIRED_BY_SCRIPT - "SCRIPT_ONLY", - "IGNORES_UNDERPOWERED", - "USES_MINE_CLEARING_WEAPONSET", - "CAN_USE_WAYPOINTS", - "MUST_BE_STOPPED", - - nullptr -}; -#endif // end DEFINE_COMMAND_OPTION_NAMES - -// convenient bit masks to group some command options together -const UnsignedInt COMMAND_OPTION_NEED_TARGET = - NEED_TARGET_ENEMY_OBJECT | - NEED_TARGET_NEUTRAL_OBJECT | - NEED_TARGET_ALLY_OBJECT | - NEED_TARGET_POS | - CONTEXTMODE_COMMAND; - -const UnsignedInt COMMAND_OPTION_NEED_OBJECT_TARGET = - NEED_TARGET_ENEMY_OBJECT | - NEED_TARGET_NEUTRAL_OBJECT | - NEED_TARGET_ALLY_OBJECT; - -//------------------------------------------------------------------------------------------------- -/** These are the list of commands that can be assigned to buttons that will appear - * in the context sensitive GUI for a selected unit. Not all commands are available - * on all units, in fact, many commands are for a particular single command. It will - * be up to the command GUI to translate the command assigned to a button into the - * appropriate game command and get it across the network to the game logic to perform the - * actual command logic - * - * IMPORTANT: Make sure the GUICommandType enum and the TheGuiCommandNames[] have the same - * entries in the same order */ -//------------------------------------------------------------------------------------------------- -enum GUICommandType CPP_11(: Int) -{ - GUI_COMMAND_NONE = 0, ///< invalid command - GUI_COMMAND_DOZER_CONSTRUCT, ///< dozer construct - GUI_COMMAND_DOZER_CONSTRUCT_CANCEL, ///< cancel a dozer construction process - GUI_COMMAND_UNIT_BUILD, ///< build a unit - GUI_COMMAND_CANCEL_UNIT_BUILD, ///< cancel a unit build - GUI_COMMAND_PLAYER_UPGRADE, ///< put an upgrade that applies to the player in the queue - GUI_COMMAND_OBJECT_UPGRADE, ///< put an object upgrade in the queue - GUI_COMMAND_CANCEL_UPGRADE, ///< cancel an upgrade - GUI_COMMAND_ATTACK_MOVE, ///< attack move command - GUI_COMMAND_GUARD, ///< guard command - GUI_COMMAND_GUARD_WITHOUT_PURSUIT, ///< guard command, no pursuit out of guard area - GUI_COMMAND_GUARD_FLYING_UNITS_ONLY, ///< guard command, ignore nonflyers - GUI_COMMAND_STOP, ///< stop moving - GUI_COMMAND_WAYPOINTS, ///< create a set of waypoints for this unit - GUI_COMMAND_EXIT_CONTAINER, ///< an inventory box for a container like a structure or transport - GUI_COMMAND_EVACUATE, ///< dump all our contents - GUI_COMMAND_EXECUTE_RAILED_TRANSPORT, ///< execute railed transport sequence - GUI_COMMAND_BEACON_DELETE, ///< delete a beacon - GUI_COMMAND_SET_RALLY_POINT, ///< set rally point for a structure - GUI_COMMAND_SELL, ///< sell a structure - GUI_COMMAND_FIRE_WEAPON, ///< fire a weapon - GUI_COMMAND_SPECIAL_POWER, ///< do a special power - GUI_COMMAND_PURCHASE_SCIENCE, ///< purchase science - GUI_COMMAND_HACK_INTERNET, ///< gain income from the ether (by hacking the internet) - GUI_COMMAND_TOGGLE_OVERCHARGE, ///< Overcharge command for power plants -#ifdef ALLOW_SURRENDER - GUI_COMMAND_POW_RETURN_TO_PRISON, ///< POW Truck, return to prison -#endif - GUI_COMMAND_COMBATDROP, ///< rappel contents to ground or bldg - GUI_COMMAND_SWITCH_WEAPON, ///< switch weapon use - - //Context sensitive command modes - GUICOMMANDMODE_HIJACK_VEHICLE, - GUICOMMANDMODE_CONVERT_TO_CARBOMB, - GUICOMMANDMODE_SABOTAGE_BUILDING, -#ifdef ALLOW_SURRENDER - GUICOMMANDMODE_PICK_UP_PRISONER, ///< POW Truck assigned to pick up a specific prisoner -#endif - - // context-insensitive command mode(s) - GUICOMMANDMODE_PLACE_BEACON, - - GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT, ///< do a special power from localPlayer's command center, regardless of selection -#if RTS_GENERALS - GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER = GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT, ///< Legacy name -#endif - GUI_COMMAND_SPECIAL_POWER_CONSTRUCT, ///< do a special power using the construct building interface - GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT, ///< do a shortcut special power using the construct building interface - - GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE, - - // add more commands here, don't forget to update the string command list below too ... - - GUI_COMMAND_NUM_COMMANDS -}; - -#ifdef DEFINE_GUI_COMMAND_NAMES -static const char *const TheGuiCommandNames[] = -{ - "NONE", - "DOZER_CONSTRUCT", - "DOZER_CONSTRUCT_CANCEL", - "UNIT_BUILD", - "CANCEL_UNIT_BUILD", - "PLAYER_UPGRADE", - "OBJECT_UPGRADE", - "CANCEL_UPGRADE", - "ATTACK_MOVE", - "GUARD", - "GUARD_WITHOUT_PURSUIT", - "GUARD_FLYING_UNITS_ONLY", - "STOP", - "WAYPOINTS", - "EXIT_CONTAINER", - "EVACUATE", - "EXECUTE_RAILED_TRANSPORT", - "BEACON_DELETE", - "SET_RALLY_POINT", - "SELL", - "FIRE_WEAPON", - "SPECIAL_POWER", - "PURCHASE_SCIENCE", - "HACK_INTERNET", - "TOGGLE_OVERCHARGE", -#ifdef ALLOW_SURRENDER - "POW_RETURN_TO_PRISON", -#endif - "COMBATDROP", - "SWITCH_WEAPON", - "HIJACK_VEHICLE", - "CONVERT_TO_CARBOMB", - "SABOTAGE_BUILDING", -#ifdef ALLOW_SURRENDER - "PICK_UP_PRISONER", -#endif - "PLACE_BEACON", -#if RTS_GENERALS - "SPECIAL_POWER_FROM_COMMAND_CENTER", ///< Legacy name -#else - "SPECIAL_POWER_FROM_SHORTCUT", -#endif - "SPECIAL_POWER_CONSTRUCT", - "SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT", - "SELECT_ALL_UNITS_OF_TYPE", - - nullptr -}; -static_assert(ARRAY_SIZE(TheGuiCommandNames) == GUI_COMMAND_NUM_COMMANDS + 1, "Incorrect array size"); -#endif // end DEFINE_GUI_COMMAND_NAMES - -enum CommandButtonMappedBorderType CPP_11(: Int) -{ - COMMAND_BUTTON_BORDER_NONE = 0, - COMMAND_BUTTON_BORDER_BUILD, - COMMAND_BUTTON_BORDER_UPGRADE, - COMMAND_BUTTON_BORDER_ACTION, - COMMAND_BUTTON_BORDER_SYSTEM, - - COMMAND_BUTTON_BORDER_COUNT -}; - -static const LookupListRec CommandButtonMappedBorderTypeNames[] = -{ - { "NONE", COMMAND_BUTTON_BORDER_NONE }, - { "BUILD", COMMAND_BUTTON_BORDER_BUILD }, - { "UPGRADE", COMMAND_BUTTON_BORDER_UPGRADE }, - { "ACTION", COMMAND_BUTTON_BORDER_ACTION }, - { "SYSTEM", COMMAND_BUTTON_BORDER_SYSTEM }, - - { nullptr, 0 } -}; -static_assert(ARRAY_SIZE(CommandButtonMappedBorderTypeNames) == COMMAND_BUTTON_BORDER_COUNT + 1, "Incorrect array size"); -//------------------------------------------------------------------------------------------------- -/** Command buttons are used to load the buttons we place on throughout the command bar - * interface in different context sensitive windows depending on the situation and - * type of the object selected */ -//------------------------------------------------------------------------------------------------- -class CommandButton : public Overridable -{ - - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CommandButton, "CommandButton" ); - -public: - - CommandButton(); - // virtual destructor prototype provided by MemoryPoolObject - - /// INI parsing - const FieldParse *getFieldParse() const { return s_commandButtonFieldParseTable; } - static const FieldParse s_commandButtonFieldParseTable[]; ///< the parse table - static void parseCommand( INI* ini, void *instance, void *store, const void *userData ); - - Bool isContextCommand() const; ///< determines if this is a context sensitive command. - Bool isValidRelationshipTarget(Relationship r) const; - Bool isValidObjectTarget(const Player* sourcePlayer, const Object* targetObj) const; - Bool isValidObjectTarget(const Object* sourceObj, const Object* targetObj) const; - Bool isValidObjectTarget(const Drawable* source, const Drawable* target) const; - - // Note: It is perfectly valid for either (or both!) of targetObj and targetLocation to be nullptr. - // This is a convenience function to make several calls to other functions. - Bool isValidToUseOn(const Object *sourceObj, const Object *targetObj, const Coord3D *targetLocation, CommandSourceType commandSource) const; - Bool isReady(const Object *sourceObj) const; - - const AsciiString& getName() const { return m_name; } - const AsciiString& getCursorName() const { return m_cursorName; } - const AsciiString& getInvalidCursorName() const { return m_invalidCursorName; } - const AsciiString& getTextLabel() const { return m_textLabel; } - const AsciiString& getDescriptionLabel() const { return m_descriptionLabel; } - const AsciiString& getPurchasedLabel() const { return m_purchasedLabel; } - const AsciiString& getConflictingLabel() const { return m_conflictingLabel; } - const AudioEventRTS* getUnitSpecificSound() const { return &m_unitSpecificSound; } - - GUICommandType getCommandType() const { return m_command; } - UnsignedInt getOptions() const { return m_options; } - OVERRIDE getThingTemplate() const { return m_thingTemplate; } - const UpgradeTemplate* getUpgradeTemplate() const { return m_upgradeTemplate; } - const SpecialPowerTemplate* getSpecialPowerTemplate() const { return m_specialPower; } - RadiusCursorType getRadiusCursorType() const { return m_radiusCursor; } - WeaponSlotType getWeaponSlot() const { return m_weaponSlot; } - Int getMaxShotsToFire() const { return m_maxShotsToFire; } - const ScienceVec& getScienceVec() const { return m_science; } - CommandButtonMappedBorderType getCommandButtonMappedBorderType() const { return m_commandButtonBorder; } - const Image* getButtonImage() const { return m_buttonImage; } - void cacheButtonImage(); - - GameWindow* getWindow() const { return m_window; } - Int getFlashCount() const { return m_flashCount; } - - const CommandButton* getNext() const { return m_next; } - - void setName(const AsciiString& n) { m_name = n; } - - void setButtonImage( const Image *image ) { m_buttonImage = image; } - - // bleah. shouldn't be const, but is. sue me. (srj) - void copyImagesFrom( const CommandButton *button, Bool markUIDirtyIfChanged ) const; - - // bleah. shouldn't be const, but is. sue me. (Kris) -snork! - void copyButtonTextFrom( const CommandButton *button, Bool shortcutButton, Bool markUIDirtyIfChanged ) const; - - // bleah. shouldn't be const, but is. sue me. (srj) - void setFlashCount(Int c) const { m_flashCount = c; } - - // only for ControlBar! - void friend_addToList(CommandButton** list) { m_next = *list; *list = this; } - CommandButton* friend_getNext() { return m_next; } - -private: - AsciiString m_name; ///< template name - GUICommandType m_command; ///< type of command this button - CommandButton* m_next; - UnsignedInt m_options; ///< command options (see CommandOption enum) - const ThingTemplate* m_thingTemplate; ///< for commands that use thing templates in command data - const UpgradeTemplate* m_upgradeTemplate; ///< for commands that use upgrade templates in command data - const SpecialPowerTemplate* m_specialPower; ///< actual special power template - RadiusCursorType m_radiusCursor; ///< radius cursor, if any - AsciiString m_cursorName; ///< cursor name for placement (NEED_TARGET_POS) or valid version (CONTEXTMODE_COMMAND) - AsciiString m_invalidCursorName; ///< cursor name for invalid version - - // bleah. shouldn't be mutable, but is. sue me. (Kris) -snork! - mutable AsciiString m_textLabel; ///< string manager text label - mutable AsciiString m_descriptionLabel; ///< The description of the current command, read in from the ini - - AsciiString m_purchasedLabel; ///< Description for the current command if it has already been purchased. - AsciiString m_conflictingLabel; ///< Description for the current command if it can't be selected due to multually-exclusive choice. - WeaponSlotType m_weaponSlot; ///< for commands that refer to a weapon slot - Int m_maxShotsToFire; ///< for commands that fire weapons - ScienceVec m_science; ///< actual science - CommandButtonMappedBorderType m_commandButtonBorder; - AsciiString m_buttonImageName; - GameWindow* m_window; ///< used during the run-time assignment of a button to a gadget button window - AudioEventRTS m_unitSpecificSound; ///< Unit sound played whenever button is clicked. - - // bleah. shouldn't be mutable, but is. sue me. (srj) - mutable const Image* m_buttonImage; ///< button image - // bleah. shouldn't be mutable, but is. sue me. (srj) - mutable Int m_flashCount; ///< the number of times a cameo is supposed to flash - -}; - -//------------------------------------------------------------------------------------------------- -/** Command sets are collections of configurable command buttons. They are used in the - * command context sensitive window in the battle user interface */ -//------------------------------------------------------------------------------------------------- -enum { MAX_COMMANDS_PER_SET = 18 }; // user interface max is 14 (but internally it's 18 for script only buttons!) -enum { MAX_RIGHT_HUD_UPGRADE_CAMEOS = 5}; -enum { - MAX_PURCHASE_SCIENCE_RANK_1 = 4, - MAX_PURCHASE_SCIENCE_RANK_3 = 15, - MAX_PURCHASE_SCIENCE_RANK_8 = 4, - }; -enum { MAX_STRUCTURE_INVENTORY_BUTTONS = 10 }; // there are this many physical buttons in "inventory" windows for structures -enum { MAX_BUILD_QUEUE_BUTTONS = 9 };// physical button count for the build queue -enum { MAX_SPECIAL_POWER_SHORTCUTS = 11}; -class CommandSet : public Overridable -{ - - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( CommandSet, "CommandSet" ) - -public: - - CommandSet( const AsciiString& name ); - // virtual destructor prototype provided by MemoryPoolObject - - const AsciiString& getName() const { return m_name; } - const CommandButton* getCommandButton(Int i) const; - - // only for the control bar. - CommandSet* friend_getNext() { return m_next; } - const FieldParse* friend_getFieldParse() const { return m_commandSetFieldParseTable; } - void friend_addToList(CommandSet** listHead); - -private: - - static const FieldParse m_commandSetFieldParseTable[]; ///< the parse table - static void parseCommandButton( INI* ini, void *instance, void *store, const void *userData ); - - AsciiString m_name; ///< name of this command set - const CommandButton *m_command[ MAX_COMMANDS_PER_SET ]; ///< the set of command buttons that make this set - - CommandSet *m_next; - -}; - -//------------------------------------------------------------------------------------------------- -/** The Side selece window data is used to animate on the proper generals select */ -//------------------------------------------------------------------------------------------------- -class SideSelectWindowData -{ -public: - SideSelectWindowData() - { - generalSpeak = nullptr; - m_currColor = 0; - m_gereralsNameWin = nullptr; - m_lastTime = 0; - m_pTemplate = nullptr; - m_sideNameWin = nullptr; - m_startTime = 0; - m_state = 0; - m_upgradeImage1 = nullptr; - m_upgradeImage1Win = nullptr; - m_upgradeImage2 = nullptr; - m_upgradeImage2Win = nullptr; - m_upgradeImage3 = nullptr; - m_upgradeImage3Win = nullptr; - m_upgradeImage4 = nullptr; - m_upgradeImage4Win = nullptr; - m_upgradeImageSize.x = m_upgradeImageSize.y = 0; - - m_upgradeLabel1Win = nullptr; - m_upgradeLabel2Win = nullptr; - m_upgradeLabel3Win = nullptr; - m_upgradeLabel4Win = nullptr; - sideWindow = nullptr; - } - ~SideSelectWindowData(); - - void init( ScienceType science, GameWindow *control ); - void reset(); - void update(); - void draw(); - - GameWindow *sideWindow; - GameWindow *m_animWindowWin; - AudioEventRTS *generalSpeak; -private: - enum - { - STATE_NONE = 0, - STATE_1, - STATE_2, - STATE_3, - STATE_4, - STATE_5, - STATE_6 - }; - - const PlayerTemplate *m_pTemplate; - - GameWindow *m_gereralsNameWin; - GameWindow *m_sideNameWin; - - - GameWindow *m_upgradeLabel1Win; - GameWindow *m_upgradeLabel2Win; - GameWindow *m_upgradeLabel3Win; - GameWindow *m_upgradeLabel4Win; - - GameWindow *m_upgradeImage1Win; - GameWindow *m_upgradeImage2Win; - GameWindow *m_upgradeImage3Win; - GameWindow *m_upgradeImage4Win; - - Image *m_upgradeImage1; - Image *m_upgradeImage2; - Image *m_upgradeImage3; - Image *m_upgradeImage4; - - IRegion2D m_leftLineFromButton; - IRegion2D m_rightLineFromButton; - - IRegion2D m_upgradeLine1a; - IRegion2D m_upgradeLine2a; - IRegion2D m_upgradeLine3a; - IRegion2D m_upgradeLine4a; - - IRegion2D m_upgradeLine1; - IRegion2D m_upgradeLine2; - IRegion2D m_upgradeLine3; - IRegion2D m_upgradeLine4; - - IRegion2D m_upgradeLine1MidReg; - IRegion2D m_upgradeLine2MidReg; - IRegion2D m_upgradeLine3MidReg; - IRegion2D m_upgradeLine4MidReg; - - IRegion2D m_upgrade1Clip; - IRegion2D m_upgrade2Clip; - IRegion2D m_upgrade3Clip; - IRegion2D m_upgrade4Clip; - - Color m_currColor; - ICoord2D m_line1End; - ICoord2D m_line2End; - - - ICoord2D m_upgradeLine1Mid; - ICoord2D m_upgradeLine2Mid; - ICoord2D m_upgradeLine3Mid; - ICoord2D m_upgradeLine4Mid; - - ICoord2D m_upgradeLine1End; - ICoord2D m_upgradeLine2End; - ICoord2D m_upgradeLine3End; - ICoord2D m_upgradeLine4End; - - ICoord2D m_upgradeImagePos1; - ICoord2D m_upgradeImagePos2; - ICoord2D m_upgradeImagePos3; - ICoord2D m_upgradeImagePos4; - - ICoord2D m_upgradeImageSize; - - Int m_state; - UnsignedInt m_lastTime; - UnsignedInt m_startTime; -}; - -//------------------------------------------------------------------------------------------------- -/** A command bar context is a window or set of windows that make up a context sensitive - * display of commands and information to the user based on what objects are selected - * and their capabilities */ -//------------------------------------------------------------------------------------------------- -enum ControlBarContext CPP_11(: Int) -{ - CB_CONTEXT_NONE, ///< default view for center bar and portrait window -// CB_CONTEXT_PURCHASE_SCIENCE, - CB_CONTEXT_COMMAND, ///< set of commands (attack-move,stop,deploy etc) - CB_CONTEXT_STRUCTURE_INVENTORY, ///< garrisonable building inventory interface - CB_CONTEXT_BEACON, ///< beacon interface - CB_CONTEXT_UNDER_CONSTRUCTION, ///< building under construction - CB_CONTEXT_MULTI_SELECT, ///< for when we have multiple objects selected - CB_CONTEXT_OBSERVER_INFO, ///< for when we want to populate the player info - CB_CONTEXT_OBSERVER_LIST, ///< for when we want to update the observer list - CB_CONTEXT_OCL_TIMER, ///< Countdown for OCL spewers -}; - -//------------------------------------------------------------------------------------------------- -/** Context parents, are parent windows in the control bar interface that are the key - * parts we care about to make the whole interface a context sensitive one. We will - * hide and un-hide these windows and their interface controls in order to make - * the control bar context sensitive to the object that is selected */ -//------------------------------------------------------------------------------------------------- -enum ContextParent CPP_11(: Int) -{ - CP_MASTER, ///< *The* control bar window as a whole - CP_PURCHASE_SCIENCE, - CP_COMMAND, ///< configurable command buttons parent - CP_BUILD_QUEUE, ///< build queue parent - CP_BEACON, ///< beacon parent - CP_UNDER_CONSTRUCTION, ///< building under construction parent - CP_OBSERVER_INFO, ///< Observer Info window parent - CP_OBSERVER_LIST, ///< Observer player list parent - CP_OCL_TIMER, ///< Countdown for OCL spewers - - NUM_CONTEXT_PARENTS -}; - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -enum CBCommandStatus CPP_11(: Int) -{ - CBC_COMMAND_NOT_USED = 0, ///< gui control message was *not* used - CBC_COMMAND_USED ///< gui control message was used -}; - -// ------------------------------------------------------------------------------------------------ -/** Command availability is used during the context update so that we can set the - * GUI button to be enabled/disabled/checked/unchecked to represent the current - * state of that command availability */ -// ------------------------------------------------------------------------------------------------ -enum CommandAvailability CPP_11(: Int) -{ - COMMAND_RESTRICTED, - COMMAND_AVAILABLE, - COMMAND_ACTIVE, - COMMAND_HIDDEN, - COMMAND_NOT_READY, - COMMAND_CANT_AFFORD, -}; - -enum ControlBarStages CPP_11(: Int) -{ - CONTROL_BAR_STAGE_DEFAULT = 0, ///< full view for the world to see - CONTROL_BAR_STAGE_SQUISHED, ///< squished just for expeirenced players - CONTROL_BAR_STAGE_LOW, ///< control bar a la minimalist - CONTROL_BAR_STAGE_HIDDEN, ///< yo, where be da control bar at? - - MAX_CONTROL_BAR_STAGES -}; - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -class ControlBar : public SubsystemInterface -{ - -public: - - ControlBar(); - virtual ~ControlBar() override; - - virtual void init() override; ///< from subsystem interface - virtual void reset() override; ///< from subsystem interface - virtual void update() override; ///< from subsystem interface - - /// mark the UI as dirty so the context of everything is re-evaluated - void markUIDirty(); - - /// a drawable has just become selected - void onDrawableSelected( Drawable *draw ); - - /// a drawable has just become de-selected - void onDrawableDeselected( Drawable *draw ); - - void onPlayerRankChanged(const Player *p); - void onPlayerSciencePurchasePointsChanged(const Player *p); - - /** if this button is part of the context sensitive command system, process a button click - the gadgetMessage is either a GBM_SELECTED or GBM_SELECTED_RIGHT */ - CBCommandStatus processContextSensitiveButtonClick( GameWindow *button, - GadgetGameMessage gadgetMessage ); - - /** if this button is part of the context sensitive command system, process the Transition - gadgetMessage is either a GBM_MOUSE_LEAVING or GBM_MOUSE_ENTERING */ - CBCommandStatus processContextSensitiveButtonTransition( GameWindow *button, - GadgetGameMessage gadgetMessage ); - - - /// is the drawable the currently selected drawable for the context sensitive UI? - Bool isDrivingContextUI( Drawable *draw ) const { return draw == m_currentSelectedDrawable; } - - //----------------------------------------------------------------------------------------------- - // the remaining methods are used to construct the command buttons and command sets for - // the command bar - //----------------------------------------------------------------------------------------------- - - /// find existing command button if present - const CommandButton *findCommandButton( const AsciiString& name ); - - /// find existing command set - const CommandSet *findCommandSet( const AsciiString& name ); - - void showPurchaseScience(); - void hidePurchaseScience(); - void togglePurchaseScience(); - - void showSpecialPowerShortcut(); - void hideSpecialPowerShortcut(); - void animateSpecialPowerShortcut( Bool isOn ); - - void setFullViewportHeight(); - void setScaledViewportHeight(); - - /// set the control bar to the proper scheme based off a player template that's passed in - ControlBarSchemeManager *getControlBarSchemeManager() { return m_controlBarSchemeManager; } - void setControlBarSchemeByPlayer(Player *p); - void setControlBarSchemeByName(const AsciiString& name); - void setControlBarSchemeByPlayerTemplate(const PlayerTemplate *pt); - - /// We need to sometime change what the images look like depending on what scheme we're using - void updateBuildQueueDisabledImages( const Image *image ); - - /// We need to sometime change what the images look like depending on what scheme we're using - void updateRightHUDImage( const Image *image ); - - /// We need to be able to update the command marker image based on which scheme we're using. - void updateCommandMarkerImage( const Image *image ); - void updateSlotExitImage( const Image *image); - - void updateUpDownImages( const Image *toggleButtonUpIn, const Image *toggleButtonUpOn, const Image *toggleButtonUpPushed, const Image *toggleButtonDownIn, const Image *toggleButtonDownOn, const Image *toggleButtonDownPushed,const Image *generalButtonEnable, const Image *generalButtonHighlight ); - - void preloadAssets( TimeOfDay timeOfDay ); ///< preload the assets - - /// We want to be able to have the control bar scheme set the color of the build up clock - void updateBuildUpClockColor( Color color); - - WindowVideoManager *m_videoManager; ///< Video manager to take care of all animations on screen. - AnimateWindowManager *m_animateWindowManager; ///< The animate window manager - AnimateWindowManager *m_animateWindowManagerForGenShortcuts; ///< The animate window manager - void updatePurchaseScience(); - AnimateWindowManager *m_generalsScreenAnimate; ///< The animate window manager - - // Initialize the Observer controls Must be called after we've already loaded the window - void initObserverControls(); - void populateObserverInfoWindow (); - void populateObserverList(); - Bool isObserverControlBarOn() { return m_isObserverCommandBar;} - - void setObserverLookAtPlayer (Player *player); ///< Sets the looked at player. Used to present information about the player. - Player *getObserverLookAtPlayer () const { return m_observerLookAtPlayer; } ///< Returns the looked at player. Can return null. - - void setObservedPlayer(Player *player); ///< Sets the observed player. Used to present the game world as if that player was the local player. - Player *getObservedPlayer() const { return m_observedPlayer; } ///< Return the observed player. Can return null. - - /// Returns the currently viewed player. May return nullptr if no player is selected while observing. - Player* getCurrentlyViewedPlayer(); - /// Returns the relationship with the currently viewed player. May return NEUTRAL if no player is selected while observing. - Relationship getCurrentlyViewedPlayerRelationship(const Team* team); - -// ControlBarResizer *getControlBarResizer() {return m_controlBarResizer;} - - // Functions for repositioning/resizing the control bar - void switchControlBarStage( ControlBarStages stage ); - void toggleControlBarStage(); - - const Image *getStarImage(); - - Color getBorderColor(){return m_commandBarBorderColor;} - void updateBorderColor( Color color) {m_commandBarBorderColor = color; } - - /// set the command data into the button - void setControlCommand( GameWindow *button, const CommandButton *commandButton ); - - void getForegroundMarkerPos(Int *x, Int *y); - void getBackgroundMarkerPos(Int *x, Int *y); - - - static void parseCommandSetDefinition( INI *ini ); - static void parseCommandButtonDefinition( INI *ini ); - - void drawTransitionHandler(); - const Image *getArrowImage(){ return m_genArrow; } - void setArrowImage( const Image *arrowImage ){ m_genArrow = arrowImage; } - - void initSpecialPowershortcutBar( Player *player); - - void triggerRadarAttackGlow(); - - void drawSpecialPowerShortcutMultiplierText(); - - Bool hasAnyShortcutSelection() const; - -protected: - void updateRadarAttackGlow (); - - void setDefaultControlBarConfig(); - void setSquishedControlBarConfig(); - void setLowControlBarConfig(); - void setHiddenControlBar(); - - /// find existing command button if present - CommandButton* findNonConstCommandButton( const AsciiString& name ); - - /// allocate a new command button, link to list, initialize to default, and return - CommandButton *newCommandButton( const AsciiString& name ); - CommandButton *newCommandButtonOverride( CommandButton *buttonToOverride ); - - /// allocate a new command set, link to list, initialize to default, and return it - CommandSet *newCommandSet( const AsciiString& name ); - CommandSet *newCommandSetOverride( CommandSet *setToOverride ); - - - /// evaluate what the user should see based on what selected drawables we have in our UI - void evaluateContextUI(); - - /// add the common commands of this drawable to the common command set - void addCommonCommands( Drawable *draw, Bool firstDrawable ); - - /// switch the interface context to the new mode and populate as needed - void switchToContext( ControlBarContext context, Drawable *draw ); - - /// set the command data into the button - void setControlCommand( const AsciiString& buttonWindowName, GameWindow *parent, - const CommandButton *commandButton ); - - /// show/hide the portrait window image using the image pointer to set - void setPortraitByImage( const Image *image ); - - /// show/hide the portrait window image using the image from the object - void setPortraitByObject( Object *obj ); - - /// show rally point at world location, a nullptr location will hide any visible rally point marker - void showRallyPoint( const Coord3D *loc ); - - /// post process step, after all commands and command sets are loaded - void postProcessCommands(); - - // the following methods are for resetting data for various contexts - void resetCommonCommandData(); /// reset shared command data - void resetContainData(); /// reset container data we use to tie controls to objects IDs for containment - void resetBuildQueueData(); /// reset the build queue data we use to die queue entires to control - - // the following methods are for populating the context GUI controls for a particular context - static void populateButtonProc( Object *obj, void *userData ); - void populatePurchaseScience(Player* player); - void populateCommand( Object *obj ); - void populateMultiSelect(); - void populateBuildQueue( Object *producer ); - void populateStructureInventory( Object *building ); - void populateBeacon( Object *beacon ); - void populateUnderConstruction( Object *objectUnderConstruction ); - void populateOCLTimer( Object *creatorObject ); - void doTransportInventoryUI( Object *transport, const CommandSet *commandSet ); - static void populateInvDataCallback( Object *obj, void *userData ); - - // the following methods are for updating the currently showing context - CommandAvailability getCommandAvailability( const CommandButton *command, Object *obj, GameWindow *win, GameWindow *applyToWin = nullptr, Bool forceDisabledEvaluation = FALSE ) const; - void updateContextMultiSelect(); - void updateContextPurchaseScience(); - void updateContextCommand(); - void updateContextStructureInventory(); - void updateContextBeacon(); - void updateContextUnderConstruction(); - void updateContextOCLTimer(); - - // the following methods are for the special power shortcut window - - void populateSpecialPowerShortcut( Player *player); - void updateSpecialPowerShortcut(); - - static const Image* calculateVeterancyOverlayForThing( const ThingTemplate *thingTemplate ); - static const Image* calculateVeterancyOverlayForObject( const Object *obj ); - - // the following methods do command processing for GUI selections - CBCommandStatus processCommandUI( GameWindow *control, GadgetGameMessage gadgetMessage ); - CBCommandStatus processCommandTransitionUI( GameWindow *control, GadgetGameMessage gadgetMessage ); - - // methods to help out with each context - void updateConstructionTextDisplay( Object *obj ); - void updateOCLTimerTextDisplay( UnsignedInt totalSeconds, Real percent ); - - void setUpDownImages(); - // methods for flashing cameos -public: - void setFlash( Bool b ) { m_flash = b; } - - // get method for list of commandbuttons - const CommandButton *getCommandButtons() { return m_commandButtons; } - -protected: - - ICoord2D m_defaultControlBarPosition; ///< Stored the original position of the control bar on the screen - ControlBarStages m_currentControlBarStage; - - Bool m_UIDirty; ///< the context UI must be re-evaluated - - CommandButton *m_commandButtons; ///< list of possible commands to have - CommandSet *m_commandSets; ///< list of all command sets defined - ControlBarSchemeManager *m_controlBarSchemeManager; ///< The Scheme singleton - - GameWindow *m_contextParent[ NUM_CONTEXT_PARENTS ]; ///< "parent" window for buttons that are part of the context sensitive interface - - Drawable *m_currentSelectedDrawable; ///< currently selected drawable for the context sensitive interface - ControlBarContext m_currContext; ///< our current displayed context - - DrawableID m_rallyPointDrawableID; ///< rally point drawable for visual rally point - - Real m_displayedConstructPercent; ///< construct percent last displayed to user - UnsignedInt m_displayedOCLTimerSeconds; ///< OCL Timer seconds remaining last displayed to user - UnsignedInt m_displayedQueueCount; ///< queue count last displayed to user - UnsignedInt m_lastRecordedInventoryCount; ///< last known UI state of an inventory count - - GameWindow *m_rightHUDWindow; ///< window of the right HUD display - GameWindow *m_rightHUDCameoWindow; ///< window of the right HUD display - GameWindow *m_rightHUDUpgradeCameos[MAX_RIGHT_HUD_UPGRADE_CAMEOS]; - GameWindow *m_rightHUDUnitSelectParent; - - GameWindow *m_communicatorButton; ///< button for the communicator - - WindowLayout *m_scienceLayout; ///< the Science window layout - GameWindow *m_sciencePurchaseWindowsRank1[ MAX_PURCHASE_SCIENCE_RANK_1 ]; ///< command window controls for easy access - GameWindow *m_sciencePurchaseWindowsRank3[ MAX_PURCHASE_SCIENCE_RANK_3 ]; ///< command window controls for easy access - GameWindow *m_sciencePurchaseWindowsRank8[ MAX_PURCHASE_SCIENCE_RANK_8 ]; ///< command window controls for easy access - GameWindow *m_specialPowerShortcutButtons[ MAX_SPECIAL_POWER_SHORTCUTS ]; - GameWindow *m_specialPowerShortcutButtonParents[ MAX_SPECIAL_POWER_SHORTCUTS ]; - DisplayString *m_shortcutDisplayStrings[ MAX_SPECIAL_POWER_SHORTCUTS ]; - Int m_currentlyUsedSpecialPowersButtons; ///< Value will be <= MAX_SPECIAL_POWER_SHORTCUTS; - - - WindowLayout *m_specialPowerLayout; - GameWindow *m_specialPowerShortcutParent; - - GameWindow *m_commandWindows[ MAX_COMMANDS_PER_SET ]; ///< command window controls for easy access - const CommandButton *m_commonCommands[ MAX_COMMANDS_PER_SET ]; ///< shared commands we will use for multi-selection - - // removed from multiplayer branch - //GameWindow *m_commandMarkers[ MAX_COMMANDS_PER_SET ]; ///< When we don't have a command, they want to show an image -// removed from multiplayer branch - //void showCommandMarkers(); ///< function that compare's what's being shown in m_commandWindows and shows the ones that are hidden. - - -public: - // method for hiding communicator window CCB - void hideCommunicator( Bool b ); - -protected: - - struct ContainEntry - { - GameWindow *control; - ObjectID objectID; - }; - static ContainEntry m_containData[ MAX_COMMANDS_PER_SET ]; ///< inventory buttons integrated into the regular command set for buildings/transports - - struct QueueEntry - { - GameWindow *control; ///< window that the GUI control is tied to - ProductionType type; ///< type of queue data - union - { - ProductionID productionID; ///< production id for unit productions - const UpgradeTemplate *upgradeToResearch; ///< upgrade template for upgrade productions - }; - - }; - QueueEntry m_queueData[ MAX_BUILD_QUEUE_BUTTONS ]; ///< what the build queue represents - - //cameo flash - Bool m_flash; ///< tells update whether or not to check for flash - - Bool m_sideSelectAnimateDown; - ICoord2D m_animateDownWin1Size; - ICoord2D m_animateDownWin2Size; - ICoord2D m_animateDownWin1Pos; - ICoord2D m_animateDownWin2Pos; - GameWindow *m_animateDownWindow; - UnsignedInt m_animTime; - - Color m_buildUpClockColor; - - Bool m_isObserverCommandBar; ///< If this is true, the command bar behaves greatly different - Player *m_observerLookAtPlayer; ///< The current player we're looking at, Null if we're not looking at anyone. - Player *m_observedPlayer; ///< The current player we're observing, Null if we're not observing anyone. - - WindowLayout *m_buildToolTipLayout; ///< The window that will slide on/display tooltips - Bool m_showBuildToolTipLayout; ///< every frame we test to see if we are going to continue showing this or not. -public: - void showBuildTooltipLayout( GameWindow *cmdButton ); - void hideBuildTooltipLayout(); - void deleteBuildTooltipLayout(); - Bool getShowBuildTooltipLayout(){return m_showBuildToolTipLayout; } - void populateBuildTooltipLayout( const CommandButton *commandButton, GameWindow *tooltipWin = nullptr ); - void repopulateBuildTooltipLayout(); -private: - - - // Command Bar button border bars stuff - Color m_commandButtonBorderBuildColor; - Color m_commandButtonBorderActionColor; - Color m_commandButtonBorderUpgradeColor; - Color m_commandButtonBorderSystemColor; - - Color m_commandBarBorderColor; - - void setCommandBarBorder( GameWindow *button, CommandButtonMappedBorderType type); -public: - void updateCommandBarBorderColors(Color build, Color action, Color upgrade, Color system ); - -private: - - /// find existing command set - CommandSet *findNonConstCommandSet( const AsciiString& name ); - - const Image *m_genStarOn; - const Image *m_genStarOff; - - const Image *m_toggleButtonUpIn; - const Image *m_toggleButtonUpOn; - const Image *m_toggleButtonUpPushed; - const Image *m_toggleButtonDownIn; - const Image *m_toggleButtonDownOn; - const Image *m_toggleButtonDownPushed; - - GameWindowTransitionsHandler *m_transitionHandler; - const Image *m_genArrow; - - static const Image *m_rankVeteranIcon; - static const Image *m_rankEliteIcon; - static const Image *m_rankHeroicIcon; - - const Image *m_generalButtonEnable; - const Image *m_generalButtonHighlight; - - - Bool m_genStarFlash; - Int m_lastFlashedAtPointValue; - - ICoord2D m_controlBarForegroundMarkerPos; - ICoord2D m_controlBarBackgroundMarkerPos; - - Bool m_radarAttackGlowOn; - Int m_remainingRadarAttackGlowFrames; - GameWindow *m_radarAttackGlowWindow; - -#if defined(RTS_DEBUG) - UnsignedInt m_lastFrameMarkedDirty; - UnsignedInt m_consecutiveDirtyFrames; -#endif -// ControlBarResizer *m_controlBarResizer; - -}; - -// EXTERNALS ////////////////////////////////////////////////////////////////////////////////////// -extern ControlBar *TheControlBar; diff --git a/Generals/Code/GameEngine/Include/GameClient/ControlBarResizer.h b/Generals/Code/GameEngine/Include/GameClient/ControlBarResizer.h deleted file mode 100644 index 8617d7da0e8..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/ControlBarResizer.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarResizer.h ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Sep 2002 -// -// Filename: ControlBarResizer.h -// -// author: Chris Huybregts -// -// purpose: -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// FORWARD REFERENCES ///////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// TYPE DEFINES /////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -class ResizerWindow -{ -public: -ResizerWindow(); - AsciiString m_name; - ICoord2D m_defaultSize; - ICoord2D m_defaultPos; - ICoord2D m_altSize; - ICoord2D m_altPos; -}; - -class ControlBarResizer -{ -public: - ControlBarResizer(); - ~ControlBarResizer(); - - void init(); - - // parse Functions for the INI file - const FieldParse *getFieldParse() const { return m_controlBarResizerParseTable; } ///< returns the parsing fields - static const FieldParse m_controlBarResizerParseTable[]; ///< the parse table - - ResizerWindow *findResizerWindow( AsciiString name ); ///< attempt to find the control bar scheme by it's name - ResizerWindow *newResizerWindow( AsciiString name ); ///< create a new control bar scheme and return it. - - void sizeWindowsDefault(); - void sizeWindowsAlt(); - - typedef std::list< ResizerWindow *> ResizerWindowList; - ResizerWindowList m_resizerWindowsList; - -}; -//----------------------------------------------------------------------------- -// INLINING /////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// EXTERNALS ////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Include/GameClient/ControlBarScheme.h b/Generals/Code/GameEngine/Include/GameClient/ControlBarScheme.h deleted file mode 100644 index 901b7349f8e..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/ControlBarScheme.h +++ /dev/null @@ -1,286 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarScheme.h ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Apr 2002 -// -// Filename: ControlBarScheme.h -// -// author: Chris Huybregts -// -// purpose: -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "GameClient/Color.h" - -//----------------------------------------------------------------------------- -// FORWARD REFERENCES ///////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -class AsciiString; -class playerTemplate; -class Image; -enum TimeOfDay CPP_11(: Int); - -//----------------------------------------------------------------------------- -// TYPE DEFINES /////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#define MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS 6 -#define CONTROL_BAR_SCHEME_FOREGROUND_IMAGE_LAYERS 3 - -// Class that holds the images the control bar will draw -//----------------------------------------------------------------------------- -class ControlBarSchemeImage -{ -public: - ControlBarSchemeImage(); - ~ControlBarSchemeImage(); - - AsciiString m_name; ///< Name of the image - ICoord2D m_position; ///< the position we'll draw it at - ICoord2D m_size; ///< the size of the image needed when we draw it - Image *m_image; ///< the actual pointer to the mapped image - - // m_layer is where the image will get drawn, everything in layer 0-2 gets drawn during the foreground draw - // the layers 3-5 gets drawn during the background draw - Int m_layer; //layer means how deep the image will be drawn, it's a number between 0-5 with 0 being on top -}; - -// Class that will hold the information needed for the animations -//----------------------------------------------------------------------------- -class ControlBarSchemeAnimation -{ -public: - ControlBarSchemeAnimation(); - ~ControlBarSchemeAnimation(); - /// Enum that will contain all the kinds of animations we have... make sure in ControlBarScheme.cpp there's a - /// mapping for it for the INI translation - enum - { - CB_ANIM_SLIDE_RIGHT = 0, - - CB_ANIM_MAX - }; - - AsciiString m_name; ///< Current animation name - Int m_animType; ///< Type of animation that this will follow - ControlBarSchemeImage *m_animImage; ///< Pointer of the image that this animation will act on - UnsignedInt m_animDuration; ///< Contians how long the animation should take based off game frames - ICoord2D m_finalPos; ///< The final position when we hit the m_animDuration frame - - UnsignedInt getCurrentFrame() { return m_currentFrame; } - void setCurrentFrame( UnsignedInt currentFrame ) { m_currentFrame = currentFrame; } - ICoord2D getStartPos() { return m_startPos; } - void setStartPos(ICoord2D startPos) { m_startPos = startPos; } -private: - ICoord2D m_startPos; ///< set when we first begin an animation - UnsignedInt m_currentFrame; ///< This is the last frame (a value between 0 and m_animDuration) -}; - - -// Class that each scheme will have. Contains all information about that scheme -//----------------------------------------------------------------------------- -class ControlBarScheme -{ -public: - ControlBarScheme(); - ~ControlBarScheme(); - - void init(); - void update(); - void drawForeground( Coord2D multi, ICoord2D offset ); ///< draw function to be called within a w3d draw procedure for the foreground - void drawBackground( Coord2D multi, ICoord2D offset ); ///< draw function to be called within a w3d draw procedure for the background - void reset(); - - void addAnimation( ControlBarSchemeAnimation *schemeAnim ); - void addImage( ControlBarSchemeImage *schemeImage); - void updateAnim (ControlBarSchemeAnimation * anim); - - - AsciiString m_name; ///< it's name - ICoord2D m_ScreenCreationRes; ///< Used to determine what screen res this will look the best on - AsciiString m_side; ///< contain what faction type this command bar was made for (used when selecting command bar by template - Image *m_buttonQueueImage; ///< We'll probably want each one to have it's own image. - Image *m_rightHUDImage; ///< We'll probably want each one to have it's own right HUD image. - Color m_buildUpClockColor; ///< we can setup the color for the buildup clock if we want - - Color m_borderBuildColor; ///< we can setup the color for the button border colors - Color m_borderActionColor; ///< we can setup the color for the button border colors - Color m_borderUpgradeColor; ///< we can setup the color for the button border colors - Color m_borderSystemColor; ///< we can setup the color for the button border colors - - Color m_commandBarBorderColor; - - Image *m_optionsButtonEnable; - Image *m_optionsButtonHightlited; - Image *m_optionsButtonPushed; - Image *m_optionsButtonDisabled; - - Image *m_idleWorkerButtonEnable; - Image *m_idleWorkerButtonHightlited; - Image *m_idleWorkerButtonPushed; - Image *m_idleWorkerButtonDisabled; - - Image *m_buddyButtonEnable; - Image *m_buddyButtonHightlited; - Image *m_buddyButtonPushed; - Image *m_buddyButtonDisabled; - - Image *m_beaconButtonEnable; - Image *m_beaconButtonHightlited; - Image *m_beaconButtonPushed; - Image *m_beaconButtonDisabled; - - Image *m_genBarButtonIn; - Image *m_genBarButtonOn; - - Image *m_toggleButtonUpIn; - Image *m_toggleButtonUpOn; - Image *m_toggleButtonUpPushed; - Image *m_toggleButtonDownIn; - Image *m_toggleButtonDownOn; - Image *m_toggleButtonDownPushed; - - Image *m_generalButtonEnable; - Image *m_generalButtonHightlited; - Image *m_generalButtonPushed; - Image *m_generalButtonDisabled; - - Image *m_uAttackButtonEnable; - Image *m_uAttackButtonHightlited; - Image *m_uAttackButtonPushed; - - Image *m_minMaxButtonEnable; - Image *m_minMaxButtonHightlited; - Image *m_minMaxButtonPushed; - - Image *m_genArrow; - - - ICoord2D m_moneyUL; - ICoord2D m_moneyLR; - - ICoord2D m_minMaxUL; - ICoord2D m_minMaxLR; - - ICoord2D m_generalUL; - ICoord2D m_generalLR; - - ICoord2D m_uAttackUL; - ICoord2D m_uAttackLR; - - ICoord2D m_optionsUL; - ICoord2D m_optionsLR; - - ICoord2D m_workerUL; - ICoord2D m_workerLR; - - ICoord2D m_chatUL; - ICoord2D m_chatLR; - - ICoord2D m_beaconUL; - ICoord2D m_beaconLR; - - ICoord2D m_powerBarUL; - ICoord2D m_powerBarLR; - - - - - - Image *m_expBarForeground; - - Image *m_commandMarkerImage; - - typedef std::list< ControlBarSchemeImage* > ControlBarSchemeImageList; - ControlBarSchemeImageList m_layer[MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS]; - - typedef std::list< ControlBarSchemeAnimation* > ControlBarSchemeAnimationList; - ControlBarSchemeAnimationList m_animations; - -}; - - -class ControlBarSchemeManager -{ -public: - ControlBarSchemeManager(); - ~ControlBarSchemeManager(); - - void init(); ///< Initialize from the INI files - void update(); ///< move the animations if we have any - void drawForeground( ICoord2D offset ); ///< draw function to be called within a w3d draw procedure for the foreground - void drawBackground( ICoord2D offset ); ///< draw function to be called within a w3d draw procedure for the background - - void setControlBarSchemeByPlayer(Player *p); ///< Based off the playerTemplate, pick the right scheme for the control bar - void setControlBarSchemeByPlayerTemplate( const PlayerTemplate *pt, Bool useSmall = FALSE); - void setControlBarScheme(AsciiString schemeName); ///< SchemeName must be a valid INI entry - - // parse Functions for the INI file - const FieldParse *getFieldParse() const { return m_controlBarSchemeFieldParseTable; } ///< returns the parsing fields - static const FieldParse m_controlBarSchemeFieldParseTable[]; ///< the parse table - static void parseImagePart( INI* ini, void *instance, void *store, const void *userData ); ///< Parse the image part of the INI file - static void parseAnimatingPart( INI* ini, void *instance, void *store, const void *userData ); ///< Parse the animation part of the INI file - static void parseAnimatingPartImage( INI* ini, void *instance, void *store, const void *userData ); ///< parse the image part of the animation part :) - - ControlBarScheme *findControlBarScheme( AsciiString name ); ///< attempt to find the control bar scheme by it's name - ControlBarScheme *newControlBarScheme( AsciiString name ); ///< create a new control bar scheme and return it. - - void preloadAssets( TimeOfDay timeOfDay ); ///< preload the assets - -private: - ControlBarScheme *m_currentScheme; ///< the current scheme that everythign uses - Coord2D m_multiplier; - - typedef std::list< ControlBarScheme* > ControlBarSchemeList; ///< list of control bar schemes - ControlBarSchemeList m_schemeList; - -}; - -//----------------------------------------------------------------------------- -// INLINING /////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// EXTERNALS ////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp deleted file mode 100644 index ebd6ec65472..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp +++ /dev/null @@ -1,3803 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBar.cpp /////////////////////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Context sensitive command interface -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine -#define DEFINE_GUI_COMMAND_NAMES -#define DEFINE_COMMAND_OPTION_NAMES -#define DEFINE_WEAPONSLOTTYPE_NAMES -#define DEFINE_RADIUSCURSOR_NAMES - -#include "Common/ActionManager.h" -#include "Common/GameType.h" -#include "Common/MultiplayerSettings.h" -#include "Common/NameKeyGenerator.h" -#include "Common/Override.h" -#include "Common/PlayerTemplate.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/ProductionPrerequisite.h" -#include "Common/SpecialPower.h" -#include "Common/ThingTemplate.h" -#include "Common/ThingFactory.h" -#include "Common/Upgrade.h" -#include "Common/Recorder.h" - -#include "GameLogic/GameLogic.h" -#include "GameLogic/Object.h" -#include "GameLogic/Module/ProductionUpdate.h" -#include "GameLogic/Module/OCLUpdate.h" -#include "GameLogic/Module/ContainModule.h" -#include "GameLogic/Module/SpecialPowerModule.h" -#include "GameLogic/Module/StealthUpdate.h" -#include "GameLogic/Module/RebuildHoleBehavior.h" -#include "GameLogic/ScriptEngine.h" - -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/ControlBar.h" -#include "GameClient/ControlBarScheme.h" -#include "GameClient/Drawable.h" -#include "GameClient/Display.h" -#include "GameClient/DisplayStringManager.h" -#include "GameClient/GameClient.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GameText.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetProgressBar.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/InGameUI.h" -#include "GameClient/WindowVideoManager.h" -#include "GameClient/ControlBarResizer.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/HotKey.h" -#include "GameClient/GameWindowTransitions.h" -#include "GameClient/GUICallbacks.h" - -#include "GameNetwork/GameInfo.h" - - -// PUBLIC ///////////////////////////////////////////////////////////////////////////////////////// -ControlBar *TheControlBar = nullptr; - -const Image* ControlBar::m_rankVeteranIcon = nullptr; -const Image* ControlBar::m_rankEliteIcon = nullptr; -const Image* ControlBar::m_rankHeroicIcon = nullptr; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// CommandButton ////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -const FieldParse CommandButton::s_commandButtonFieldParseTable[] = -{ - - { "Command", CommandButton::parseCommand, nullptr, offsetof( CommandButton, m_command ) }, - { "Options", INI::parseBitString32, TheCommandOptionNames, offsetof( CommandButton, m_options ) }, - { "Object", INI::parseThingTemplate, nullptr, offsetof( CommandButton, m_thingTemplate ) }, - { "Upgrade", INI::parseUpgradeTemplate, nullptr, offsetof( CommandButton, m_upgradeTemplate ) }, - { "WeaponSlot", INI::parseLookupList, TheWeaponSlotTypeNamesLookupList, offsetof( CommandButton, m_weaponSlot ) }, - { "MaxShotsToFire", INI::parseInt, nullptr, offsetof( CommandButton, m_maxShotsToFire ) }, - { "Science", INI::parseScienceVector, nullptr, offsetof( CommandButton, m_science ) }, - { "SpecialPower", INI::parseSpecialPowerTemplate, nullptr, offsetof( CommandButton, m_specialPower ) }, - { "TextLabel", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_textLabel ) }, - { "DescriptLabel", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_descriptionLabel ) }, - { "PurchasedLabel", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_purchasedLabel ) }, - { "ConflictingLabel", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_conflictingLabel ) }, - { "ButtonImage", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_buttonImageName ) }, - { "CursorName", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_cursorName ) }, - { "InvalidCursorName", INI::parseAsciiString, nullptr, offsetof( CommandButton, m_invalidCursorName ) }, - { "ButtonBorderType", INI::parseLookupList, CommandButtonMappedBorderTypeNames, offsetof( CommandButton, m_commandButtonBorder ) }, - { "RadiusCursorType", INI::parseIndexList, TheRadiusCursorNames, offsetof( CommandButton, m_radiusCursor ) }, - { "UnitSpecificSound", INI::parseAudioEventRTS, nullptr, offsetof( CommandButton, m_unitSpecificSound ) }, - - { nullptr, nullptr, nullptr, 0 } - -}; -static void commandButtonTooltip(GameWindow *window, - WinInstanceData *instData, - UnsignedInt mouse) -{ - TheControlBar->showBuildTooltipLayout(window); -} - -/// mark the UI as dirty so the context of everything is re-evaluated -void ControlBar::markUIDirty() -{ - m_UIDirty = TRUE; - -#if defined(RTS_DEBUG) - UnsignedInt now = TheGameLogic->getFrame(); - if( now == m_lastFrameMarkedDirty ) - { - //Do nothing. - } - else if( now == m_lastFrameMarkedDirty + 1 ) - { - m_consecutiveDirtyFrames++; - } - else - { - m_consecutiveDirtyFrames = 1; - } - m_lastFrameMarkedDirty = now; - - if( m_consecutiveDirtyFrames > 20 ) - { - 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.") ); - } - -#endif -} - -Player* ControlBar::getCurrentlyViewedPlayer() -{ - if (isObserverControlBarOn()) - return getObserverLookAtPlayer(); - - return ThePlayerList->getLocalPlayer(); -} - -Relationship ControlBar::getCurrentlyViewedPlayerRelationship(const Team* team) -{ - if (Player* player = getCurrentlyViewedPlayer()) - return player->getRelationship(team); - - return NEUTRAL; -} - -void ControlBar::populatePurchaseScience( Player* player ) -{ -// TheInGameUI->deselectAllDrawables(); - - const CommandSet *commandSet1; - const CommandSet *commandSet3; - const CommandSet *commandSet8; - Int i; - if(TheScriptEngine->isGameEnding()) - return; - // get command set - if(!player ||!player->getPlayerTemplate() || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1().isEmpty() || - player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3().isEmpty() || - player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8().isEmpty()) - return; - commandSet1 = findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING - commandSet3 = findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING - commandSet8 = findCommandSet(player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - if (m_sciencePurchaseWindowsRank1[i] != nullptr) - m_sciencePurchaseWindowsRank1[i]->winHide(TRUE); - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - if (m_sciencePurchaseWindowsRank3[i] != nullptr) - m_sciencePurchaseWindowsRank3[i]->winHide(TRUE); - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - if (m_sciencePurchaseWindowsRank8[i] != nullptr) - m_sciencePurchaseWindowsRank8[i]->winHide(TRUE); - - // if no command set match is found hide all the buttons - if( commandSet1 == nullptr || - commandSet3 == nullptr || - commandSet8 == nullptr ) - return; - - // populate the button with commands defined - const CommandButton *commandButton; - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - { - if (m_sciencePurchaseWindowsRank1[i] == nullptr) - continue; - - // get command button - commandButton = commandSet1->getCommandButton(i); - - // if button is not present, just hide the window - if( commandButton == nullptr || BitIsSet( commandButton->getOptions(), SCRIPT_ONLY ) ) - { - // hide window on interface - m_sciencePurchaseWindowsRank1[ i ]->winHide( TRUE ); - } - else - { - // make sure the window is not hidden - m_sciencePurchaseWindowsRank1[ i ]->winHide( FALSE ); - - // Disable by default - m_sciencePurchaseWindowsRank1[ i ]->winEnable( FALSE ); - - // populate the visible button with data from the command button - - setControlCommand( m_sciencePurchaseWindowsRank1[ i ], commandButton ); - if (!commandButton->getScienceVec().empty()) - { - ScienceType st = commandButton->getScienceVec()[ 0 ]; - - if( player->isScienceDisabled( st ) ) - { - //A script has deemed this science disabled. - m_sciencePurchaseWindowsRank1[ i ]->winEnable( FALSE ); - } - else if( player->isScienceHidden( st ) ) - { - //A script has deemed this science unavailable, thus hidden - m_sciencePurchaseWindowsRank1[ i ]->winHide( TRUE ); - } - else - { - //Handle normal game logic cases! - if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints()) - { - m_sciencePurchaseWindowsRank1[ i ]->winEnable( TRUE ); - } - if(player->hasScience(st)) - { - m_sciencePurchaseWindowsRank1[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR); - } - else - { - m_sciencePurchaseWindowsRank1[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR); - } - if(!TheScienceStore->playerHasRootPrereqsForScience(player, st)) - m_sciencePurchaseWindowsRank1[ i ]->winHide(TRUE); - } - } - } - - } - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - { - if (m_sciencePurchaseWindowsRank3[i] == nullptr) - continue; - - // get command button - commandButton = commandSet3->getCommandButton(i); - - // if button is not present, just hide the window - if( commandButton == nullptr || BitIsSet( commandButton->getOptions(), SCRIPT_ONLY ) ) - { - // hide window on interface - m_sciencePurchaseWindowsRank3[ i ]->winHide( TRUE ); - } - else - { - // make sure the window is not hidden - m_sciencePurchaseWindowsRank3[ i ]->winHide( FALSE ); - - // Disable by default - m_sciencePurchaseWindowsRank3[ i ]->winEnable( FALSE ); - - // populate the visible button with data from the command button - - setControlCommand( m_sciencePurchaseWindowsRank3[ i ], commandButton ); - ScienceType st = SCIENCE_INVALID; - ScienceVec sv = commandButton->getScienceVec(); - if (! sv.empty()) - { - st = sv[ 0 ]; - } - - if( player->isScienceDisabled( st ) ) - { - //A script has deemed this science disabled. - m_sciencePurchaseWindowsRank3[ i ]->winEnable( FALSE ); - } - else if( player->isScienceHidden( st ) ) - { - //A script has deemed this science unavailable, thus hidden - m_sciencePurchaseWindowsRank3[ i ]->winHide( TRUE ); - } - else - { - //Handle normal game logic cases! - if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints()) - { - m_sciencePurchaseWindowsRank3[ i ]->winEnable( TRUE ); - } - if(player->hasScience(st)) - { - m_sciencePurchaseWindowsRank3[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR); - } - else - { - m_sciencePurchaseWindowsRank3[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR); - } - if(!TheScienceStore->playerHasRootPrereqsForScience(player, st)) - m_sciencePurchaseWindowsRank3[ i ]->winHide(TRUE); - } - - } - - } - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - { - if (m_sciencePurchaseWindowsRank8[i] == nullptr) - continue; - - // get command button - commandButton = commandSet8->getCommandButton(i); - - // if button is not present, just hide the window - if( commandButton == nullptr || BitIsSet( commandButton->getOptions(), SCRIPT_ONLY ) ) - { - // hide window on interface - m_sciencePurchaseWindowsRank8[ i ]->winHide( TRUE ); - } - else - { - // make sure the window is not hidden - m_sciencePurchaseWindowsRank8[ i ]->winHide( FALSE ); - - // Disable by default - m_sciencePurchaseWindowsRank8[ i ]->winEnable( FALSE ); - - // populate the visible button with data from the command button - - setControlCommand( m_sciencePurchaseWindowsRank8[ i ], commandButton ); - ScienceType st = SCIENCE_INVALID; - st = commandButton->getScienceVec()[ 0 ]; - if( player->isScienceDisabled( st ) ) - { - //A script has deemed this science disabled. - m_sciencePurchaseWindowsRank8[ i ]->winEnable( FALSE ); - } - else if( player->isScienceHidden( st ) ) - { - //A script has deemed this science unavailable, thus hidden - m_sciencePurchaseWindowsRank8[ i ]->winHide( TRUE ); - } - else - { - //Handle normal game logic cases! - if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints()) - { - m_sciencePurchaseWindowsRank8[ i ]->winEnable( TRUE ); - } - if(player->hasScience(st)) - { - m_sciencePurchaseWindowsRank8[ i ]->winSetStatus(WIN_STATUS_ALWAYS_COLOR); - } - else - { - m_sciencePurchaseWindowsRank8[ i ]->winClearStatus(WIN_STATUS_ALWAYS_COLOR); - } - if(!TheScienceStore->playerHasRootPrereqsForScience(player, st)) - m_sciencePurchaseWindowsRank8[ i ]->winHide(TRUE); - } - - } - - } - - - GameWindow *win = nullptr; - UnicodeString tempUS; - win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextRankPointsAvailable" ) ); - if(win) - { - tempUS.format(L"%d", player->getSciencePurchasePoints()); - GadgetStaticTextSetText(win, tempUS); - } - -#if RTS_GENERALS - win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextLevel" ) ); - if(win) - { - tempUS.format(TheGameText->fetch("SCIENCE:Rank"), player->getRankLevel()); - GadgetStaticTextSetText(win, tempUS); - } -#else - // redundant to StaticTextTitle in the Zero Hour context -#endif - - win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:ProgressBarExperience" ) ); - if(win) - { - Int progress; - progress = ((player->getSkillPoints() - player->getSkillPointsLevelDown()) * 100) /(player->getSkillPointsLevelUp() - player->getSkillPointsLevelDown()); - GadgetProgressBarSetProgress(win, progress); - } - - win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:StaticTextTitle" ) ); - if(win) - { - AsciiString tempAs; - - tempAs.format("SCIENCE:Rank%d", player->getRankLevel()); - GadgetStaticTextSetText(win, TheGameText->fetch(tempAs)); - } - - - // - // to avoid a one frame delay where windows may become enabled/disabled, run the update - // at once to get it all in the correct state immediately - // - updateContextPurchaseScience(); -/* - // get the side select buttons - GameWindow* win = m_contextParent[ CP_PURCHASE_SCIENCE ]; - - Color color = GameMakeColor(255, 255, 255, 255); - - /// @todo srj -- evil hack testing code. do not imitate. - ScienceVec purchasable, potential; - TheScienceStore->getPurchasableSciences(player, purchasable, potential); - GadgetListBoxReset(win); - for (ScienceVec::const_iterator it = purchasable.begin(); it != purchasable.end(); ++it) - { - ScienceType st = *it; - UnicodeString u; - u.translate(TheScienceStore->getInternalNameForScience(st)); - GadgetListBoxAddEntryText(win, u, color, -1, -1); - } - for (ScienceVec::const_iterator it2 = potential.begin(); it2 != potential.end(); ++it2) - { - ScienceType st = *it2; - AsciiString foo = "(Not Yet)"; - foo.concat(TheScienceStore->getInternalNameForScience(st)); - UnicodeString u; - u.translate(foo); - GadgetListBoxAddEntryText(win, u, color, -1, -1); - } - GadgetListBoxAddEntryText(win, L"Cancel", color, -1, -1);*/ - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextPurchaseScience() -{ - GameWindow *win =nullptr; - Player *player = ThePlayerList->getLocalPlayer(); - win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:ProgressBarExperience" ) ); - if(win) - { - Int progress; - progress = ((player->getSkillPoints() - player->getSkillPointsLevelDown()) * 100) /(player->getSkillPointsLevelUp() - player->getSkillPointsLevelDown()); - GadgetProgressBarSetProgress(win, progress); - } - -// win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], TheNameKeyGenerator->nameToKey( "ControlBar.wnd:TextEntryGeneralName" ) ); -// if(win) -// { -// UnicodeString temp = GadgetTextEntryGetText(win); -// if(temp.compare(player->getGeneralName()) != 0) -// player->setGeneralName(temp); -// } -/* - /// @todo srj -- evil hack testing code. do not imitate. - Object *obj = m_currentSelectedDrawable->getObject(); - - if( obj == nullptr ) - return; - - // sanity - if( obj->isKindOf( KINDOF_COMMANDCENTER ) == FALSE ) - switchToContext( CB_CONTEXT_NONE, nullptr ); - - GameWindow* win = m_contextParent[ CP_PURCHASE_SCIENCE ]; - - Int selected; - GadgetListBoxGetSelected( win, &selected ); - if( selected != -1 ) - { - UnicodeString usci = GadgetListBoxGetText( win, selected, 0 ); - AsciiString sci; - sci.translate(usci); - ScienceType st = usci.getCharAt(0) == '(' ? SCIENCE_INVALID : TheScienceStore->getScienceFromInternalName(sci); - - if (st != SCIENCE_INVALID) - { - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PURCHASE_SCIENCE ); - msg->appendIntegerArgument( st ); - } - - switchToContext( CB_CONTEXT_NONE, nullptr ); - } -*/ - -} - -//------------------------------------------------------------------------------------------------- -/** parse command definition */ -//------------------------------------------------------------------------------------------------- -void CommandButton::parseCommand( INI* ini, void *instance, void *store, const void *userData ) -{ - const char *token = ini->getNextToken(); - Int i; - - for( i = 0; TheGuiCommandNames[ i ]; i++ ) - { - - if( stricmp( TheGuiCommandNames[ i ], token ) == 0 ) - { - - GUICommandType *command = (GUICommandType *)store; - *command = (GUICommandType)i; - return; - - } - - } - - // if we're here the command was not found - throw INI_INVALID_DATA; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -CommandButton::CommandButton() -{ - - m_command = GUI_COMMAND_NONE; - m_thingTemplate = nullptr; - m_upgradeTemplate = nullptr; - m_weaponSlot = PRIMARY_WEAPON; - m_maxShotsToFire = 0x7fffffff; // huge number - m_science.clear(); - m_specialPower = nullptr; - m_buttonImage = nullptr; - - //Code renderer handles these states now. - //m_disabledImage = nullptr; - //m_hiliteImage = nullptr; - //m_pushedImage = nullptr; - - m_flashCount = 0; - m_conflictingLabel.clear(); - m_cursorName.clear(); - m_descriptionLabel.clear(); - m_invalidCursorName.clear(); - m_name.clear(); - m_options = 0; - m_purchasedLabel.clear(); - m_textLabel.clear(); - m_window = nullptr; - m_commandButtonBorder = COMMAND_BUTTON_BORDER_NONE; - //m_prev = nullptr; - m_next = nullptr; - m_radiusCursor = RADIUSCURSOR_NONE; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -CommandButton::~CommandButton() -{ - -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isValidRelationshipTarget(Relationship r) const -{ - UnsignedInt mask = 0; - if (r == ENEMIES) mask |= NEED_TARGET_ENEMY_OBJECT; - else if (r == ALLIES) mask |= NEED_TARGET_ALLY_OBJECT; - else if (r == NEUTRAL) mask |= NEED_TARGET_NEUTRAL_OBJECT; - - return (m_options & mask) != 0; -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isValidObjectTarget(const Player* sourcePlayer, const Object* targetObj) const -{ - if (!sourcePlayer || !targetObj) - return false; - - Relationship r = sourcePlayer->getRelationship(targetObj->getTeam()); - - return isValidRelationshipTarget(r); -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isValidObjectTarget(const Object* sourceObj, const Object* targetObj) const -{ - if (!sourceObj || !targetObj) - return false; - - Relationship r = sourceObj->getRelationship(targetObj); - - return isValidRelationshipTarget(r); -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isValidToUseOn(const Object *sourceObj, const Object *targetObj, const Coord3D *targetLocation, CommandSourceType commandSource) const -{ - if (m_upgradeTemplate) { - // @todo: Make a const version of pui. We're not altering the production queue, so this const-cast - // is okay. - ProductionUpdateInterface *pui = const_cast(sourceObj)->getProductionUpdateInterface(); - if (pui) { - const ProductionEntry *pe = pui->firstProduction(); - while (pe) { - if (pe->getProductionUpgrade() != nullptr) - return false; - pe = pui->nextProduction(pe); - } - return sourceObj->affectedByUpgrade(m_upgradeTemplate) && !sourceObj->hasUpgrade(m_upgradeTemplate); - } - // No ProductionUpdateInterface means we can't do this. - return false; - } - - if( BitIsSet( m_options, COMMAND_OPTION_NEED_OBJECT_TARGET ) && !targetObj ) - { - return false; - } - - Coord3D pos; - if( targetLocation ) - { - pos.set( targetLocation ); - } - - if( BitIsSet( m_options, NEED_TARGET_POS ) && !targetLocation ) - { - if( targetObj ) - { - pos.set( targetObj->getPosition() ); - } - else - { - return false; - } - } - - if( BitIsSet( m_options, COMMAND_OPTION_NEED_OBJECT_TARGET ) ) - { - return TheActionManager->canDoSpecialPowerAtObject( sourceObj, targetObj, commandSource, m_specialPower, m_options, false ); - } - - if( BitIsSet( m_options, NEED_TARGET_POS ) ) - { - return TheActionManager->canDoSpecialPowerAtLocation( sourceObj, &pos, commandSource, m_specialPower, nullptr, m_options, false ); - } - - return TheActionManager->canDoSpecialPower( sourceObj, m_specialPower, commandSource, m_options, false ); -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isReady(const Object *sourceObj) const -{ - SpecialPowerModuleInterface *mod = sourceObj->getSpecialPowerModule( m_specialPower ); - if( mod && mod->getPercentReady() == 1.0f ) - return true; - - if (m_upgradeTemplate && sourceObj->affectedByUpgrade(m_upgradeTemplate) && !sourceObj->hasUpgrade(m_upgradeTemplate)) - return true; - - return false; -} - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isValidObjectTarget(const Drawable* source, const Drawable* target) const -{ - return isValidObjectTarget(source ? source->getObject() : nullptr, target ? target->getObject() : nullptr); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// CommandSet ///////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** These are the fields you can define in a command set, they correspond to physical - * buttons in the GUI */ -//------------------------------------------------------------------------------------------------- -const FieldParse CommandSet::m_commandSetFieldParseTable[] = -{ - - { "1", CommandSet::parseCommandButton, (void *)nullptr, offsetof( CommandSet, m_command ) }, - { "2", CommandSet::parseCommandButton, (void *)1, offsetof( CommandSet, m_command ) }, - { "3", CommandSet::parseCommandButton, (void *)2, offsetof( CommandSet, m_command ) }, - { "4", CommandSet::parseCommandButton, (void *)3, offsetof( CommandSet, m_command ) }, - { "5", CommandSet::parseCommandButton, (void *)4, offsetof( CommandSet, m_command ) }, - { "6", CommandSet::parseCommandButton, (void *)5, offsetof( CommandSet, m_command ) }, - { "7", CommandSet::parseCommandButton, (void *)6, offsetof( CommandSet, m_command ) }, - { "8", CommandSet::parseCommandButton, (void *)7, offsetof( CommandSet, m_command ) }, - { "9", CommandSet::parseCommandButton, (void *)8, offsetof( CommandSet, m_command ) }, - { "10", CommandSet::parseCommandButton, (void *)9, offsetof( CommandSet, m_command ) }, - { "11", CommandSet::parseCommandButton, (void *)10, offsetof( CommandSet, m_command ) }, - { "12", CommandSet::parseCommandButton, (void *)11, offsetof( CommandSet, m_command ) }, - { "13", CommandSet::parseCommandButton, (void *)12, offsetof( CommandSet, m_command ) }, - { "14", CommandSet::parseCommandButton, (void *)13, offsetof( CommandSet, m_command ) }, - { "15", CommandSet::parseCommandButton, (void *)14, offsetof( CommandSet, m_command ) }, - { "16", CommandSet::parseCommandButton, (void *)15, offsetof( CommandSet, m_command ) }, - { "17", CommandSet::parseCommandButton, (void *)16, offsetof( CommandSet, m_command ) }, - { "18", CommandSet::parseCommandButton, (void *)17, offsetof( CommandSet, m_command ) }, - { nullptr, nullptr, nullptr, 0 } - -}; - -//------------------------------------------------------------------------------------------------- -Bool CommandButton::isContextCommand() const -{ - return BitIsSet( m_options, CONTEXTMODE_COMMAND ); -} - -//------------------------------------------------------------------------------------------------- -// bleah. shouldn't be const, but is. sue me. (srj) -void CommandButton::copyImagesFrom( const CommandButton *button, Bool markUIDirtyIfChanged ) const -{ - if( m_buttonImage != button->getButtonImage() ) - { - m_buttonImage = button->getButtonImage(); - - //Code renderer handles these states now. - //m_disabledImage = button->getDisabledImage(); - //m_hiliteImage = button->getHiliteImage(); - //m_pushedImage = button->getPushedImage(); - - if( markUIDirtyIfChanged ) - { - TheControlBar->markUIDirty(); - } - } -} - -//------------------------------------------------------------------------------------------------- -// bleah. shouldn't be const, but is. sue me. (Kris) -snork! -void CommandButton::copyButtonTextFrom( const CommandButton *button, Bool shortcutButton, Bool markUIDirtyIfChanged ) const -{ - //This function was added to change the strings when you upgrade from a DaisyCutter to a MOAB. All other special - //powers are the same. - Bool change = FALSE; - if( shortcutButton ) - { - //Not the best code, but conflicting label means shortcut label (most won't have any string specified). - if( button->getConflictingLabel().isNotEmpty() && m_textLabel.compare( button->getConflictingLabel() ) ) - { - m_textLabel = button->getConflictingLabel(); - change = TRUE; - } - } - else - { - //Copy the text from the purchase science button if it exists (most won't). - if( button->getTextLabel().isNotEmpty() && m_textLabel.compare( button->getTextLabel() ) ) - { - m_textLabel = button->getTextLabel(); - change = TRUE; - } - } - if( button->getDescriptionLabel().isNotEmpty() && m_descriptionLabel.compare( button->getDescriptionLabel() ) ) - { - m_descriptionLabel = button->getDescriptionLabel(); - change = TRUE; - } - if( markUIDirtyIfChanged && change ) - { - TheControlBar->markUIDirty(); - } -} - -//------------------------------------------------------------------------------------------------- -/** Parse a single command button definition */ -//------------------------------------------------------------------------------------------------- -void CommandSet::parseCommandButton( INI* ini, void *instance, void *store, const void *userData ) -{ - const char *token = ini->getNextToken(); - - // get find the command button from this name - const CommandButton *commandButton = TheControlBar->findCommandButton( AsciiString( token ) ); - if( commandButton == nullptr ) - { - - DEBUG_CRASH(( "[LINE: %d - FILE: '%s'] Unknown command '%s' found in command set", - ini->getLineNum(), ini->getFilename().str(), token )); - throw INI_INVALID_DATA; - - } - - // get the index to store the command at, and the command array itself - const CommandButton **buttonArray = (const CommandButton **)store; - Int buttonIndex = (Int)userData; - - // sanity - DEBUG_ASSERTCRASH( buttonIndex < MAX_COMMANDS_PER_SET, ("parseCommandButton: button index '%d' out of range", - buttonIndex) ); - - // save it - buttonArray[ buttonIndex ] = commandButton; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -CommandSet::CommandSet(const AsciiString& name) : - m_name(name), - m_next(nullptr) -{ - for( Int i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - m_command[ i ] = nullptr; -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -const CommandButton* CommandSet::getCommandButton(Int i) const -{ - const CommandButton* button; - // Check for TheGameLogic == null, cause it is in Worldbuilder, and wb gets command bar info. jba. - if (TheGameLogic && TheGameLogic->findControlBarOverride(m_name, i, button)) - return button; - - return m_command[i]; -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void CommandSet::friend_addToList(CommandSet** listHead) -{ - m_next = *listHead; - *listHead = this; -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -CommandSet::~CommandSet() -{ - -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// ControlBar ///////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -ControlBar::ControlBar() -{ - Int i; - m_commandButtons = nullptr; - m_commandSets = nullptr; - m_controlBarSchemeManager = nullptr; - m_isObserverCommandBar = FALSE; - m_observerLookAtPlayer = nullptr; - m_observedPlayer = nullptr; - m_buildToolTipLayout = nullptr; - m_showBuildToolTipLayout = FALSE; - - m_animateDownWin1Pos.x = m_animateDownWin1Pos.y = 0; - m_animateDownWin1Size.x = m_animateDownWin1Size.y = 0; - m_animateDownWin2Pos.x = m_animateDownWin2Pos.y = 0; - m_animateDownWin2Size.x = m_animateDownWin2Size.y = 0; - - m_animateDownWindow = nullptr; - m_animTime = 0; - - for( i = 0; i < MAX_COMMANDS_PER_SET; i++) - { - m_commonCommands[i] = nullptr; - } - - m_currContext = CB_CONTEXT_NONE; - m_defaultControlBarPosition.x = m_defaultControlBarPosition.y = 0; - m_genStarFlash = FALSE; - m_genStarOff = nullptr; - m_genStarOn = nullptr; - m_UIDirty = FALSE; - // m_controlBarResizer = nullptr; - m_buildUpClockColor = GameMakeColor(0,0,0,100); - m_commandBarBorderColor = GameMakeColor(0,0,0,100); - for( i = 0; i < NUM_CONTEXT_PARENTS; i++ ) - m_contextParent[ i ] = nullptr; - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - m_commandWindows[ i ] = nullptr; - // removed from multiplayer branch - //m_commandMarkers[ i ] = nullptr; - } - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - m_sciencePurchaseWindowsRank1[i] = nullptr; - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - m_sciencePurchaseWindowsRank3[i] = nullptr; - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - m_sciencePurchaseWindowsRank8[i] = nullptr; - - for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ ) - { - m_specialPowerShortcutButtons[i] = nullptr; - m_specialPowerShortcutButtonParents[i] = nullptr; - } - - m_specialPowerShortcutParent = nullptr; - m_specialPowerLayout = nullptr; - m_scienceLayout = nullptr; - m_rightHUDWindow = nullptr; - m_rightHUDCameoWindow = nullptr; - for( i = 0; i < MAX_RIGHT_HUD_UPGRADE_CAMEOS; i++ ) - m_rightHUDUpgradeCameos[i]; - m_rightHUDUnitSelectParent = nullptr; - m_communicatorButton = nullptr; - m_currentSelectedDrawable = nullptr; - m_currContext = CB_CONTEXT_NONE; - m_rallyPointDrawableID = INVALID_DRAWABLE_ID; - m_displayedConstructPercent = -1.0f; - m_displayedOCLTimerSeconds = 0; - m_displayedQueueCount = 0; - resetBuildQueueData(); - resetContainData(); - m_lastRecordedInventoryCount = 0; - - m_videoManager = nullptr; - m_animateWindowManager = nullptr; - m_generalsScreenAnimate = nullptr; - m_animateWindowManagerForGenShortcuts = nullptr; - m_flash = FALSE; - m_toggleButtonUpIn = nullptr; - m_toggleButtonUpOn = nullptr; - m_toggleButtonUpPushed = nullptr; - m_toggleButtonDownIn = nullptr; - m_toggleButtonDownOn = nullptr; - m_toggleButtonDownPushed = nullptr; - - m_generalButtonEnable = nullptr; - m_generalButtonHighlight = nullptr; - m_genArrow = nullptr; - m_sideSelectAnimateDown = FALSE; - updateCommandBarBorderColors(GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED,GAME_COLOR_UNDEFINED); - - m_radarAttackGlowOn = FALSE; - m_remainingRadarAttackGlowFrames = 0; - m_radarAttackGlowWindow = nullptr; - -#if defined(RTS_DEBUG) - m_lastFrameMarkedDirty = 0; - m_consecutiveDirtyFrames = 0; -#endif - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -ControlBar::~ControlBar() -{ - - if(m_scienceLayout) - { - m_scienceLayout->destroyWindows(); - deleteInstance(m_scienceLayout); - m_scienceLayout = nullptr; - } - m_genArrow = nullptr; - - delete m_videoManager; - m_videoManager = nullptr; - - delete m_animateWindowManagerForGenShortcuts; - m_animateWindowManagerForGenShortcuts = nullptr; - - delete m_animateWindowManager; - m_animateWindowManager = nullptr; - - delete m_generalsScreenAnimate; - m_generalsScreenAnimate = nullptr; - - delete m_controlBarSchemeManager; - m_controlBarSchemeManager = nullptr; - -// delete m_controlBarResizer; -// m_controlBarResizer = nullptr; - - // destroy all the command set definitions - CommandSet *set; - while( m_commandSets ) - { - set = m_commandSets->friend_getNext(); - deleteInstance(m_commandSets); - m_commandSets = set; - - } - - // destroy all our command button definitions - CommandButton *button; - while( m_commandButtons ) - { - button = m_commandButtons->friend_getNext(); - deleteInstance(m_commandButtons); - m_commandButtons = button; - - } - if(m_buildToolTipLayout) - { - m_buildToolTipLayout->destroyWindows(); - deleteInstance(m_buildToolTipLayout); - m_buildToolTipLayout = nullptr; - } - - if(m_specialPowerLayout) - { - m_specialPowerLayout->destroyWindows(); - deleteInstance(m_specialPowerLayout); - m_specialPowerLayout = nullptr; - } - - m_radarAttackGlowWindow = nullptr; - - if (m_rightHUDCameoWindow && m_rightHUDCameoWindow->winGetUserData()) - { - delete m_rightHUDCameoWindow->winGetUserData(); - m_rightHUDCameoWindow->winSetUserData(nullptr); - } - -} -void ControlBarPopupDescriptionUpdateFunc( WindowLayout *layout, void *param ); - -//------------------------------------------------------------------------------------------------- -/** Initialize the control bar, this is our interface to the context sensitive GUI */ -//------------------------------------------------------------------------------------------------- -void ControlBar::init() -{ - INI ini; - m_sideSelectAnimateDown = FALSE; - // load the command buttons - ini.loadFileDirectory( "Data\\INI\\Default\\CommandButton", INI_LOAD_OVERWRITE, nullptr ); - ini.loadFileDirectory( "Data\\INI\\CommandButton", INI_LOAD_OVERWRITE, nullptr ); - - // load the command sets - ini.loadFileDirectory( "Data\\INI\\CommandSet", INI_LOAD_OVERWRITE, nullptr ); - - // post process step after loading the command buttons and command sets - postProcessCommands(); - - // Init the scheme manager, this will call its own INI init function. - m_controlBarSchemeManager = NEW ControlBarSchemeManager; - m_controlBarSchemeManager->init(); - - //Added this check because the builder uses the ControlBar, but doesn't care about - //the GUI. - if( TheWindowManager ) - { - // - // the control bar has several windows that make up our context sensitive interface, we - // want those parent windows so that we can easily hide and show them to make the - // interface context sensitive - // - NameKeyType id; - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ControlBarParent" ); - m_contextParent[ CP_MASTER ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - m_contextParent[ CP_MASTER ]->winGetPosition(&m_defaultControlBarPosition.x, &m_defaultControlBarPosition.y); - - m_scienceLayout = TheWindowManager->winCreateLayout("GeneralsExpPoints.wnd"); - m_scienceLayout->hide(TRUE); - id = TheNameKeyGenerator->nameToKey( "GeneralsExpPoints.wnd:GenExpParent" ); - - m_contextParent[ CP_PURCHASE_SCIENCE ] = TheWindowManager->winGetWindowFromId( nullptr, id );//m_scienceLayout->getFirstWindow(); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:UnderConstructionWindow" ); - m_contextParent[ CP_UNDER_CONSTRUCTION ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerWindow" ); - m_contextParent[ CP_OCL_TIMER ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BeaconWindow" ); - m_contextParent[ CP_BEACON ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:CommandWindow" ); - m_contextParent[ CP_COMMAND ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ProductionQueueWindow" ); - m_contextParent[ CP_BUILD_QUEUE ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ObserverPlayerListWindow" ); - m_contextParent[ CP_OBSERVER_LIST ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ObserverPlayerInfoWindow" ); - m_contextParent[ CP_OBSERVER_INFO ] = TheWindowManager->winGetWindowFromId( nullptr, id ); - - - // get the command windows and save for easy access later - Int i; - ICoord2D commandSize, commandPos; - AsciiString windowName; - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - - windowName.format( "ControlBar.wnd:ButtonCommand%02d", i + 1 ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_commandWindows[ i ] = - TheWindowManager->winGetWindowFromId( m_contextParent[ CP_COMMAND ], id ); - if (m_commandWindows[ i ]) - { - m_commandWindows[ i ]->winGetPosition(&commandPos.x, &commandPos.y); - m_commandWindows[ i ]->winGetSize(&commandSize.x, &commandSize.y); - m_commandWindows[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - } - - // removed from multiplayer branch -// windowName.format( "ControlBar.wnd:CommandMarker%02d", i + 1 ); -// id = TheNameKeyGenerator->nameToKey( windowName.str() ); -// m_commandMarkers[ i ] = -// TheWindowManager->winGetWindowFromId( m_contextParent[ CP_COMMAND ], id ); -// // set the size and position to make sure their in the same place as the buttons. -// m_commandMarkers[i]->winSetPosition(commandPos.x -2, commandPos.y - 2); -// m_commandMarkers[i]->winSetSize(commandSize.x + 2, commandSize.y + 2); - - - - } - - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - { - windowName.format( "GeneralsExpPoints.wnd:ButtonRank1Number%d", i ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_sciencePurchaseWindowsRank1[ i ] = - TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id ); - if (m_sciencePurchaseWindowsRank1[ i ] != nullptr) - m_sciencePurchaseWindowsRank1[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - } - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - { - windowName.format( "GeneralsExpPoints.wnd:ButtonRank3Number%d", i ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_sciencePurchaseWindowsRank3[ i ] = - TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id ); - if (m_sciencePurchaseWindowsRank3[ i ] != nullptr) - m_sciencePurchaseWindowsRank3[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - } - - for( i = 0; i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - { - windowName.format( "GeneralsExpPoints.wnd:ButtonRank8Number%d", i ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_sciencePurchaseWindowsRank8[ i ] = - TheWindowManager->winGetWindowFromId( m_contextParent[ CP_PURCHASE_SCIENCE ], id ); - if (m_sciencePurchaseWindowsRank8[ i ] != nullptr) - m_sciencePurchaseWindowsRank8[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - } - - // keep a pointer to the window making up the right HUD display - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:RightHUD" ); - m_rightHUDWindow = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:WinUnitSelected" ); - m_rightHUDUnitSelectParent = TheWindowManager->winGetWindowFromId( nullptr, id ); - - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:CameoWindow" ); - m_rightHUDCameoWindow = TheWindowManager->winGetWindowFromId( nullptr, id ); - for( i = 0; i < MAX_RIGHT_HUD_UPGRADE_CAMEOS; i++ ) - { - windowName.format( "ControlBar.wnd:UnitUpgrade%d", i+1 ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_rightHUDUpgradeCameos[ i ] = - TheWindowManager->winGetWindowFromId( m_rightHUDWindow, id ); - m_rightHUDUpgradeCameos[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - } - -// m_transitionHandler = NEW GameWindowTransitionsHandler; -// m_transitionHandler->load(); -// m_transitionHandler->init(); - - // don't forget about the communicator button CCB - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PopupCommunicator" ); - m_communicatorButton = TheWindowManager->winGetWindowFromId( nullptr, id ); - setControlCommand(m_communicatorButton, findCommandButton("NonCommand_Communicator") ); - m_communicatorButton->winSetTooltipFunc(commandButtonTooltip); - - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonOptions")); - if(win) - { - setControlCommand(win, findCommandButton("NonCommand_Options") ); - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonIdleWorker")); - if(win) - { - setControlCommand(win, findCommandButton("NonCommand_IdleWorker") ); - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonPlaceBeacon")); - if(win) - { - setControlCommand(win, findCommandButton("NonCommand_Beacon") ); - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonGeneral")); - if(win) - { - setControlCommand(win, findCommandButton("NonCommand_GeneralsExperience") ); - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonLarge")); - if(win) - { - setControlCommand(win, findCommandButton("NonCommand_UpDown") ); - win->winSetTooltipFunc(commandButtonTooltip); - } - - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:PowerWindow")); - if(win) - { - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey("ControlBar.wnd:MoneyDisplay")); - if(win) - { - win->winSetTooltipFunc(commandButtonTooltip); - } - win = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:GeneralsExp")); - if(win) - { - win->winSetTooltipFunc(commandButtonTooltip); - } - - m_radarAttackGlowWindow = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinUAttack")); - - - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" )); - win->winGetScreenPosition(&m_controlBarForegroundMarkerPos.x, &m_controlBarForegroundMarkerPos.y); - win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" )); - win->winGetScreenPosition(&m_controlBarBackgroundMarkerPos.x,&m_controlBarBackgroundMarkerPos.y); - - if(!m_videoManager) - m_videoManager = NEW WindowVideoManager; - if(!m_animateWindowManager) - m_animateWindowManager = NEW AnimateWindowManager; - if(!m_generalsScreenAnimate) - m_generalsScreenAnimate = NEW AnimateWindowManager; - if(!m_animateWindowManagerForGenShortcuts) - m_animateWindowManagerForGenShortcuts = NEW AnimateWindowManager; - m_buildToolTipLayout = TheWindowManager->winCreateLayout( "ControlBarPopupDescription.wnd" ); - if(m_buildToolTipLayout) - { - m_buildToolTipLayout->hide(TRUE); - m_buildToolTipLayout->setUpdate(ControlBarPopupDescriptionUpdateFunc); - } - - m_genStarOn = TheMappedImageCollection ? (Image *)TheMappedImageCollection->findImageByName("BarButtonGenStarON") : nullptr; - m_genStarOff = TheMappedImageCollection ? (Image *)TheMappedImageCollection->findImageByName("BarButtonGenStarOFF") : nullptr; - m_genStarFlash = TRUE; - m_lastFlashedAtPointValue = -1; - - m_rankVeteranIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron1L" ) : nullptr; - m_rankEliteIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron2L" ) : nullptr; - m_rankHeroicIcon = TheMappedImageCollection ? TheMappedImageCollection->findImageByName( "SSChevron3L" ) : nullptr; - - -// if(!m_controlBarResizer) -// m_controlBarResizer = NEW ControlBarResizer; -// m_controlBarResizer->init(); - - - - // Initialize the Observer controls - initObserverControls(); - - // by default switch to the none context - switchToContext( CB_CONTEXT_NONE, nullptr ); - } - -} - -//------------------------------------------------------------------------------------------------- -/** Reset the context sensitive control bar GUI */ -//------------------------------------------------------------------------------------------------- -void ControlBar::reset() -{ - hideSpecialPowerShortcut(); - // do not destroy the rally drawable, it will get destroyed with everything else during a reset - m_rallyPointDrawableID = INVALID_DRAWABLE_ID; - if(m_radarAttackGlowWindow) - m_radarAttackGlowWindow->winEnable(TRUE); - m_radarAttackGlowOn = FALSE; - m_remainingRadarAttackGlowFrames = 0; - - m_displayedConstructPercent = -1.0f; - m_displayedOCLTimerSeconds = 0; - - m_isObserverCommandBar = FALSE; // reset us to use a normal command bar - m_observerLookAtPlayer = nullptr; - m_observedPlayer = nullptr; - - if(m_buildToolTipLayout) - m_buildToolTipLayout->hide(TRUE); - m_showBuildToolTipLayout = FALSE; - - if(m_animateWindowManager) - m_animateWindowManager->reset(); - - if(m_animateWindowManagerForGenShortcuts) - m_animateWindowManagerForGenShortcuts->reset(); - - if(m_generalsScreenAnimate) - m_generalsScreenAnimate->reset(); - - - if(m_videoManager) - m_videoManager->reset(); - - // go back to default context - switchToContext( CB_CONTEXT_NONE, nullptr ); - m_sideSelectAnimateDown = FALSE; - if(m_animateDownWindow) - { - TheWindowManager->winDestroy( m_animateDownWindow ); - m_animateDownWindow = nullptr; - } - - // Remove any overridden sets. - CommandSet *set, *nextSet; - set = m_commandSets; - while (set) { - Bool possibleAdjustment = FALSE; - nextSet = set->friend_getNext(); - if (set == m_commandSets) { - possibleAdjustment = TRUE; - } - - Overridable *stillValid = set->deleteOverrides(); - if (stillValid == nullptr && possibleAdjustment) { - m_commandSets = nextSet; - } - - set = nextSet; - } - - // Remove any overridden command buttons. - CommandButton *button, *nextButton; - button = m_commandButtons; - while (button) { - Bool possibleAdjustment = FALSE; - nextButton = button->friend_getNext(); - if (button == m_commandButtons) { - possibleAdjustment = TRUE; - } - - Overridable *stillValid = button->deleteOverrides(); - if (stillValid == nullptr && possibleAdjustment) { - m_commandButtons = nextButton; - } - - button = nextButton; - } - if(TheTransitionHandler) - TheTransitionHandler->remove("ControlBarArrow"); - m_genArrow = nullptr; - - m_lastFlashedAtPointValue = -1; - m_genStarFlash = TRUE; -} - -//------------------------------------------------------------------------------------------------- -/** Update phase, we can track if our selected object is destroyed, update button - * percentages, status, enabled status etc */ -//------------------------------------------------------------------------------------------------- -void ControlBar::update() -{ - if (TheGlobalData->m_headless) - return; - getStarImage(); - updateRadarAttackGlow(); - if(m_controlBarSchemeManager) - m_controlBarSchemeManager->update(); - - // Update our video manager - if( m_videoManager ) - m_videoManager->update(); - - if (m_animateWindowManager) - m_animateWindowManager->update(); - - if (m_animateWindowManager) - { - if (m_animateWindowManager->isFinished() && m_animateWindowManager->isReversed()) - { - Int id = (Int)TheNameKeyGenerator->nameToKey("ControlBar.wnd:ControlBarParent"); - GameWindow *window = TheWindowManager->winGetWindowFromId(nullptr, id); - if (window && !window->winIsHidden()) - window->winHide(TRUE); - } - } - - if(m_animateWindowManagerForGenShortcuts) - m_animateWindowManagerForGenShortcuts->update(); - if (m_animateWindowManagerForGenShortcuts && m_specialPowerShortcutParent) - { - if (m_animateWindowManagerForGenShortcuts->isFinished() && m_animateWindowManagerForGenShortcuts->isReversed()) - { - if (m_specialPowerShortcutParent && !m_specialPowerShortcutParent->winIsHidden()) - m_specialPowerShortcutParent->winHide(TRUE); - } - } - - - - if( !m_buildToolTipLayout->isHidden()) - { - m_buildToolTipLayout->runUpdate(); - m_showBuildToolTipLayout = FALSE; - } -/* - else if( m_buildToolTipLayout ) - { - hideBuildTooltipLayout(); - }*/ - - updateSpecialPowerShortcut(); - // if we're an observer, don't do the complete update - if( m_isObserverCommandBar) - { - if((TheGameLogic->getFrame() % (LOGICFRAMES_PER_SECOND/2)) == 0) - populateObserverInfoWindow(); - - Drawable *drawToEvaluateFor = nullptr; - if( TheInGameUI->getSelectCount() > 1 ) - { - // Attempt to isolate a Drawable here to evaluate - // The need arises when selected is an AngryMob, - // whose selection actually consists of varied units - // but is represented in the UI as a single unit, - // so we must isolate and evaluate only the Nexus - drawToEvaluateFor = TheGameClient->findDrawableByID( TheInGameUI->getSoloNexusSelectedDrawableID() ) ; - } - else // get the first and only drawble in the selection list - // TheSuperHackers @fix Mauller 07/04/2025 The first access to this can return an empty list - if (!TheInGameUI->getAllSelectedDrawables()->empty()) { - drawToEvaluateFor = TheInGameUI->getAllSelectedDrawables()->front(); - } - - Object* obj = drawToEvaluateFor ? drawToEvaluateFor->getObject() : nullptr; - setPortraitByObject(obj); - - const Coord3D* exitPosition = nullptr; - if (obj && obj->getControllingPlayer() == getCurrentlyViewedPlayer() && obj->getObjectExitInterface()) - exitPosition = obj->getObjectExitInterface()->getRallyPoint(); - - showRallyPoint(exitPosition); - return; - } - - - // check flashing - if( m_flash ) - { - // go through all the command buttons to see which one needs to flash - for( Int i = 0; i < MAX_COMMANDS_PER_SET; ++i ) - { - GameWindow *button = m_commandWindows[ i ]; - if( button != nullptr) - { - const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(button); - if( commandButton != nullptr ) - { - if( commandButton->getFlashCount() > 0 && TheGameClient->getFrame() % 10 == 0 ) - { - if( commandButton->getFlashCount() % 2 == 0 ) - { - commandButton->setFlashCount(commandButton->getFlashCount() - 1); - button->winSetStatus( WIN_STATUS_FLASHING ); - } - else - { - commandButton->setFlashCount(commandButton->getFlashCount() - 1); - button->winClearStatus( WIN_STATUS_FLASHING ); - if( commandButton->getFlashCount() == 0 ) - { - setFlash( FALSE ); - } - } - } - } - } - } - } - - if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden()) - updateContextPurchaseScience(); - - // - // first, if the UI is dirty repopulate the UI with what the user should see for all the - // selected drawables - // - if( m_UIDirty ) - { - evaluateContextUI(); - populateSpecialPowerShortcut(ThePlayerList->getLocalPlayer()); - // if we have a build tooltip layout, update it with the new data. - repopulateBuildTooltipLayout(); - } - - // enable/disable the beacon button depending on if the max has been reached - if (ThePlayerList && ThePlayerList->getLocalPlayer() && ThePlayerList->getLocalPlayer()->getPlayerTemplate()) - { - Int count; - const ThingTemplate *thing = TheThingFactory->findTemplate( ThePlayerList->getLocalPlayer()->getPlayerTemplate()->getBeaconTemplate() ); - ThePlayerList->getLocalPlayer()->countObjectsByThingTemplate( 1, &thing, false, &count ); - static NameKeyType beaconPlacementButtonID = NAMEKEY("ControlBar.wnd:ButtonPlaceBeacon"); - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr, beaconPlacementButtonID); - if (win) - { - if (count < TheMultiplayerSettings->getMaxBeaconsPerPlayer()) - { - win->winEnable(TRUE); - } - else - { - win->winEnable(FALSE); - } - } - } - - // - // most control bar contexts have one selected thing that we switch on and update - // based on if that thing changed in some way ... the exception is when multi selected - // - if( m_currContext == CB_CONTEXT_MULTI_SELECT ) - { - - updateContextMultiSelect(); - return; - - } - - // if nothing is selected get out of here except if we're in the Purchase science context... that requires - // us to not have anything selected - if( m_currentSelectedDrawable == nullptr ) - { - - // we better be in the default none context - DEBUG_ASSERTCRASH( m_currContext == CB_CONTEXT_NONE, ("ControlBar::update no selection, but not we're not showing the default NONE context") ); - return; - - } - - - - // if our selected drawable has no object get out of here - Object *obj = nullptr; - if(m_currentSelectedDrawable) - obj = m_currentSelectedDrawable->getObject(); - if( obj == nullptr ) - { - - switchToContext( CB_CONTEXT_NONE, nullptr ); - return; - - } - - switch( m_currContext ) - { - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_NONE: - break; - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_COMMAND: - updateContextCommand(); - break; - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_STRUCTURE_INVENTORY: - updateContextStructureInventory(); - break; - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_BEACON: - updateContextBeacon(); - break; - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_UNDER_CONSTRUCTION: - updateContextUnderConstruction(); - break; - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_OCL_TIMER: - updateContextOCLTimer(); - break; - - } - - - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::onDrawableSelected( Drawable *draw ) -{ - - // set a dirty flag so next time we update we can reconstruct the UI - markUIDirty(); - - // cancel any pending GUI commands - TheInGameUI->setGUICommand( nullptr ); - - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::onDrawableDeselected( Drawable *draw ) -{ - - // set a dirty flag so next time we update we can reconstruct the UI - markUIDirty(); - - if (TheInGameUI->getSelectCount() == 0) - { - // we just deselected everything - cancel any pending GUI commands - TheInGameUI->setGUICommand( nullptr ); - } - - // - // always when becoming unselected should we remove any build placement icons because if - // we have some and are in the middle of a build process, it must obviously be over now - // because we are no longer selecting the dozer or worker - // - TheInGameUI->placeBuildAvailable( nullptr, nullptr ); - -} - -//------------------------------------------------------------------------------------------------- - -const Image *ControlBar::getStarImage() -{ - if(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints() || ThePlayerList->getLocalPlayer()->getSciencePurchasePoints() <= 0) - m_genStarFlash = FALSE; - else - m_lastFlashedAtPointValue = ThePlayerList->getLocalPlayer()->getSciencePurchasePoints(); - - GameWindow *win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonGeneral" ) ); - if(!win) - return nullptr; - if(!m_genStarFlash) - { - GadgetButtonSetEnabledImage(win, m_generalButtonEnable); - return nullptr; - } - - if(TheGameLogic->getFrame()% LOGICFRAMES_PER_SECOND > LOGICFRAMES_PER_SECOND/2) - { - GadgetButtonSetEnabledImage(win, m_generalButtonHighlight); - return nullptr; - } - - GadgetButtonSetEnabledImage(win, m_generalButtonEnable); - - return nullptr; - -} - - -//------------------------------------------------------------------------------------------------- -void ControlBar::onPlayerRankChanged(const Player *p) -{ - if (!p->isLocalPlayer()) - return; - - if(!(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints())) - { - if(TheTransitionHandler && TheInGameUI->getInputEnabled()) - TheTransitionHandler->setGroup("ControlBarArrow"); - } -// populateSpecialPowerShortcut((Player *)p); - m_genStarFlash = TRUE; - /// @todo implement me - markUIDirty(); -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::onPlayerSciencePurchasePointsChanged(const Player *p) -{ - if (!p->isLocalPlayer()) - return; - if(!(m_lastFlashedAtPointValue > ThePlayerList->getLocalPlayer()->getSciencePurchasePoints())) - { - if(TheTransitionHandler && TheInGameUI->getInputEnabled()) - TheTransitionHandler->setGroup("ControlBarArrow"); - } -// populateSpecialPowerShortcut((Player *)p); - m_genStarFlash = TRUE; - /// @todo implement me - markUIDirty(); -} - -//------------------------------------------------------------------------------------------------- -/** Given the drawables that we have selected into our context sensitive UI, evaluate - * and perform all UI manipulations to make the GUI show to the user what we want them - * to see */ -//------------------------------------------------------------------------------------------------- -void ControlBar::evaluateContextUI() -{ - - // - // the UI has been "evaluated" and is now displaying the most current and correct - // information to the player - // - m_UIDirty = FALSE; - - // if our purchase science window is up, we will want to update it by repopulating it. - if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden()) - showPurchaseScience(); - - // erase any current state of the GUI by switching out to the empty context - switchToContext( CB_CONTEXT_NONE, nullptr ); - - // sanity, nothing selected - if( TheInGameUI->getSelectCount() == 0 ) - return; - - // get the list of drawable IDs from the in game UI - const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables(); - - // sanity - if( selectedDrawables->empty() == TRUE ) - return; - - //Make sure the selected objects are in fact, controllable! If not, then - //we don't show any GUI commands for them!!! - //This is used when we select enemy objects or objects on another team. - //@todo we may want to show their portrait - if( !TheInGameUI->areSelectedObjectsControllable() ) - { - //Also make sure the unit isn't a garrisonable neutral civ team building! - Drawable *draw = selectedDrawables->front(); - - //sanity - if( !draw ) - { - return; - } - Object *obj = draw->getObject(); - if( !obj ) - { - return; - } - - if (obj->getControllingPlayer() - && obj->getControllingPlayer()->getPlayerTemplate() - && obj->getControllingPlayer()->getPlayerTemplate()->getBeaconTemplate().compare(obj->getTemplate()->getName()) == 0 - ) - { - switchToContext( CB_CONTEXT_BEACON, draw ); - } - else - { - switchToContext( CB_CONTEXT_NONE, draw ); - } - - //Check for a contain interface and a enemy relationship and reject that! - ContainModuleInterface *contain = obj->getContain(); - if( contain && contain->getContainMax() > 0 ) - { - - const Player *otherPlayer = contain->getApparentControllingPlayer(ThePlayerList->getLocalPlayer()); - if (!otherPlayer) - otherPlayer = obj->getControllingPlayer(); - Player *player = ThePlayerList->getLocalPlayer(); - - if( !player || !otherPlayer ) - { - //Sanity. - return; - } - Relationship relation = player->getRelationship( otherPlayer->getDefaultTeam() ); - - //Note: All following checks already account for the fact that this object - //isn't ours. - - //The only case we can actually see a non-controlled controlbar is a neutral garrisonable structure. - if( !contain->isGarrisonable() || relation != NEUTRAL ) - { - //Can't peek inside enemy/allied containers period! - return; - } - } - else - { - return; - } - } - - // - // when we have multiple things selected, we will only display the common commands - // in the center command bar that can be displayed with multi-units selected - // - - - Drawable *drawToEvaluateFor = nullptr; - Bool multiSelect = FALSE; - - - if( TheInGameUI->getSelectCount() > 1 ) - { - // Attempt to isolate a Drawable here to evaluate - // The need arises when selected is an AngryMob, - // whose selection actually consists of varied units - // but is represented in the UI as a single unit, - // so we must isolate and evaluate only the Nexus - drawToEvaluateFor = TheGameClient->findDrawableByID( TheInGameUI->getSoloNexusSelectedDrawableID() ) ; - multiSelect = ( drawToEvaluateFor == nullptr ); - - } - else // get the first and only drawble in the selection list - drawToEvaluateFor = selectedDrawables->front(); - - - - if( multiSelect ) - { - switchToContext( CB_CONTEXT_MULTI_SELECT, nullptr ); - } - else if ( drawToEvaluateFor )// either we have exactly one drawable, or we have isolated one to evaluate for... - { - - // get the first and only drawable in the selection list - //Drawable *draw = selectedDrawables->front(); - - // sanity - //if( draw == nullptr ) - // return; - - // get object - Object *obj = drawToEvaluateFor->getObject(); - if( obj == nullptr ) - return; - - // we show no interface for objects being sold - if( obj->getStatusBits().test( OBJECT_STATUS_SOLD ) ) - return; - - static const NameKeyType key_OCLUpdate = NAMEKEY( "OCLUpdate" ); - OCLUpdate *update = (OCLUpdate*)obj->findUpdateModule( key_OCLUpdate ); - - // - // a command center is context sensitive itself, if a side has *NOT* been chosen we display - // the side select interface for command centers only, but note how under construction is - // more important than anything - // - Bool contextSelected = FALSE; - if( obj->getStatusBits().test( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) - { - - switchToContext( CB_CONTEXT_UNDER_CONSTRUCTION, drawToEvaluateFor ); - contextSelected = TRUE; - - } - - // check for a regular switch to the appropriate context - if( contextSelected == FALSE ) - { - ContainModuleInterface *cmi = obj->getContain(); - - if( cmi && cmi->isGarrisonable() && obj->getCommandSetString().isEmpty() ) - { - //Kris: This is a convenient section to graft an inventory commandset for - //garrisoned troops. However, we only want to use this if we DON'T have - //a commandset defined. If we do, then trust that the commandset will - //handle it! - - Player *localPlayer = ThePlayerList->getLocalPlayer(); - Relationship relationship; - - // we cannot select objects that are controlled by our enemies - relationship = localPlayer->getRelationship( obj->getTeam() ); - if( obj->isLocallyControlled() == TRUE || relationship == NEUTRAL ) - switchToContext( CB_CONTEXT_STRUCTURE_INVENTORY, drawToEvaluateFor ); - - } - else if( update ) - { - switchToContext( CB_CONTEXT_OCL_TIMER, drawToEvaluateFor ); - } - else if( obj->getCommandSetString().isEmpty() == FALSE ) - { - - switchToContext( CB_CONTEXT_COMMAND, drawToEvaluateFor ); - - } - else if (obj->getControllingPlayer()->getPlayerTemplate()->getBeaconTemplate().compare(obj->getTemplate()->getName()) == 0) - { - switchToContext( CB_CONTEXT_BEACON, drawToEvaluateFor ); - } - else - switchToContext( CB_CONTEXT_NONE, drawToEvaluateFor ); - } - - } - -} - -//------------------------------------------------------------------------------------------------- -/** Find a command button of the given name if present */ -//------------------------------------------------------------------------------------------------- -CommandButton *ControlBar::findNonConstCommandButton( const AsciiString& name ) -{ - - for( const CommandButton *command = m_commandButtons; command; command = command->getNext() ) - if( command->getName() == name ) - return const_cast((const CommandButton*)command->getFinalOverride()); - - return nullptr; // not found - -} - -//------------------------------------------------------------------------------------------------- -/** Allocate a new command button, assign name, and tie to list */ -//------------------------------------------------------------------------------------------------- -CommandButton *ControlBar::newCommandButton( const AsciiString& name ) -{ - CommandButton *newButton; - - // allocate new button - newButton = newInstance(CommandButton); - - // assign name - newButton->setName(name); - - // link to list - newButton->friend_addToList(&m_commandButtons); - - // return the new button - return newButton; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -CommandButton *ControlBar::newCommandButtonOverride( CommandButton *buttonToOverride ) -{ - if (!buttonToOverride) { - return nullptr; - } - - CommandButton *newOverride; - - // allocate new button - newOverride = newInstance(CommandButton); - - *newOverride = *buttonToOverride; - - newOverride->markAsOverride(); - buttonToOverride->setNextOverride(newOverride); - - return newOverride; -} - -//------------------------------------------------------------------------------------------------- -/** Parse a command set */ -//------------------------------------------------------------------------------------------------- -/*static*/ void ControlBar::parseCommandSetDefinition( INI *ini ) -{ - AsciiString name; - CommandSet *commandSet; - - // read the name - const char* c = ini->getNextToken(); - name.set( c ); - - // find existing item if present - commandSet = TheControlBar->findNonConstCommandSet( name ); - if( commandSet == nullptr ) - { - - // allocate a new item - commandSet = TheControlBar->newCommandSet( name ); - if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) { - commandSet->markAsOverride(); - } - } - else if( ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES ) - { - //Holy crap, this sucks to debug!!! - //If you have two different command sets, the previous - //code would simply allow you to define multiple command set - //with the same name, and just nuke the old button with the new one. - //So, I (KM) have added this assert to notify in case of two same-name - //command set. - DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate commandset %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() )); - throw INI_INVALID_DATA; - - //@todo SUPPORT OVERRIDES -- JM - } else { - commandSet = TheControlBar->newCommandSetOverride(commandSet); - } - - // sanity - DEBUG_ASSERTCRASH( commandSet, ("parseCommandSetDefinition: Unable to allocate set '%s'", name.str()) ); - - // parse the ini definition - ini->initFromINI( commandSet, commandSet->friend_getFieldParse() ); - -} - -//------------------------------------------------------------------------------------------------- -/** Find existing command set by name */ -//------------------------------------------------------------------------------------------------- -CommandSet* ControlBar::findNonConstCommandSet( const AsciiString& name ) -{ - CommandSet* set; - - for( set = m_commandSets; set != nullptr; set = set->friend_getNext() ) - if( set->getName() == name ) - return const_cast((const CommandSet *) set); - - return nullptr; // set not found - -} -//------------------------------------------------------------------------------------------------- -/** find existing command button if present */ -//------------------------------------------------------------------------------------------------- -const CommandButton *ControlBar::findCommandButton( const AsciiString& name ) -{ - CommandButton *btn = findNonConstCommandButton(name); - if( btn ) - { - btn = (CommandButton *)btn->friend_getFinalOverride(); - } - return btn; -} - -//------------------------------------------------------------------------------------------------- -/** Find existing command set by name */ -//------------------------------------------------------------------------------------------------- -const CommandSet *ControlBar::findCommandSet( const AsciiString& name ) -{ - CommandSet *set = findNonConstCommandSet(name); - if (set) - set = (CommandSet*)set->friend_getFinalOverride(); - return set; -} - -//------------------------------------------------------------------------------------------------- -/** Allocate a new command set, link to list, initialize to default, and return it */ -//------------------------------------------------------------------------------------------------- -CommandSet *ControlBar::newCommandSet( const AsciiString& name ) -{ - // allocate a new set - CommandSet* set = newInstance(CommandSet)(name); - // add it to the list. - set->friend_addToList(&m_commandSets); - // return the newly created set - return set; - -} - -//------------------------------------------------------------------------------------------------- -/** Create an overridden command set. */ -//------------------------------------------------------------------------------------------------- -CommandSet *ControlBar::newCommandSetOverride( CommandSet *setToOverride ) -{ - if (!setToOverride) { - return nullptr; - } - - // allocate a new set - CommandSet* set = newInstance(CommandSet)(setToOverride->getName()); - - // it's an override; DON'T add it to the main list. - // !!! DO NOT DO THIS !!! -- > set->friend_addToList(&m_commandSets); <-- !!! DO NOT DO THIS !!! - - *set = *setToOverride; - set->markAsOverride(); - - setToOverride->setNextOverride(set); - - return set; -} - -//------------------------------------------------------------------------------------------------- -/** Process a button click for the context sensitive GUI */ -//------------------------------------------------------------------------------------------------- -CBCommandStatus ControlBar::processContextSensitiveButtonClick( GameWindow *button, - GadgetGameMessage gadgetMessage ) -{ - - // call command processing method - return processCommandUI( button, gadgetMessage ); - -} - -//------------------------------------------------------------------------------------------------- -/** Process a button click for the context sensitive GUI */ -//------------------------------------------------------------------------------------------------- -CBCommandStatus ControlBar::processContextSensitiveButtonTransition( GameWindow *button, - GadgetGameMessage gadgetMessage ) -{ - - // call command processing method - return processCommandTransitionUI( button, gadgetMessage ); - -} - - -//------------------------------------------------------------------------------------------------- -/** Switch the user interface to the new context specified and fill out any of the - * art and/or buttons that we need to for the new context using data from the object - * passed in */ -//------------------------------------------------------------------------------------------------- -void ControlBar::switchToContext( ControlBarContext context, Drawable *draw ) -{ - - // restore the right hud to a plain window - setPortraitByObject( nullptr ); - - Object *obj = draw ? draw->getObject() : nullptr; - setPortraitByObject( obj ); - - // if we're switching context, we have to repopulate the hotkey manager - if(TheHotKeyManager) - TheHotKeyManager->reset(); - - // ... and also remove any radius cursor that is active. - TheInGameUI->setRadiusCursorNone(); - - // save a pointer for the currently selected drawable - m_currentSelectedDrawable = draw; - - if (IsInGameChatActive() == FALSE && TheGameLogic && !TheGameLogic->isInShellGame()) { - TheWindowManager->winSetFocus( nullptr ); - } - - // hide/un-hide the appropriate windows for the context - switch( context ) - { - - //------------------------------------------------------------------------------------------------- - case CB_CONTEXT_NONE: - { - - // show or hide the right window groups - //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( TRUE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - //Clear any potentially flashing buttons! - for( int i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - // the implementation won't necessarily use the max number of windows possible - if (m_commandWindows[ i ]) - { - m_commandWindows[ i ]->winClearStatus( WIN_STATUS_FLASHING ); - } - } - // if there is a current selected drawable then we wil display a selection portrait if present - if( draw ) - { - //Get the current thing template. - const ThingTemplate *thing = draw->getTemplate(); - - //Special case -- if we are a GLA hole, then get the rebuild building template - Object *obj = draw->getObject(); - if( obj && obj->isKindOf( KINDOF_REBUILD_HOLE ) ) - { - RebuildHoleBehaviorInterface *rhbi = RebuildHoleBehavior::getRebuildHoleBehaviorInterfaceFromObject( obj ); - if( rhbi ) - { - thing = rhbi->getRebuildTemplate(); - } - } - - //Set the correct portrait. - setPortraitByObject( obj ); - } - - // do not show any rally point marker - showRallyPoint( nullptr ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_COMMAND: - { - - // show or hide the right window groups - //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( FALSE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - // fill the specific UI info - populateCommand( draw->getObject() ); - - // - // for objects that are able to create units, we show a build queue if we actually - // actually have something in production, otherwise we show the selection portrait - // - if( obj ) - { - ProductionUpdateInterface *pu = obj->getProductionUpdateInterface(); - - if( pu && pu->firstProduction() != nullptr ) - { - - m_contextParent[ CP_BUILD_QUEUE ]->winHide( FALSE ); - populateBuildQueue( obj ); - setPortraitByObject( nullptr ); - } - else - { - setPortraitByObject( obj ); - } - - } - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_STRUCTURE_INVENTORY: - { - - // show or hide the right window groups - //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( FALSE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - // fill the specific UI info - populateStructureInventory( draw->getObject() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_BEACON: - { - - // show or hide the right window groups - //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( TRUE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( FALSE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - - // fill the specific UI info - populateBeacon( draw->getObject() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_UNDER_CONSTRUCTION: - { - - // show or hide the right window groups - //m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( TRUE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( FALSE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - // fill the specific UI info - populateUnderConstruction( draw->getObject() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_OCL_TIMER: - { - - // show or hide the right window groups -// m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( TRUE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( FALSE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - // fill the specific UI info - populateOCLTimer( draw->getObject() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case CB_CONTEXT_MULTI_SELECT: - { - - // show or hide the right window groups -// m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( FALSE ); // multi select shows common commands - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( TRUE ); - - - // fill the specific UI info - populateMultiSelect(); - - break; - - } - case CB_CONTEXT_OBSERVER_LIST: - { - - // show or hide the right window groups -// m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - m_contextParent[ CP_COMMAND ]->winHide( TRUE ); - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - m_contextParent[ CP_BEACON ]->winHide( TRUE ); - m_contextParent[ CP_UNDER_CONSTRUCTION ]->winHide( TRUE ); - m_contextParent[ CP_OCL_TIMER ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_INFO ]->winHide( TRUE ); - m_contextParent[ CP_OBSERVER_LIST ]->winHide( FALSE ); - - - // fill the specific UI info - populateObserverList(); - break; - - } - - //--------------------------------------------------------------------------------------------- - default: - { - - DEBUG_CRASH( ("ControlBar::switchToContext, unknown context '%d'", context) ); - break; - - } - - } - - // save our context - m_currContext = context; - -} - -void ControlBar::setCommandBarBorder( GameWindow *button, CommandButtonMappedBorderType type) -{ - if(!button) - return; - - switch( type ) - { - case COMMAND_BUTTON_BORDER_BUILD: - { - GadgetButtonSetBorder(button, m_commandButtonBorderBuildColor); - break; - } - //------------------------------------------------------------------------------------------------- - case COMMAND_BUTTON_BORDER_UPGRADE: - { - GadgetButtonSetBorder(button, m_commandButtonBorderUpgradeColor ); - break; - } - //------------------------------------------------------------------------------------------------- - case COMMAND_BUTTON_BORDER_ACTION: - { - GadgetButtonSetBorder(button, m_commandButtonBorderActionColor); - break; - } - //------------------------------------------------------------------------------------------------- - case COMMAND_BUTTON_BORDER_SYSTEM: - { - GadgetButtonSetBorder(button, m_commandButtonBorderSystemColor); - break; - } - - //------------------------------------------------------------------------------------------------- - case COMMAND_BUTTON_BORDER_NONE: - default: - GadgetButtonSetBorder(button, GAME_COLOR_UNDEFINED, FALSE); - } -} - - -//------------------------------------------------------------------------------------------------- -/** Set the command data into the control */ -//------------------------------------------------------------------------------------------------- -void ControlBar::setControlCommand( GameWindow *button, const CommandButton *commandButton ) -{ - - // the window must be a gadget button - if( button->winGetInputFunc() != GadgetPushButtonInput ) - { - - DEBUG_CRASH( ("setControlCommand: Window is not a button") ); - return; - - } - - // sanity - if( commandButton == nullptr ) - { - - DEBUG_CRASH( ("setControlCommand: null commandButton passed in") ); - return; - - } - - // - // set the button gadget control to be a normal button or a check like button if - // the command says it needs one - // - if( BitIsSet( commandButton->getOptions(), CHECK_LIKE )) - GadgetButtonEnableCheckLike( button, TRUE, FALSE ); - else - GadgetButtonEnableCheckLike( button, FALSE, FALSE ); - - // - // set the imagry ... note that for 99% of the command buttons it's sufficient to specify - // only the disabled, enabled, hilite, and hilite pushed images. For push-like buttons - // we actually utilize all the state available to a GameWindow. We will replicate the - // hilite pushed image to be the enabled pushed image ... and we will also replicate - // the disabled image to be the disabled pushed image. For complete control over all - // the states of these buttons we would add additional lines to the INI for a command - // button and store those additional images in the command button - // - if( commandButton->getButtonImage() ) - GadgetButtonSetEnabledImage( button, commandButton->getButtonImage() ); - - //if( commandButton->getDisabledImage() ) - //{ - // GadgetButtonSetDisabledImage( button, commandButton->getDisabledImage() ); - // GadgetButtonSetDisabledSelectedImage( button, commandButton->getDisabledImage() ); - //} //end if - //if( commandButton->getHiliteImage() ) - // GadgetButtonSetHiliteImage( button, commandButton->getHiliteImage() ); - //if( commandButton->getPushedImage() ) - //{ - // GadgetButtonSetHiliteSelectedImage( button, commandButton->getPushedImage() ); - // GadgetButtonSetEnabledSelectedImage( button, commandButton->getPushedImage() ); - //} // end if - - // set the text - if( commandButton->getTextLabel().isEmpty() == FALSE || !commandButton->getScienceVec().empty()) - { - button->winSetTooltipFunc(commandButtonTooltip); - } - else - GadgetButtonSetText( button, L"" ); - - // save the command in the user data of the window - GadgetButtonSetData(button, (void*)commandButton); - //button->winSetUserData( commandButton ); - - setCommandBarBorder(button, commandButton->getCommandButtonMappedBorderType()); - - if (TheHotKeyManager) - { - AsciiString hotKey = TheHotKeyManager->searchHotKey(commandButton->getTextLabel()); - if(hotKey.isNotEmpty()) - TheHotKeyManager->addHotKey(button, hotKey); - } - GadgetButtonSetAltSound(button, "GUICommandBarClick"); - -} - -//------------------------------------------------------------------------------------------------- -void CommandButton::cacheButtonImage() -{ - if (!TheMappedImageCollection) { - return; - } - if( m_buttonImageName.isNotEmpty() ) - { - m_buttonImage = TheMappedImageCollection->findImageByName( m_buttonImageName ); - DEBUG_ASSERTCRASH( m_buttonImage, ("CommandButton: %s is looking for button image %s but can't find it. Skipping...", m_name.str(), m_buttonImageName.str() ) ); - m_buttonImageName.clear(); // we're done with this, so nuke it - } -} - -//------------------------------------------------------------------------------------------------- -/** post process step, after all commands and command sets are loaded */ -//------------------------------------------------------------------------------------------------- -void ControlBar::postProcessCommands() -{ - for ( CommandButton *button = m_commandButtons; button; button = button->friend_getNext() ) - { - button->cacheButtonImage(); - } -} - -//------------------------------------------------------------------------------------------------- -/** set the command for the button identified by the window name - * NOTE that parent may be nullptr, it only helps to speed up the search for a particular - * window ID */ -//------------------------------------------------------------------------------------------------- -void ControlBar::setControlCommand( const AsciiString& buttonWindowName, GameWindow *parent, - const CommandButton *commandButton ) -{ - UnsignedInt winID = TheNameKeyGenerator->nameToKey( buttonWindowName ); - GameWindow *win = TheWindowManager->winGetWindowFromId( parent, winID ); - - if( win == nullptr ) - { - - DEBUG_CRASH( ("setControlCommand: Unable to find window '%s'", buttonWindowName.str()) ); - return; - - } - - // call the workhorse - setControlCommand( win, commandButton ); - -} - -//------------------------------------------------------------------------------------------------- -/** show/hide the portrait window image */ -//------------------------------------------------------------------------------------------------- -void ControlBar::setPortraitByImage( const Image *image ) -{ - - if( image ) - { - m_rightHUDUnitSelectParent->winHide(FALSE); - m_rightHUDCameoWindow->winSetEnabledImage( 0, image ); - //m_rightHUDWindow->winSetEnabledImage( 0, image ); - m_rightHUDWindow->winClearStatus( WIN_STATUS_IMAGE ); - m_rightHUDCameoWindow->winSetStatus( WIN_STATUS_IMAGE ); - for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i) - m_rightHUDUpgradeCameos[i]->winHide(TRUE); - - } - else - { - m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE ); - m_rightHUDCameoWindow->winClearStatus( WIN_STATUS_IMAGE ); - m_rightHUDUnitSelectParent->winHide(TRUE); - for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i) - m_rightHUDUpgradeCameos[i]->winHide(TRUE); - //m_rightHUDWindow->winSetEnabledImage( 0, image ); - //m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE ); - - } - -} - -//------------------------------------------------------------------------------------------------- -/** show/hide the portrait image by object. We like to use this method as opposed to the - * plain image one above so that we can build more intelligence into what portrait to - * show for an object given its current state or object type */ -//------------------------------------------------------------------------------------------------- -void ControlBar::setPortraitByObject( Object *obj ) -{ - - if( obj ) - { - if( obj->isKindOf( KINDOF_SHOW_PORTRAIT_WHEN_CONTROLLED ) && !obj->isLocallyControlled() ) - { - //Handles civ vehicles without terrorists in them - setPortraitByObject( nullptr ); - return; - } - - const ThingTemplate *thing = obj->getTemplate(); - Player *player = obj->getControllingPlayer(); - - //If we have an enemy stealth disguised unit, swap portraits! - Drawable *draw = obj->getDrawable(); - if( draw && draw->getStealthLook() == STEALTHLOOK_DISGUISED_ENEMY ) - { - thing = draw->getTemplate(); - if( thing->isKindOf( KINDOF_SHOW_PORTRAIT_WHEN_CONTROLLED ) ) - { - //If a bomb truck disguises as a civ vehicle, don't use it's portrait (or else you'll see the terrorist). - setPortraitByObject( nullptr ); - return; - } - StealthUpdate *stealth = obj->getStealth(); - if( stealth && stealth->isDisguised() ) - { - //Fake player upgrades too! - player = ThePlayerList->getNthPlayer( stealth->getDisguisedPlayerIndex() ); - } - } - - const Image* portrait = thing->getSelectedPortraitImage(); - - m_rightHUDUnitSelectParent->winHide(FALSE); - // enable the window window as an image window and set the image - m_rightHUDCameoWindow->winSetEnabledImage( 0, portrait ); - - //Display the veterancy rank of the object on the portrait. - const Image *image = calculateVeterancyOverlayForObject( obj ); - GadgetButtonDrawOverlayImage( m_rightHUDCameoWindow, image ); - - //m_rightHUDWindow->winSetEnabledImage( 0, portrait ); - m_rightHUDWindow->winClearStatus( WIN_STATUS_IMAGE ); - m_rightHUDCameoWindow->winSetStatus( WIN_STATUS_IMAGE ); - - for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i) - { - AsciiString upgradeName = thing->getUpgradeCameoName(i); - if(upgradeName.isEmpty()) - { - m_rightHUDUpgradeCameos[i]->winHide(TRUE); - continue; - } - const UpgradeTemplate *ut = TheUpgradeCenter->findUpgrade(upgradeName); - if(!ut) - { - m_rightHUDUpgradeCameos[i]->winHide(TRUE); - continue; - } - - m_rightHUDUpgradeCameos[i]->winHide(FALSE); - m_rightHUDUpgradeCameos[i]->winSetEnabledImage( 0, ut->getButtonImage() ); - if( obj->hasUpgrade(ut) ) - { - //Object level upgrades - m_rightHUDUpgradeCameos[i]->winEnable( TRUE ); - } - else if( player && player->hasUpgradeComplete( ut ) ) - { - //Player level upgrades - m_rightHUDUpgradeCameos[i]->winEnable( TRUE ); - } - else - { - //Failure - m_rightHUDUpgradeCameos[i]->winEnable( FALSE ); - } - } - - - } - else - { - m_rightHUDUnitSelectParent->winHide(TRUE); - m_rightHUDWindow->winSetStatus( WIN_STATUS_IMAGE ); - m_rightHUDCameoWindow->winClearStatus( WIN_STATUS_IMAGE ); - for(Int i = 0; i < MAX_UPGRADE_CAMEO_UPGRADES; ++i) - m_rightHUDUpgradeCameos[i]->winHide(TRUE); - - //Clear any overlay the portrait had on it. - GadgetButtonDrawOverlayImage( m_rightHUDCameoWindow, nullptr ); - } - -} - -// ------------------------------------------------------------------------------------------------ -/** Show a rally point marker at the world location specified. If no location is specified - * any marker that we might have visible is hidden */ -// ------------------------------------------------------------------------------------------------ -void ControlBar::showRallyPoint(const Coord3D* loc) -{ - // if loc is null, destroy any rally point drawable we have shown - if (loc == nullptr) - { - // destroy rally point drawable if present - if (m_rallyPointDrawableID != INVALID_DRAWABLE_ID) - TheGameClient->destroyDrawable(TheGameClient->findDrawableByID(m_rallyPointDrawableID)); - - m_rallyPointDrawableID = INVALID_DRAWABLE_ID; - return; - } - - Drawable* marker = nullptr; - - // create a rally point drawable if necessary - if (m_rallyPointDrawableID == INVALID_DRAWABLE_ID) - { - const ThingTemplate* ttn = TheThingFactory->findTemplate("RallyPointMarker"); - marker = TheThingFactory->newDrawable(ttn); - DEBUG_ASSERTCRASH(marker, ("showRallyPoint: Unable to create rally point drawable")); - if (marker) - { - marker->setDrawableStatus(DRAWABLE_STATUS_NO_SAVE); - m_rallyPointDrawableID = marker->getID(); - } - } - else - marker = TheGameClient->findDrawableByID(m_rallyPointDrawableID); - - // sanity - DEBUG_ASSERTCRASH(marker, ("showRallyPoint: No rally point marker found")); - - // set the position of the rally point drawable to the position passed in - marker->setPosition(loc); - marker->setOrientation(TheGlobalData->m_downwindAngle); // To blow down wind -- ML - - // set the marker colors to that of the local player - Player* player = getCurrentlyViewedPlayer(); - if (player) - { - if (TheGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT) - marker->setIndicatorColor(player->getPlayerNightColor()); - else - marker->setIndicatorColor(player->getPlayerColor()); - } -} - -// ------------------------------------------------------------------------------------------------ -/** Show a rally point marker at the world location specified. If no location is specified - * any marker that we might have visible is hidden */ -// ------------------------------------------------------------------------------------------------ -void ControlBar::setControlBarSchemeByPlayer(Player *p) -{ - if(m_controlBarSchemeManager) - m_controlBarSchemeManager->setControlBarSchemeByPlayer(p); - - static NameKeyType buttonPlaceBeaconID = NAMEKEY( "ControlBar.wnd:ButtonPlaceBeacon" ); - static NameKeyType buttonIdleWorkerID = NAMEKEY("ControlBar.wnd:ButtonIdleWorker"); - static NameKeyType buttonGeneralID = NAMEKEY("ControlBar.wnd:ButtonGeneral"); - GameWindow *buttonPlaceBeacon = TheWindowManager->winGetWindowFromId( nullptr, buttonPlaceBeaconID ); - GameWindow *buttonIdleWorker = TheWindowManager->winGetWindowFromId( nullptr, buttonIdleWorkerID ); - GameWindow *buttonGeneral = TheWindowManager->winGetWindowFromId( nullptr, buttonGeneralID ); - - if( !p->isPlayerActive() ) - { - m_isObserverCommandBar = TRUE; - switchToContext( CB_CONTEXT_OBSERVER_LIST, nullptr ); - DEBUG_LOG(("We're loading the Observer Command Bar")); - - if (buttonPlaceBeacon) - buttonPlaceBeacon->winHide(TRUE); - if (buttonIdleWorker) - buttonIdleWorker->winHide(TRUE); - if (buttonGeneral) - buttonGeneral->winEnable(FALSE); - } - else - { - switchToContext( CB_CONTEXT_NONE, nullptr ); - m_isObserverCommandBar = FALSE; - - if (buttonPlaceBeacon) - buttonPlaceBeacon->winHide( - (TheGameLogic->getGameMode() != GAME_LAN && TheGameLogic->getGameMode() != GAME_INTERNET) || - !TheGameInfo->isMultiPlayer()); - if (buttonIdleWorker) - buttonIdleWorker->winHide(FALSE); - if (buttonGeneral) - { - buttonGeneral->winHide(FALSE); - buttonGeneral->winEnable(TRUE); - } - } - switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); -} - -void ControlBar::setControlBarSchemeByPlayerTemplate( const PlayerTemplate *pt) -{ - if(m_controlBarSchemeManager) - m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(pt); - - static NameKeyType buttonPlaceBeaconID = NAMEKEY( "ControlBar.wnd:ButtonPlaceBeacon" ); - static NameKeyType buttonIdleWorkerID = NAMEKEY("ControlBar.wnd:ButtonIdleWorker"); - static NameKeyType buttonGeneralID = NAMEKEY("ControlBar.wnd:ButtonGeneral"); - GameWindow *buttonPlaceBeacon = TheWindowManager->winGetWindowFromId( nullptr, buttonPlaceBeaconID ); - GameWindow *buttonIdleWorker = TheWindowManager->winGetWindowFromId( nullptr, buttonIdleWorkerID ); - GameWindow *buttonGeneral = TheWindowManager->winGetWindowFromId( nullptr, buttonGeneralID ); - - if(pt == ThePlayerTemplateStore->findPlayerTemplate(TheNameKeyGenerator->nameToKey("FactionObserver"))) - { - m_isObserverCommandBar = TRUE; - switchToContext( CB_CONTEXT_OBSERVER_LIST, nullptr ); - DEBUG_LOG(("We're loading the Observer Command Bar")); - - if (buttonPlaceBeacon) - buttonPlaceBeacon->winHide(TRUE); - if (buttonIdleWorker) - buttonIdleWorker->winHide(TRUE); - if (buttonGeneral) - buttonGeneral->winEnable(FALSE); - } - else - { - switchToContext( CB_CONTEXT_NONE, nullptr ); - m_isObserverCommandBar = FALSE; - - if (buttonPlaceBeacon) - buttonPlaceBeacon->winHide( - (TheGameLogic->getGameMode() != GAME_LAN && TheGameLogic->getGameMode() != GAME_INTERNET) || - !TheGameInfo->isMultiPlayer()); - if (buttonIdleWorker) - buttonIdleWorker->winHide(FALSE); - if (buttonGeneral) - { - buttonGeneral->winHide(FALSE); - buttonGeneral->winEnable(TRUE); - } - } - switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); - - hidePurchaseScience(); -} - -void ControlBar::setControlBarSchemeByName(const AsciiString& name) -{ - if(m_controlBarSchemeManager) - m_controlBarSchemeManager->setControlBarScheme( name ); - switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); - -} - -void ControlBar::preloadAssets( TimeOfDay timeOfDay ) -{ - if (m_controlBarSchemeManager) - m_controlBarSchemeManager->preloadAssets( timeOfDay ); -} - -void ControlBar::updateBuildQueueDisabledImages( const Image *image ) -{ - if(!image) - return; - // We have to do this because the build queue data might have been reset - static NameKeyType buildQueueIDs[ MAX_BUILD_QUEUE_BUTTONS ]; - static Bool idsInitialized = FALSE; - Int i; - - // get name key ids for the build queue buttons - if( idsInitialized == FALSE ) - { - AsciiString buttonName; - - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - { - - buttonName.format( "ControlBar.wnd:ButtonQueue%02d", i + 1 ); - buildQueueIDs[ i ] = TheNameKeyGenerator->nameToKey( buttonName ); - - } - - idsInitialized = TRUE; - - } - - // get window pointers to all the buttons for the build queue - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - { - - // get window commented out cause I believe we already set this. We'll see in a few minutes - m_queueData[ i ].control = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_BUILD_QUEUE ], - buildQueueIDs[ i ] ); - - GadgetButtonSetDisabledImage( m_queueData[ i ].control, image ); - - } - -} - -void ControlBar::updateRightHUDImage( const Image *image ) -{ - if(!m_rightHUDWindow || !image) - return; - m_rightHUDWindow->winSetEnabledImage(0, image); - -} - -void ControlBar::updateBuildUpClockColor( Color color) -{ - m_buildUpClockColor = color; -} - - - -void ControlBar::updateCommandBarBorderColors(Color build, Color action, Color upgrade, Color system ) -{ - m_commandButtonBorderBuildColor = build; - m_commandButtonBorderActionColor = action; - m_commandButtonBorderUpgradeColor = upgrade; - m_commandButtonBorderSystemColor = system; -} - -// --------------------------------------------------------------------------------------- -// hides the communicator button -void ControlBar::hideCommunicator( Bool b ) -{ - //sanity - if( m_communicatorButton != nullptr ) - m_communicatorButton->winHide( b ); -} - -// --------------------------------------------------------------------------------------- -// Outside hook so when the genera's head is pushed, we can switch to the purchase science -// context -void ControlBar::updatePurchaseScience() -{ -// if(m_generalsScreenAnimate && TheGlobalData->m_animateWindows) -// { -// Bool wasFinished = m_generalsScreenAnimate->isFinished(); -// m_generalsScreenAnimate->update(); -// if (m_generalsScreenAnimate->isFinished() && !wasFinished && m_generalsScreenAnimate->isReversed()) -// m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide(TRUE); -// } -} - -void ControlBar::showPurchaseScience() -{ - - if(TheScriptEngine->isGameEnding()) - return; - populatePurchaseScience(ThePlayerList->getLocalPlayer()); - m_genStarFlash = FALSE; - if(!m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden()) - return; - //switchToContext(CB_CONTEXT_PURCHASE_SCIENCE, nullptr); - m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide(FALSE); - if (TheGlobalData->m_animateWindows) - TheTransitionHandler->setGroup("GenExpFade"); - //m_generalsScreenAnimate->registerGameWindow( m_contextParent[ CP_PURCHASE_SCIENCE ], WIN_ANIMATION_SLIDE_TOP, TRUE, 200 ); - -} - -void ControlBar::hidePurchaseScience() -{ - if(m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden()) - return; - - if( m_contextParent[ CP_PURCHASE_SCIENCE ] ) - { - m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); - } -// if (!TheGlobalData->m_animateWindows) -// { -// if( m_contextParent[ CP_PURCHASE_SCIENCE ] ) -// { -// m_contextParent[ CP_PURCHASE_SCIENCE ]->winHide( TRUE ); -// } -// } -// else -// { -// //if (m_generalsScreenAnimate->isFinished()) -// if(TheTransitionHandler->isFinished()) -// TheTransitionHandler->reverse("GenExpFade"); -// //m_generalsScreenAnimate->reverseAnimateWindow(); -// } -} - -void ControlBar::togglePurchaseScience() -{ - if(m_contextParent[ CP_PURCHASE_SCIENCE ]->winIsHidden()) - showPurchaseScience(); - else - hidePurchaseScience(); -} - -void ControlBar::toggleControlBarStage() -{ - if(m_currentControlBarStage == CONTROL_BAR_STAGE_DEFAULT ) - switchControlBarStage(CONTROL_BAR_STAGE_LOW); - else - switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); -} - -// Functions for repositioning/resizing the control bar -void ControlBar::switchControlBarStage( ControlBarStages stage ) -{ - if(stage < CONTROL_BAR_STAGE_DEFAULT || stage >= MAX_CONTROL_BAR_STAGES) - return; - switch (stage) { - case CONTROL_BAR_STAGE_DEFAULT: - setDefaultControlBarConfig(); - break; -// case CONTROL_BAR_STAGE_SQUISHED: -// setSquishedControlBarConfig(); -// break; - case CONTROL_BAR_STAGE_LOW: - setLowControlBarConfig(); - break; - case CONTROL_BAR_STAGE_HIDDEN: - setHiddenControlBar(); - break; - default: - DEBUG_CRASH(("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage)); - } - -} -void ControlBar::setDefaultControlBarConfig() -{ -// if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED) -// { -// m_controlBarResizer->sizeWindowsDefault(); -// m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), FALSE); -// } - m_currentControlBarStage = CONTROL_BAR_STAGE_DEFAULT; - setScaledViewportHeight(); - m_contextParent[ CP_MASTER ]->winSetPosition(m_defaultControlBarPosition.x, m_defaultControlBarPosition.y); - m_contextParent[ CP_MASTER ]->winHide(FALSE); - repopulateBuildTooltipLayout(); - setUpDownImages(); - -} - -void ControlBar::setSquishedControlBarConfig() -{ - if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED) - return; - m_currentControlBarStage = CONTROL_BAR_STAGE_SQUISHED; - m_contextParent[ CP_MASTER ]->winSetPosition(m_defaultControlBarPosition.x, m_defaultControlBarPosition.y); - -// m_controlBarResizer->sizeWindowsAlt(); - repopulateBuildTooltipLayout(); - setFullViewportHeight(); - m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), TRUE); -} - -void ControlBar::setLowControlBarConfig() -{ -// if(m_currentControlBarStage == CONTROL_BAR_STAGE_SQUISHED) -// { -// m_controlBarResizer->sizeWindowsDefault(); -// m_controlBarSchemeManager->setControlBarSchemeByPlayerTemplate(ThePlayerList->getLocalPlayer()->getPlayerTemplate(), FALSE); -// } - - m_currentControlBarStage = CONTROL_BAR_STAGE_LOW; - ICoord2D pos; - pos.x = m_defaultControlBarPosition.x; - pos.y = TheDisplay->getHeight() - .1 * TheDisplay->getHeight(); - setFullViewportHeight(); - m_contextParent[ CP_MASTER ]->winSetPosition(pos.x, pos.y); - m_contextParent[ CP_MASTER ]->winHide(FALSE); - setUpDownImages(); - -} - -void ControlBar::setHiddenControlBar() -{ - m_currentControlBarStage = CONTROL_BAR_STAGE_HIDDEN; - m_contextParent[ CP_MASTER ]->winHide(TRUE); -} -// removed from multiplayer test -//void ControlBar::showCommandMarkers() -//{ -// for(Int i =0; i < MAX_COMMANDS_PER_SET; ++i) -// { -// if(m_commandWindows[i]->winIsHidden()) -// m_commandMarkers[i]->winHide(FALSE); -// else -// m_commandMarkers[i]->winHide(TRUE); -// } -//} -// -void ControlBar::updateCommandMarkerImage( const Image *image ) -{ - // removed from multiplayer branch - -// // we don't mind if the image is null, that way we can not draw anything - // for(Int i =0; i < MAX_COMMANDS_PER_SET; ++i) - // { - // m_commandMarkers[i]->winSetEnabledImage(0, image); - // } - -} -void ControlBar::updateSlotExitImage( const Image *image ) -{ - //Hardcoding values here Not a good thing but there's no other way right now. - if(!image) - return; - - //Kris: - //Other than this being a completely ridiculously retarded idea, I'm not inclined - //to recode this in a better way, yikes! Btw, I DID NOT CODE THIS! But this is - //what this does: The button images are overridden by a faction specific icon. - //The proper way to fix this would be to make a commandbutton option and loop - //through all buttons on init to replace the icon. We need a system like this - //for neutral buildings which can have a different empty inventory icon based - //on the faction player. - - CommandButton *cmdButton = findNonConstCommandButton( "Command_StructureExit" ); - if(cmdButton) - cmdButton->setButtonImage(image); - - cmdButton = findNonConstCommandButton( "Command_TransportExit" ); - if(cmdButton) - cmdButton->setButtonImage(image); - - cmdButton = findNonConstCommandButton( "Command_BunkerExit" ); - if(cmdButton) - cmdButton->setButtonImage(image); - - cmdButton = findNonConstCommandButton( "Command_FireBaseExit" ); - if(cmdButton) - cmdButton->setButtonImage(image); - -} - -void ControlBar::updateUpDownImages( const Image *toggleButtonUpIn, const Image *toggleButtonUpOn, const Image *toggleButtonUpPushed, - const Image *toggleButtonDownIn, const Image *toggleButtonDownOn, const Image *toggleButtonDownPushed, - const Image *generalButtonEnable, const Image *generalButtonHighlight ) -{ - m_toggleButtonUpIn = toggleButtonUpIn; - m_toggleButtonUpOn = toggleButtonUpOn; - m_toggleButtonUpPushed = toggleButtonUpPushed; - m_toggleButtonDownIn = toggleButtonDownIn; - m_toggleButtonDownOn = toggleButtonDownOn; - m_toggleButtonDownPushed = toggleButtonDownPushed; - - - m_generalButtonEnable = generalButtonEnable; - m_generalButtonHighlight = generalButtonHighlight; - - setUpDownImages(); -} - -void ControlBar::setUpDownImages() -{ - GameWindow *win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonLarge" ) ); - if(!win) - return; - // we only care if it's in it's low state, else we put the default images up - if(m_currentControlBarStage == CONTROL_BAR_STAGE_LOW) - { - GadgetButtonSetEnabledImage(win, m_toggleButtonUpOn); - GadgetButtonSetHiliteImage(win, m_toggleButtonUpIn); - GadgetButtonSetHiliteSelectedImage(win, m_toggleButtonUpPushed); - return; - } - - GadgetButtonSetEnabledImage(win, m_toggleButtonDownOn); - GadgetButtonSetHiliteImage(win, m_toggleButtonDownIn); - GadgetButtonSetHiliteSelectedImage(win, m_toggleButtonDownPushed); - -} - -void ControlBar::getForegroundMarkerPos(Int *x, Int *y) -{ - *x = m_controlBarForegroundMarkerPos.x; - *y = m_controlBarForegroundMarkerPos.y; -} -void ControlBar::getBackgroundMarkerPos(Int *x, Int *y) -{ - *x = m_controlBarBackgroundMarkerPos.x; - *y = m_controlBarBackgroundMarkerPos.y; -} - -void ControlBar::drawTransitionHandler() -{ -// if(m_transitionHandler) -// m_transitionHandler->draw(); -} -enum{ - RADAR_ATTACK_GLOW_FRAMES = 150, - RADAR_ATTACK_GLOW_NUM_TIMES = 15 ///< number of times we'll flash -}; - -void ControlBar::triggerRadarAttackGlow() -{ - if(!m_radarAttackGlowWindow) - return; - m_radarAttackGlowOn = TRUE; - m_remainingRadarAttackGlowFrames = RADAR_ATTACK_GLOW_FRAMES; - if(BitIsSet(m_radarAttackGlowWindow->winGetStatus(),WIN_STATUS_ENABLED) == TRUE) - m_radarAttackGlowWindow->winEnable(FALSE); -} - -void ControlBar::updateRadarAttackGlow () -{ - if(!m_radarAttackGlowOn || !m_radarAttackGlowWindow) - return; - m_remainingRadarAttackGlowFrames--; - if(m_remainingRadarAttackGlowFrames <= 0) - { - m_radarAttackGlowOn = FALSE; - m_radarAttackGlowWindow->winEnable(TRUE); - return; - } - - if(m_remainingRadarAttackGlowFrames % RADAR_ATTACK_GLOW_NUM_TIMES == 0) - { - m_radarAttackGlowWindow->winEnable(!BitIsSet(m_radarAttackGlowWindow->winGetStatus(),WIN_STATUS_ENABLED)); - } - - -} -void ControlBar::initSpecialPowershortcutBar( Player *player) -{ - Int i = 0; - for( ; i < MAX_SPECIAL_POWER_SHORTCUTS; ++i ) - { - m_specialPowerShortcutButtonParents[i] = nullptr; - m_specialPowerShortcutButtons[i] = nullptr; - } - - if(m_specialPowerLayout) - { - m_specialPowerLayout->destroyWindows(); - deleteInstance(m_specialPowerLayout); - m_specialPowerLayout = nullptr; - } - m_specialPowerShortcutParent = nullptr; - m_currentlyUsedSpecialPowersButtons = 0; - const PlayerTemplate *pt = player->getPlayerTemplate(); - - if(!player || !pt|| !player->isLocalPlayer() - || pt->getSpecialPowerShortcutButtonCount() == 0 - || pt->getSpecialPowerShortcutWinName().isEmpty() - || !player->isPlayerActive()) - return; - m_currentlyUsedSpecialPowersButtons = pt->getSpecialPowerShortcutButtonCount(); - AsciiString layoutName, tempName, windowName, parentName; - layoutName = pt->getSpecialPowerShortcutWinName(); - m_specialPowerLayout = TheWindowManager->winCreateLayout(layoutName); - m_specialPowerLayout->hide(TRUE); - - tempName = layoutName; - tempName.concat(":GenPowersShortcutBarParent"); - NameKeyType id = TheNameKeyGenerator->nameToKey( tempName ); - m_specialPowerShortcutParent = TheWindowManager->winGetWindowFromId( nullptr, id );//m_scienceLayout->getFirstWindow(); - - tempName = layoutName; - tempName.concat(":ButtonCommand%d"); - parentName = layoutName; - parentName.concat(":ButtonParent%d"); - m_currentlyUsedSpecialPowersButtons = MIN(pt->getSpecialPowerShortcutButtonCount(), MAX_SPECIAL_POWER_SHORTCUTS); - for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ ) - { - windowName.format( tempName, i+1 ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_specialPowerShortcutButtons[ i ] = - TheWindowManager->winGetWindowFromId( m_specialPowerShortcutParent, id ); - - if (m_specialPowerShortcutButtons[ i ] != nullptr) - { - m_specialPowerShortcutButtons[ i ]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - // Oh god... this is a total hack for shortcut buttons to handle rendering text top left corner... - m_specialPowerShortcutButtons[ i ]->winSetStatus( WIN_STATUS_SHORTCUT_BUTTON ); - - windowName.format( parentName, i+1 ); - id = TheNameKeyGenerator->nameToKey( windowName.str() ); - m_specialPowerShortcutButtonParents[ i ] = - TheWindowManager->winGetWindowFromId( m_specialPowerShortcutParent, id ); - } - } - -} - -void ControlBar::populateSpecialPowerShortcut( Player *player) -{ - const CommandSet *commandSet; - Int i; - if(!player || !player->getPlayerTemplate() - || !player->isLocalPlayer() || m_currentlyUsedSpecialPowersButtons == 0 - || m_specialPowerShortcutButtons == nullptr || m_specialPowerShortcutButtonParents == nullptr) - return; - for( i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; ++i ) - { - if (m_specialPowerShortcutButtons[i]) - m_specialPowerShortcutButtons[i]->winHide(TRUE); - if (m_specialPowerShortcutButtonParents[i]) - m_specialPowerShortcutButtonParents[i]->winHide(TRUE); - - } - - // get command set - if(player->getPlayerTemplate()->getSpecialPowerShortcutCommandSet().isEmpty() ) - return; - commandSet = findCommandSet(player->getPlayerTemplate()->getSpecialPowerShortcutCommandSet()); // TEMP WILL CHANGE TO PROPER WAY ONCE WORKING - if(!commandSet) - return; - // populate the button with commands defined - Int currentButton = 0; - const CommandButton *commandButton; - for( i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ ) - { - - // get command button - commandButton = commandSet->getCommandButton(i); - - // if button is not present, just hide the window - if( commandButton == nullptr ) - { - continue; - // hide window on interface - //m_specialPowerShortcutButtons[ i ]->winHide( TRUE ); - - } - else - { - - if( BitIsSet( commandButton->getOptions(), NEED_UPGRADE ) ) - { - const UpgradeTemplate *upgrade = commandButton->getUpgradeTemplate(); - if( upgrade && !ThePlayerList->getLocalPlayer()->hasUpgradeComplete( upgrade->getUpgradeMask() ) ) - { - //Kris: 8/13/03 - Don't show shortcut buttons that require upgrades we don't have. As far as - //I know, only the radar van scan has this. The MOAB is handled differently (sciences). - continue; - } - } - - // - // commands that require sciences we don't have are hidden so they never show up - // cause we can never pick "another" general technology throughout the game - // - if( BitIsSet( commandButton->getOptions(), NEED_SPECIAL_POWER_SCIENCE ) ) - { - const SpecialPowerTemplate *power = commandButton->getSpecialPowerTemplate(); - - if( !power ) - { - //Should have the power.. button is probably missing the SpecialPower = xxx entry. - DEBUG_CRASH( ("CommandButton %s needs a SpecialPower entry, but it's either incorrect or missing.", commandButton->getName().str()) ); - continue; - } - - //We just need to find something that has the power. - Object *obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( commandButton->getSpecialPowerTemplate()->getSpecialPowerType() ); - if( !obj ) - { - continue; - } - - if( power->getRequiredScience() != SCIENCE_INVALID ) - { - if( player->hasScience( power->getRequiredScience() ) == FALSE ) - { - //Hide the power - //m_specialPowerShortcutButtons[ i ]->winHide( TRUE ); - continue; - } - else - { - //The player does have the special power! Now determine if the images require - //enhancement based on upgraded versions. This is determined by the command - //button specifying a vector of sciences in the command button. - Int bestIndex = -1; - ScienceType science; - for( size_t scienceIndex = 0; scienceIndex < commandButton->getScienceVec().size(); ++scienceIndex ) - { - science = commandButton->getScienceVec()[ scienceIndex ]; - - //Keep going until we reach the end or don't have the required science! - if( player->hasScience( science ) ) - { - bestIndex = scienceIndex; - } - else - { - break; - } - } - - if( bestIndex != -1 ) - { - //Now get the best sciencetype. - science = commandButton->getScienceVec()[ bestIndex ]; - - const CommandSet *commandSet1; - const CommandSet *commandSet3; - const CommandSet *commandSet8; - Int i; - - // get command set - if( !player || !player->getPlayerTemplate() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1().isEmpty() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3().isEmpty() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8().isEmpty() ) - { - continue; - } - commandSet1 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1() ); - commandSet3 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3() ); - commandSet8 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8() ); - - if( !commandSet1 || !commandSet3 || !commandSet8 ) - { - continue; - } - - Bool found = FALSE; - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - { - const CommandButton *command = commandSet1->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, TRUE, TRUE ); - found = TRUE; - break; - } - } - } - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - { - const CommandButton *command = commandSet3->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, TRUE, TRUE ); - found = TRUE; - break; - } - } - } - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - { - const CommandButton *command = commandSet8->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, TRUE, TRUE ); - found = TRUE; - break; - } - } - } - } - } - } - } - else if( commandButton->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE ) - { - //Make sure we actually have an object of type that we want to be able to select. - Object *obj = ThePlayerList->getLocalPlayer()->findAnyExistingObjectWithThingTemplate( commandButton->getThingTemplate() ); - if( !obj ) - { - continue; - } - } - - DEBUG_ASSERTCRASH(m_specialPowerShortcutButtons[ currentButton ] != nullptr, ("m_specialPowerShortcutButtons[%d] is null", currentButton)); - DEBUG_ASSERTCRASH(m_specialPowerShortcutButtonParents[ currentButton ] != nullptr, ("m_specialPowerShortcutButtonParents[%d] is null", currentButton)); - - // make sure the window is not hidden - m_specialPowerShortcutButtons[ currentButton ]->winHide( FALSE ); - m_specialPowerShortcutButtonParents[ currentButton ]->winHide( FALSE ); - // enable by default - m_specialPowerShortcutButtons[ currentButton ]->winEnable( TRUE ); - m_specialPowerShortcutButtonParents[ currentButton ]->winEnable( TRUE ); - - // populate the visible button with data from the command button - setControlCommand( m_specialPowerShortcutButtons[ currentButton ], commandButton ); - GadgetButtonSetAltSound(m_specialPowerShortcutButtons[ currentButton ], "GUIGenShortcutClick"); - currentButton++; - - } - - } - if(m_contextParent[ CP_MASTER ] && !m_contextParent[ CP_MASTER ]->winIsHidden() && m_specialPowerShortcutParent->winIsHidden()) - { - showSpecialPowerShortcut(); - animateSpecialPowerShortcut(TRUE); - } - updateSpecialPowerShortcut(); -} - -//------------------------------------------------------------------------------------------------- -Bool ControlBar::hasAnyShortcutSelection() const -{ - for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ ) - { - GameWindow *win; - const CommandButton *command; - - win = m_specialPowerShortcutButtons[ i ]; - if( win->winIsHidden() == TRUE ) - continue; - - // get the command from the control - command = (const CommandButton *)GadgetButtonGetData(win); - if( !command ) - continue; - - if( command->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE ) - { - //We found one, so we'll always show shortcuts! - return TRUE; - } - } - return FALSE; -} - -//------------------------------------------------------------------------------------------------- -void ControlBar::updateSpecialPowerShortcut() -{ - if(!m_specialPowerShortcutParent || !m_specialPowerShortcutButtons - || !ThePlayerList || !ThePlayerList->getLocalPlayer()) - return; - - Bool hasShortcutSelectionButtons = hasAnyShortcutSelection(); - Bool hasAnyShortcutSpecialPower = ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower(); - - Bool hasValidShortcutButton = hasShortcutSelectionButtons || hasAnyShortcutSpecialPower; - - if( hasValidShortcutButton - && m_specialPowerShortcutParent->winIsHidden() - && m_contextParent[ CP_MASTER ] - && !m_contextParent[ CP_MASTER ]->winIsHidden() ) - { - showSpecialPowerShortcut(); - animateSpecialPowerShortcut(TRUE); - } - else if( !hasValidShortcutButton - && !m_specialPowerShortcutParent->winIsHidden() - && m_animateWindowManagerForGenShortcuts->isFinished() ) - { - animateSpecialPowerShortcut(FALSE); - } - - if(m_specialPowerShortcutParent->winIsHidden()) - return; - - if(!ThePlayerList->getLocalPlayer()->isPlayerActive()) - { - hideSpecialPowerShortcut(); - return; - } - if(m_contextParent[ CP_MASTER ] && !m_contextParent[ CP_MASTER ]->winIsHidden() && m_specialPowerShortcutParent->winIsHidden()) - showSpecialPowerShortcut(); - - for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ ) - { - GameWindow *win; - const CommandButton *command; - // get the window - win = m_specialPowerShortcutButtons[ i ]; - - if( win->winIsHidden() == TRUE ) - continue; - // get the command from the control - command = (const CommandButton *)GadgetButtonGetData(win); - //command = (const CommandButton *)win->winGetUserData(); - if( command == nullptr ) - continue; - - - win->winClearStatus( WIN_STATUS_NOT_READY ); - win->winClearStatus( WIN_STATUS_ALWAYS_COLOR ); - - - // is the command available - - CommandAvailability availability = COMMAND_RESTRICTED; - - const SpecialPowerTemplate *spTemplate = command->getSpecialPowerTemplate(); - Object *obj = nullptr; - if( spTemplate ) - { - obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( command->getSpecialPowerTemplate()->getSpecialPowerType() ); - availability = getCommandAvailability( command, obj, win ); - } - else if( command->getCommandType() == GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE ) - { - availability = COMMAND_HIDDEN; - Object *obj = ThePlayerList->getLocalPlayer()->findAnyExistingObjectWithThingTemplate( command->getThingTemplate() ); - if( obj ) - { - //Make command available if it isn't a special power template shortcut power. - availability = COMMAND_AVAILABLE; - - UnsignedInt mostReadyPercentage; - obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerForThing( command->getThingTemplate(), mostReadyPercentage ); - if( obj ) - { - //Ugh... hacky. - //Look for a command button for a special power and if so, then get the command availability for it. - const CommandSet *commandSet = findCommandSet( obj->getCommandSetString() ); - if( commandSet ) - { - for( Int commandIndex = 0; commandIndex < MAX_COMMANDS_PER_SET; commandIndex++ ) - { - const CommandButton *evalButton = commandSet->getCommandButton( commandIndex ); - GameWindow *evalButtonWin = m_commandWindows[ commandIndex ]; - if( evalButton && evalButton->getCommandType() == GUI_COMMAND_SPECIAL_POWER ) - { - //We want to evaluate the special powerbutton... but apply the clock overlay to our button! - availability = getCommandAvailability( evalButton, obj, evalButtonWin, win ); - break; - } - } - } - } - } - } - - // enable/disable the window control - switch( availability ) - { - case COMMAND_HIDDEN: - win->winHide( TRUE ); - break; - case COMMAND_RESTRICTED: - win->winEnable( FALSE ); - break; - case COMMAND_NOT_READY: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_NOT_READY ); - break; - case COMMAND_CANT_AFFORD: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_ALWAYS_COLOR ); - break; - default: - win->winEnable( TRUE ); - break; - } - } -} - -//------------------------------------------------------------------------------------------------- -void ControlBar::drawSpecialPowerShortcutMultiplierText() -{ - for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; i++ ) - { - GameWindow *win; - const CommandButton *command; - // get the window - win = m_specialPowerShortcutButtons[ i ]; - - if( win->winIsHidden() == TRUE ) - continue; - // get the command from the control - command = (const CommandButton *)GadgetButtonGetData(win); - //command = (const CommandButton *)win->winGetUserData(); - if( command == nullptr ) - continue; - - //draw superweapon ready multipliers - for( int i = 0; i < MAX_SPECIAL_POWER_SHORTCUTS; i++ ) - { - if( !m_shortcutDisplayStrings[ i ] ) - { - //m_shortcutDisplayStrings[ i ] = TheDisplayStringManager->newDisplayString(); - //m_shortcutDisplayStrings[ i ]->setFont( TheFontLibrary->getFont( "Arial", 16, false ) ); - } - - const SpecialPowerTemplate *spTemplate = command->getSpecialPowerTemplate(); - Int numReady = 0; - if( spTemplate ) - { - numReady = ThePlayerList->getLocalPlayer()->countReadyShortcutSpecialPowersOfType( spTemplate->getSpecialPowerType() ); - } - if( numReady > 1 ) // Lorenzen changed... Displaying a "1" is superfluous - { - UnicodeString unibuffer; - unibuffer.format( L"%d", numReady ); - - GadgetButtonSetText( win, unibuffer ); - - //m_shortcutDisplayStrings[ i ]->setText( unibuffer ); - //TheControlBar->m_shortcutDisplayStrings[ i ]->draw( 600, i * 40 + 40, GameMakeColor(255,255,255,255), GameMakeColor(0,0,0,0), 0, 0 ); - } - else - { - UnicodeString unibuffer; - GadgetButtonSetText( win, unibuffer ); - //TheDisplayStringManager->freeDisplayString( m_shortcutDisplayStrings[ i ] ); - //m_shortcutDisplayStrings[ i ] = nullptr; - } - } - } -} - -void ControlBar::animateSpecialPowerShortcut( Bool isOn ) -{ - if(!m_specialPowerShortcutParent || !m_animateWindowManagerForGenShortcuts || !m_currentlyUsedSpecialPowersButtons) - return; - Bool dontAnimate = TRUE; - for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; ++i ) - { - if (m_specialPowerShortcutButtons[i]->winGetUserData()) - { - dontAnimate = FALSE; - break; - } - } - if(dontAnimate) - return; - - if(isOn) - { - m_animateWindowManagerForGenShortcuts->reset(); - m_animateWindowManagerForGenShortcuts->registerGameWindow(m_specialPowerShortcutParent,WIN_ANIMATION_SLIDE_RIGHT,TRUE,500,0); - } - else - { - m_animateWindowManagerForGenShortcuts->reverseAnimateWindow(); - } -} - -void ControlBar::showSpecialPowerShortcut() -{ - if(TheScriptEngine->isGameEnding() || !m_specialPowerShortcutParent - ||!m_specialPowerShortcutButtons || !ThePlayerList || !ThePlayerList->getLocalPlayer()) - return; - Bool dontAnimate = TRUE; - for( Int i = 0; i < m_currentlyUsedSpecialPowersButtons; ++i ) - { - if (m_specialPowerShortcutButtons[i]->winGetUserData()) - { - dontAnimate = FALSE; - break; - } - } - if( dontAnimate || (!ThePlayerList->getLocalPlayer()->hasAnyShortcutSpecialPower() && !hasAnyShortcutSelection()) ) - return; - m_specialPowerShortcutParent->winHide(FALSE); - populateSpecialPowerShortcut(ThePlayerList->getLocalPlayer()); - -} - -void ControlBar::hideSpecialPowerShortcut() -{ - if(!m_specialPowerShortcutParent) - return; - - m_specialPowerShortcutParent->winHide(TRUE); - -} - -void ControlBar::setFullViewportHeight() -{ - TheTacticalView->setHeight(TheDisplay->getHeight()); -} - -void ControlBar::setScaledViewportHeight() -{ - TheTacticalView->setHeight(TheDisplay->getHeight() * TheGlobalData->m_viewportHeightScale); -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp deleted file mode 100644 index 79e70a04c2b..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarBeacon.cpp ///////////////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Methods specific to the control bar beacon display -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/NameKeyGenerator.h" -#include "Common/ThingTemplate.h" -#include "GameClient/ControlBar.h" -#include "GameClient/Drawable.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/InGameUI.h" -#include "GameLogic/Object.h" - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::populateBeacon( Object *beacon ) -{ - - // set the portrait for the thing being constructed - setPortraitByObject( beacon ); - - static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText"); - static NameKeyType staticTextID = NAMEKEY("ControlBar.wnd:StaticTextBeaconLabel"); - static NameKeyType clearButtonID = NAMEKEY("ControlBar.wnd:ButtonClearBeaconText"); - - GameWindow *textEntryWin = TheWindowManager->winGetWindowFromId(nullptr, textID); - GameWindow *staticTextWin = TheWindowManager->winGetWindowFromId(nullptr, staticTextID); - GameWindow *buttonWin = TheWindowManager->winGetWindowFromId(nullptr, clearButtonID); - - if (beacon->isLocallyControlled()) - { - if (textEntryWin) - { - textEntryWin->winHide(FALSE); - GadgetTextEntrySetText( textEntryWin, beacon->getDrawable()->getCaptionText() ); - TheWindowManager->winSetFocus( textEntryWin ); - } - - if (staticTextWin) - staticTextWin->winHide(FALSE); - - if (buttonWin) - buttonWin->winHide(FALSE); - } - else - { - if (textEntryWin) - textEntryWin->winHide(TRUE); - - if (staticTextWin) - staticTextWin->winHide(TRUE); - - if (buttonWin) - buttonWin->winHide(TRUE); - } -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextBeacon() -{ - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType BeaconWindowInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - if (msg == GWM_CHAR && mData1 == KEY_ESC) - { - TheInGameUI->deselectAllDrawables(TRUE); // there should only be one beacon and nothing else selected - return MSG_HANDLED; - } - - return MSG_IGNORED; - -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp deleted file mode 100644 index f5e1cc6070e..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp +++ /dev/null @@ -1,1530 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarCommand.cpp //////////////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Methods specific to the control bar unit commands -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/NameKeyGenerator.h" -#include "Common/ThingTemplate.h" -#include "Common/ThingFactory.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/PlayerTemplate.h" -#include "Common/SpecialPower.h" -#include "Common/Upgrade.h" -#include "Common/BuildAssistant.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/Module/BattlePlanUpdate.h" -#include "GameLogic/Module/DozerAIUpdate.h" -#include "GameLogic/Module/OverchargeBehavior.h" -#include "GameLogic/Module/ProductionUpdate.h" -#include "GameLogic/Module/SpecialPowerModule.h" -#include "GameLogic/Module/TransportContain.h" -#include "GameLogic/Module/MobNexusContain.h" -#include "GameLogic/Module/SpecialAbilityUpdate.h" -#include "GameLogic/Module/VeterancyGainCreate.h" -#include "GameLogic/Module/HackInternetAIUpdate.h" -#include "GameLogic/Weapon.h" - -#include "GameClient/InGameUI.h" -#include "GameClient/Drawable.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetPushButton.h" - - -// PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// -static GameWindow *commandWindows[ MAX_COMMANDS_PER_SET ]; -Bool commandWindowsInitialized = FALSE; -static Color BuildClockColor = GameMakeColor(0,0,0,100); -// STATIC DATA STORAGE //////////////////////////////////////////////////////////////////////////// -ControlBar::ContainEntry ControlBar::m_containData[ MAX_COMMANDS_PER_SET ]; - -//------------------------------------------------------------------------------------------------- -/** Note, this iterate callback assumes that the inventory exit buttons appear in a - * continuous order in the layout of the command set */ -//------------------------------------------------------------------------------------------------- -struct PopulateInvButtonData -{ - Int currIndex; ///< index that represents the control we're talking about - Int maxIndex; ///< this is the last valid control we can use - GameWindow **controls; ///< the controls - Object *transport; ///< the transport -}; - -//------------------------------------------------------------------------------------------------- -/** Used for the callback iterator on transport contents to do the actual GUI fill */ -//------------------------------------------------------------------------------------------------- -void ControlBar::populateInvDataCallback( Object *obj, void *userData ) -{ - PopulateInvButtonData *data = (PopulateInvButtonData *)userData; - - // - // if we're beyond the max the GUI can support, design needs to change the parameters - // of the transport object to carry less things - // - if( data->currIndex > data->maxIndex ) - { - - DEBUG_CRASH( ("There is not enough GUI slots to hold the # of items inside a '%s'", - data->transport->getTemplate()->getName().str()) ); - return; - - } - - // get the window control that we're going to put our smiling faces in - GameWindow *control = data->controls[ data->currIndex ]; - DEBUG_ASSERTCRASH( control, ("populateInvDataCallback: Control not found") ); - - // assign our control and object id to the transport data - m_containData[ data->currIndex ].control = control; - m_containData[ data->currIndex ].objectID = obj->getID(); - data->currIndex++; - - // fill out the control enabled, hilite, and pushed images - const Image *image; - image = obj->getTemplate()->getButtonImage(); - GadgetButtonSetEnabledImage( control, image ); - - //No longer used - //image = TheMappedImageCollection->findImageByName( obj->getTemplate()->getInventoryImageName( INV_IMAGE_HILITE ) ); - //GadgetButtonSetHiliteImage( control, image ); - //image = TheMappedImageCollection->findImageByName( obj->getTemplate()->getInventoryImageName( INV_IMAGE_PUSHED ) ); - //GadgetButtonSetHiliteSelectedImage( control, image ); - - //Show the contained object's veterancy symbol! - image = calculateVeterancyOverlayForObject( obj ); - GadgetButtonDrawOverlayImage( control, image ); - - // enable the control - control->winEnable( TRUE ); - -} - -//------------------------------------------------------------------------------------------------- -/** Transports have an extra special manipulation of the user interface. They get to look - * at the available command set, and any of the commands that are TransportExit commands *AND* - * there is actually an object to represent that slot contained in the transport, the - * inventory picture of the contained object will be displayed in the window control for - * that TransportExit command. Also, transports will HIDE any TransportExit controls found - * in the command set that represent slots that *DO NOT EXIST* for the transport (that is, - * the transport can only hold 4 things, but the GUI has buttons for 8 things). For slots - * that are empty but present in the transport the UI will show a disabled button to show - * the user that there is an open "slot" */ -//------------------------------------------------------------------------------------------------- -void ControlBar::doTransportInventoryUI( Object *transport, const CommandSet *commandSet ) -{ -/// @todo srj -- remove hard-coding here, please - //static const CommandButton *exitCommand = findCommandButton( "Command_TransportExit" ); - - // sanity - if( transport == nullptr || commandSet == nullptr ) - return; - - // get the transport contain module - ContainModuleInterface *contain = transport->getContain(); - - // sanity - if( contain == nullptr ) - return; - - // how many slots do we have inside the transport - Int transportMax = contain->getContainMax(); - - // - // first, hide any windows in 'm_commandWindows' that correspond to TransportExit commands - // within the 'commandSet' that are overflow slots (the ui could be showing more inventory - // exit button slots than there are slots in the transport) - // - // The extra slots bit means that a tank that takes up three slots will make two transport - // buttons disappear off the end to show he takes up more room. - transportMax = transportMax - contain->getExtraSlotsInUse(); - - Int firstInventoryIndex = -1; - Int lastInventoryIndex = -1; - Int inventoryCommandCount = 0; - - const CommandButton *commandButton; - for( Int i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // get command button - commandButton = commandSet->getCommandButton(i); - - // is this an inventory exit command - if( commandButton && commandButton->getCommandType() == GUI_COMMAND_EXIT_CONTAINER ) - { - - // record the index of the control for the first inventory exit command we found - if( firstInventoryIndex == -1 ) - firstInventoryIndex = i; - - // - // since we're assuming all inventory exit commands appear in a continuous order, - // we need to also need to keep track of what is the last valid inventory command index - // - lastInventoryIndex = i; - - // increment our count of available inventory exit commands found for the set - inventoryCommandCount++; - - // show the window, but disable by default unless something is actually loaded in there - m_commandWindows[ i ]->winHide( FALSE ); - m_commandWindows[ i ]->winEnable( FALSE ); - - //Clear any potential veterancy rank, or else we'll see it when it's empty! - GadgetButtonDrawOverlayImage( m_commandWindows[ i ], nullptr ); - - //Unmanned vehicles don't have any commands available -- in fact they are hidden! - if( transport->isDisabledByType( DISABLED_UNMANNED ) ) - { - m_commandWindows[ i ]->winHide( TRUE ); - } - - - // is this where we set the cameos disabled when container is subdued? - - // if we've counted more UI spots than the transport can hold, hide this command window - if( inventoryCommandCount > transportMax ) - m_commandWindows[ i ]->winHide( TRUE ); - - // - // set the inventory exit command into the window (even if it's one of the hidden ones - // it's OK cause we'll never see it to click it - // - setControlCommand( m_commandWindows[ i ], commandButton ); - - } - - } - - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - - // - // now, iterate the contained items of the transport and for each one we find we will - // populate a user interface button with its inventory picture and store the inventory - // data inside the control bar so we can respond to the button when its clicked - // - if( lastInventoryIndex >= 0 ) // just for sanity - { - PopulateInvButtonData data; - - data.controls = m_commandWindows; - data.currIndex = firstInventoryIndex; - data.maxIndex = lastInventoryIndex; - data.transport = transport; - contain->iterateContained( populateInvDataCallback, &data, FALSE ); - - } - - // - // save the last recorded inventory count so we know when we have to redo the gui when - // something exits or enters - // - m_lastRecordedInventoryCount = contain->getContainCount(); - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::populateCommand( Object *obj ) -{ - const CommandSet *commandSet; - Int i; - Player *player = obj->getControllingPlayer(); - - // reset contain data - resetContainData(); - - // reset the build queue data - resetBuildQueueData(); - - // get command set - commandSet = findCommandSet( obj->getCommandSetString() ); - - // if no command set match is found hide all the buttons - if( commandSet == nullptr ) - { - - // hide all the buttons - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - if (m_commandWindows[ i ]) - { - m_commandWindows[ i ]->winHide( TRUE ); - } - - // nothing left to do - return; - - } - - // transports do extra special things with the user interface buttons - if( obj->getContain() && obj->getContain()->isDisplayedOnControlBar() ) - doTransportInventoryUI( obj, commandSet ); - - // populate the button with commands defined - const CommandButton *commandButton; - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // get command button - commandButton = commandSet->getCommandButton(i); - - // if button is not present, just hide the window - if( commandButton == nullptr ) - { - - // hide window on interface - m_commandWindows[ i ]->winHide( TRUE ); - - } - else - { - - //Script only command -- don't show it in the UI. - if( BitIsSet( commandButton->getOptions(), SCRIPT_ONLY ) ) - { - m_commandWindows[ i ]->winHide( TRUE ); - continue; - } - // - // inventory exit commands were a special case already taken care above ... we needed - // to iterage through the containment for transport objects and fill out any available - // inventory exit buttons on the UI - // - if( commandButton->getCommandType() != GUI_COMMAND_EXIT_CONTAINER ) - { - - // make sure the window is not hidden - m_commandWindows[ i ]->winHide( FALSE ); - - // enable by default - m_commandWindows[ i ]->winEnable( TRUE ); - - // populate the visible button with data from the command button - setControlCommand( m_commandWindows[ i ], commandButton ); - - // - // commands that require sciences we don't have are hidden so they never show up - // cause we can never pick "another" general technology throughout the game - // - if( BitIsSet( commandButton->getOptions(), NEED_SPECIAL_POWER_SCIENCE ) ) - { - const SpecialPowerTemplate *power = commandButton->getSpecialPowerTemplate(); - - if( power && power->getRequiredScience() != SCIENCE_INVALID ) - { - if( commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE && - commandButton->getCommandType() != GUI_COMMAND_PLAYER_UPGRADE && - commandButton->getCommandType() != GUI_COMMAND_OBJECT_UPGRADE ) - { - if( player->hasScience( power->getRequiredScience() ) == FALSE ) - { - //Hide the power - m_commandWindows[ i ]->winHide( TRUE ); - } - else - { - //The player does have the special power! Now determine if the images require - //enhancement based on upgraded versions. This is determined by the command - //button specifying a vector of sciences in the command button. - Int bestIndex = -1; - ScienceType science; - for( size_t scienceIndex = 0; scienceIndex < commandButton->getScienceVec().size(); ++scienceIndex ) - { - science = commandButton->getScienceVec()[ scienceIndex ]; - - //Keep going until we reach the end or don't have the required science! - if( player->hasScience( science ) ) - { - bestIndex = scienceIndex; - } - else - { - break; - } - } - - if( bestIndex != -1 ) - { - //Now get the best sciencetype. - science = commandButton->getScienceVec()[ bestIndex ]; - - const CommandSet *commandSet1; - const CommandSet *commandSet3; - const CommandSet *commandSet8; - Int i; - - // get command set - if( !player || !player->getPlayerTemplate() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1().isEmpty() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3().isEmpty() - || player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8().isEmpty() ) - { - continue; - } - commandSet1 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank1() ); - commandSet3 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank3() ); - commandSet8 = findCommandSet( player->getPlayerTemplate()->getPurchaseScienceCommandSetRank8() ); - - if( !commandSet1 || !commandSet3 || !commandSet8 ) - { - continue; - } - - Bool found = FALSE; - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_1; i++ ) - { - const CommandButton *command = commandSet1->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, FALSE, TRUE ); - found = TRUE; - break; - } - } - } - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_3; i++ ) - { - const CommandButton *command = commandSet3->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, FALSE, TRUE ); - found = TRUE; - break; - } - } - } - for( i = 0; !found && i < MAX_PURCHASE_SCIENCE_RANK_8; i++ ) - { - const CommandButton *command = commandSet8->getCommandButton( i ); - if( command && command->getCommandType() == GUI_COMMAND_PURCHASE_SCIENCE ) - { - //All purchase sciences specify a single science. - if( command->getScienceVec().empty() ) - { - DEBUG_CRASH( ("Commandbutton %s is a purchase science button without any science! Please add it.", command->getName().str() ) ); - } - else if( command->getScienceVec()[0] == science ) - { - commandButton->copyImagesFrom( command, TRUE ); - commandButton->copyButtonTextFrom( command, FALSE, TRUE ); - found = TRUE; - break; - } - } - } - } - } - } - } - - } - - } - - } - - } - - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - - - // - // for objects that have a production exit interface, we may have a rally point set. - // if we do, we want to show that rally point in the world - // - ExitInterface *exit = obj->getObjectExitInterface(); - if( exit ) - { - - // - // if a rally point is set, show the rally point, if we don't have it set hide any rally - // point we might have visible - // - showRallyPoint( exit->getRallyPoint() ); - - } - - // - // to avoid a one frame delay where windows may become enabled/disabled, run the update - // at once to get it all in the correct state immediately - // - updateContextCommand(); - -} - -//------------------------------------------------------------------------------------------------- -/** reset transport data */ -//------------------------------------------------------------------------------------------------- -void ControlBar::resetContainData() -{ - Int i; - - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - - m_containData[ i ].control = nullptr; - m_containData[ i ].objectID = INVALID_ID; - - } - -} - -//------------------------------------------------------------------------------------------------- -/** reset the build queue data we use to die queue entries to control */ -//------------------------------------------------------------------------------------------------- -void ControlBar::resetBuildQueueData() -{ - Int i; - - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - { - - m_queueData[ i ].control = nullptr; - m_queueData[ i ].type = PRODUCTION_INVALID; - m_queueData[ i ].productionID = PRODUCTIONID_INVALID; - m_queueData[ i ].upgradeToResearch = nullptr; - - } - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::populateBuildQueue( Object *producer ) -{ -/// @todo srj -- remove hard-coding here, please - static const CommandButton *cancelUnitCommand = findCommandButton( "Command_CancelUnitCreate" ); -/// @todo srj -- remove hard-coding here, please - static const CommandButton *cancelUpgradeCommand = findCommandButton( "Command_CancelUpgradeCreate" ); - static NameKeyType buildQueueIDs[ MAX_BUILD_QUEUE_BUTTONS ]; - static Bool idsInitialized = FALSE; - Int i; - - // reset the build queue data - resetBuildQueueData(); - - // get name key ids for the build queue buttons - if( idsInitialized == FALSE ) - { - AsciiString buttonName; - - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - { - - buttonName.format( "ControlBar.wnd:ButtonQueue%02d", i + 1 ); - buildQueueIDs[ i ] = TheNameKeyGenerator->nameToKey( buttonName ); - - } - - idsInitialized = TRUE; - - } - - // get window pointers to all the buttons for the build queue - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - { - - // get window commented out cause I believe we already set this. We'll see in a few minutes - m_queueData[ i ].control = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_BUILD_QUEUE ], - buildQueueIDs[ i ] ); - - // disable window by default - m_queueData[ i ].control->winEnable( FALSE ); - - //Clear the status because this button doesn't use it -- and if it's set, it'll - //become invisible meaning the image that was there will be showed. - m_queueData[ i ].control->winClearStatus( WIN_STATUS_USE_OVERLAY_STATES ); - - // set the text of the window to nothing by default - GadgetButtonSetText( m_queueData[ i ].control, L"" ); - - //Clear any potential veterancy rank, or else we'll see it when it's empty! - GadgetButtonDrawOverlayImage( m_queueData[ i ].control, nullptr ); - - } - - // step through each object being built and set the image data for the buttons - ProductionUpdateInterface *pu = producer->getProductionUpdateInterface(); - if( pu == nullptr ) - return; // sanity - const ProductionEntry *production; - Int windowIndex = 0; - const Image *image; - for( production = pu->firstProduction(); - production; - production = pu->nextProduction( production ) ) - { - - // don't go above how many queue windows we have - if( windowIndex >= MAX_BUILD_QUEUE_BUTTONS ) - break; // exit for - - // set the command into the queue button - if( production->getProductionType() == PRODUCTION_UNIT ) - { - - // set the control command - setControlCommand( m_queueData[ windowIndex ].control, cancelUnitCommand ); - m_queueData[ windowIndex ].type = PRODUCTION_UNIT; - m_queueData[ windowIndex ].productionID = production->getProductionID(); - - // set the images - m_queueData[ windowIndex ].control->winEnable( TRUE ); - m_queueData[ windowIndex ].control->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - image = production->getProductionObject()->getButtonImage(); - GadgetButtonSetEnabledImage( m_queueData[ windowIndex ].control, image ); - - //No longer used. - //image = TheMappedImageCollection->findImageByName( production->getProductionObject()->getInventoryImageName( INV_IMAGE_HILITE ) ); - //GadgetButtonSetHiliteSelectedImage( m_queueData[ windowIndex ].control, image ); - //image = TheMappedImageCollection->findImageByName( production->getProductionObject()->getInventoryImageName( INV_IMAGE_PUSHED ) ); - //GadgetButtonSetHiliteImage( m_queueData[ windowIndex ].control, image ); - - //Show the veterancy rank of the object being constructed in the queue - const Image *image = calculateVeterancyOverlayForThing( production->getProductionObject() ); - GadgetButtonDrawOverlayImage( m_queueData[ windowIndex ].control, image ); - // - // note we're not setting a disabled image into the queue button ... when there is - // nothing in the queue we set the button to disabled, we want to leave the disabled - // queue button graphic we already have in place - // - // image = TheMappedImageCollection->findImageByName( production->getProductionObject()->getInventoryImageName( INV_IMAGE_DISABLED ) ); - // GadgetButtonSetDisabledImage( m_queueData[ windowIndex ].control, image ); - - } - else - { - const UpgradeTemplate *ut = production->getProductionUpgrade(); - - // set the control command - setControlCommand( m_queueData[ windowIndex ].control, cancelUpgradeCommand ); - m_queueData[ windowIndex ].type = PRODUCTION_UPGRADE; - m_queueData[ windowIndex ].upgradeToResearch = production->getProductionUpgrade(); - - // set the images - m_queueData[ windowIndex ].control->winEnable( TRUE ); - m_queueData[ windowIndex ].control->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - image = ut->getButtonImage(); - GadgetButtonSetEnabledImage( m_queueData[ windowIndex ].control, image ); - - //No longer used - //image = TheMappedImageCollection->findImageByName( ut->getQueueImageName( UpgradeTemplate::UPGRADE_HILITE ) ); - //GadgetButtonSetHiliteSelectedImage( m_queueData[ windowIndex ].control, image ); - //image = TheMappedImageCollection->findImageByName( ut->getQueueImageName( UpgradeTemplate::UPGRADE_PUSHED ) ); - //GadgetButtonSetHiliteImage( m_queueData[ windowIndex ].control, image ); - // - // note we're not setting a disabled image into the queue button ... when there is - // nothing in the queue we set the button to disabled, we want to leave the disabled - // queue button graphic we already have in place - // - // image = TheMappedImageCollection->findImageByName( ut->getQueueImageName( UpgradeTemplate::UPGRADE_DISABLED ) ); - // GadgetButtonSetDisabledImage( m_queueData[ windowIndex ].control, image ); - - } - - // we have filled up this window now - windowIndex++; - - } - - // - // save the count of things being produced in the build queue, when it changes we will - // repopulate the queue to visually show the change - // - m_displayedQueueCount = pu->getProductionCount(); - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextCommand() -{ - Object *obj = nullptr; - Int i; - - // get object - if( m_currentSelectedDrawable ) - obj = m_currentSelectedDrawable->getObject(); - - // - // the contents of objects are usually showed on the UI, when those contents change - // we always to update the UI - // - ContainModuleInterface *contain = obj ? obj->getContain() : nullptr; - if( contain && contain->getContainMax() > 0 && - m_lastRecordedInventoryCount != contain->getContainCount() ) - { - - // record this ast the last known number - m_lastRecordedInventoryCount = contain->getContainCount(); - - // re-evaluate the UI because something has changed - evaluateContextUI(); - - } - - // get production update for those objects that have one - ProductionUpdateInterface *pu = obj ? obj->getProductionUpdateInterface() : nullptr; - - // - // when we have a production update, we show the build queue when there is actually - // something in the queue, otherwise we show the selection portrait for the object ... so if - // the queue is visible we need to check to see if we should hide it and show the portrait, - // and if the queue is hidden, we need to check and see if it should become shown - // - if( m_contextParent[ CP_BUILD_QUEUE ]->winIsHidden() == TRUE ) - { - - if( pu && pu->firstProduction() != nullptr ) - { - - // don't show the portrait image - setPortraitByObject( nullptr ); - - // show the build queue - m_contextParent[ CP_BUILD_QUEUE ]->winHide( FALSE ); - populateBuildQueue( obj ); - - } - - } - else - { - - if( pu && pu->firstProduction() == nullptr ) - { - - // hide the build queue - m_contextParent[ CP_BUILD_QUEUE ]->winHide( TRUE ); - - // show the portrait image - setPortraitByObject( obj ); - - } - - } - - // update a visible production queue - if( m_contextParent[ CP_BUILD_QUEUE ]->winIsHidden() == FALSE ) - { - - // when the build queue is enabled, the selected portrait cannot be shown - setPortraitByObject( nullptr ); - - // - // when showing a production queue, when the production count changes of the producer - // object (the thing we have selected for the control bar) we will repopulate the - // windows to visually show the new production linup - // - if( pu ) - { - - // update the whole queue as necessary - if( pu->getProductionCount() != m_displayedQueueCount ) - populateBuildQueue( obj ); - - // - // update the build percentage on the first thing (the thing that's being built) - // in the queue - // - const ProductionEntry *produce = pu->firstProduction(); - if( produce ) - { - static NameKeyType winID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonQueue01" ); - GameWindow *win = TheWindowManager->winGetWindowFromId( m_contextParent[ CP_BUILD_QUEUE ], winID ); - - DEBUG_ASSERTCRASH( win, ("updateContextCommand: Unable to find first build queue button") ); - // UnicodeString text; - // - // text.format( L"%.0f%%", produce->getPercentComplete() ); - // GadgetButtonSetText( win, text ); - - GadgetButtonDrawInverseClock(win,produce->getPercentComplete(), m_buildUpClockColor); - - } - - } - - } - - // evaluate each command on whether or not it should be enabled - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - GameWindow *win; - const CommandButton *command; - - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // get the window - win = m_commandWindows[ i ]; - - // only consider commands for windows that are actually shown - //`tbd: fix the bug here, that is that if we don't change the unit, we won't attempt to show - // these. - if( win->winIsHidden() == TRUE ) - continue; - - // get the command from the control - command = (const CommandButton *)GadgetButtonGetData(win); - //command = (const CommandButton *)win->winGetUserData(); - if( command == nullptr ) - continue; - - -// LORENZEN COMMENTED THIS OUT 8/11 - // Reason: ExitCameos can be greyed out when the container object gets subdued - -// // ignore transport/structure inventory commands, they are handled elsewhere -// if( command->getCommandType() == GUI_COMMAND_EXIT_CONTAINER ) -// { -// win->winSetStatus( WIN_STATUS_ALWAYS_COLOR ); //Don't let these buttons render in grayscale ever! -// continue; -// } -// else - { - win->winClearStatus( WIN_STATUS_NOT_READY ); - win->winClearStatus( WIN_STATUS_ALWAYS_COLOR ); - } - - // is the command available - CommandAvailability availability = getCommandAvailability( command, obj, win ); - - // enable/disable the window control - switch( availability ) - { - case COMMAND_HIDDEN: - win->winHide( TRUE ); - break; - case COMMAND_RESTRICTED: - win->winEnable( FALSE ); - break; - case COMMAND_NOT_READY: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_NOT_READY ); - break; - case COMMAND_CANT_AFFORD: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_ALWAYS_COLOR ); - break; - default: - win->winEnable( TRUE ); - break; - } - - //Determine by the production type of this button, whether or not the created object - //will have a veterancy rank - if( command->getCommandType() != GUI_COMMAND_EXIT_CONTAINER ) - { - //Already handled for contained members -- see ControlBar::populateButtonProc() - const Image *image = calculateVeterancyOverlayForThing( command->getThingTemplate() ); - GadgetButtonDrawOverlayImage( win, image ); - } - - // - // for check-like commands we will keep the push button "pushed" or "unpushed" depending - // on the current running status of the command - // - if( BitIsSet( command->getOptions(), CHECK_LIKE )) - { - - // sanity, check like commands should have windows that are check like as well - DEBUG_ASSERTCRASH( BitIsSet( win->winGetStatus(), WIN_STATUS_CHECK_LIKE ), - ("updateContextCommand: Error, gadget window for command '%s' is not check-like!", - command->getName().str()) ); - - if( availability == COMMAND_ACTIVE ) - GadgetCheckLikeButtonSetVisualCheck( win, TRUE ); - else - GadgetCheckLikeButtonSetVisualCheck( win, FALSE ); - - } - - } - - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - -// // if we have a build tooltip layout, update it with the new data. -// repopulateBuildTooltipLayout(); - -} - -//------------------------------------------------------------------------------------------------- -const Image* ControlBar::calculateVeterancyOverlayForThing( const ThingTemplate *thingTemplate ) -{ - VeterancyLevel level = LEVEL_REGULAR; - - if( !thingTemplate ) - { - return nullptr; - } - - Player *player = ThePlayerList->getLocalPlayer(); - if( !player ) - { - return nullptr; - } - - //See if the thingTemplate has a VeterancyGainCreate - //This is HORROR CODE and needs to be optimized! - const VeterancyGainCreateModuleData *data = nullptr; - AsciiString modName; - const ModuleInfo& mi = thingTemplate->getBehaviorModuleInfo(); - for( Int modIdx = 0; modIdx < mi.getCount(); ++modIdx ) - { - modName = mi.getNthName(modIdx); - if( !modName.compare( "VeterancyGainCreate" ) ) - { - data = (const VeterancyGainCreateModuleData*)mi.getNthData( modIdx ); - - //It does, so see if the player has that upgrade - if( data ) - { - //If no science is specified, he gets it automatically (or check the science). - if( data->m_scienceRequired == SCIENCE_INVALID || player->hasScience( data->m_scienceRequired ) ) - { - //We do! So now check to see what the veterancy level would be. - if( data->m_startingLevel > level ) - { - level = data->m_startingLevel; - } - } - } - } - } - - //Return the appropriate image (including nullptr if no veterancy levels) - switch( level ) - { - case LEVEL_VETERAN: - return m_rankVeteranIcon; - case LEVEL_ELITE: - return m_rankEliteIcon; - case LEVEL_HEROIC: - return m_rankHeroicIcon; - } - return nullptr; -} - -//------------------------------------------------------------------------------------------------- -const Image* ControlBar::calculateVeterancyOverlayForObject( const Object *obj ) -{ - if( !obj ) - { - return nullptr; - } - VeterancyLevel level = obj->getVeterancyLevel(); - - //Return the appropriate image (including nullptr if no veterancy levels) - switch( level ) - { - case LEVEL_VETERAN: - return m_rankVeteranIcon; - case LEVEL_ELITE: - return m_rankEliteIcon; - case LEVEL_HEROIC: - return m_rankHeroicIcon; - } - return nullptr; -} - -//------------------------------------------------------------------------------------------------- -static Int getRappellerCount(Object* obj) -{ - Int num = 0; - const ContainedItemsList* items = obj->getContain() ? obj->getContain()->getContainedItemsList() : nullptr; - if (items) - { - for (ContainedItemsList::const_iterator it = items->begin(); it != items->end(); ++it ) - { - if ((*it)->isKindOf(KINDOF_CAN_RAPPEL)) - { - ++num; - } - } - } - return num; -} - -//------------------------------------------------------------------------------------------------- -/** What's the status between 'obj' and the 'command' at present. Can we do it? Are - * we already doing it? Can ya dig it? */ -//------------------------------------------------------------------------------------------------- -CommandAvailability ControlBar::getCommandAvailability( const CommandButton *command, - Object *obj, - GameWindow *win, - GameWindow *applyToWin, - Bool forceDisabledEvaluation ) const -{ - if( command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT - || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT ) - { - if (ThePlayerList && ThePlayerList->getLocalPlayer()) - obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( command->getSpecialPowerTemplate()->getSpecialPowerType() ); - else - obj = nullptr; - } - - //If we modify the button (like a gadget clock overlay), then sometimes we may wish to apply it to a specific different button. - //But if we don't specify anything (default), then make them the same. - if( !applyToWin ) - { - applyToWin = win; - } - - if (obj == nullptr) - return COMMAND_HIDDEN; // probably better than crashing.... - - Player *player = obj->getControllingPlayer(); - - if (obj->testScriptStatusBit(OBJECT_STATUS_SCRIPT_DISABLED) || obj->testScriptStatusBit(OBJECT_STATUS_SCRIPT_UNPOWERED)) - { - // if the object status is disabled or unpowered, you cannot do anything to it. - return COMMAND_HIDDEN; - } - - //Unmanned vehicles don't have any commands available -- in fact they are hidden! - if( obj->isDisabledByType( DISABLED_UNMANNED ) ) - { - return COMMAND_HIDDEN; - } - - //It's possible for command buttons to be a single use only type of a button -- like detonating a nuke from a convoy truck. - if( obj->hasSingleUseCommandBeenUsed() ) - { - return COMMAND_RESTRICTED; - } - - if( BitIsSet( command->getOptions(), MUST_BE_STOPPED ) ) - { - //This button can only be activated when the unit isn't moving! - AIUpdateInterface *ai = obj->getAI(); - if( ai && ai->isMoving() ) - { - return COMMAND_RESTRICTED; - } - } - - //Other disabled objects are unable to use buttons -- so gray them out. - Bool disabled = obj->isDisabled(); - - // if we are only disabled by being underpowered, and this button doesn't care, well, fix it - if (disabled - && BitIsSet(command->getOptions(), IGNORES_UNDERPOWERED) - && obj->getDisabledFlags().test(DISABLED_UNDERPOWERED) - && obj->getDisabledFlags().count() == 1) - { - disabled = false; - } - - if (disabled && !forceDisabledEvaluation) - { - - GUICommandType commandType = command->getCommandType(); - if( commandType != GUI_COMMAND_SELL && - commandType != GUI_COMMAND_EVACUATE && - commandType != GUI_COMMAND_EXIT_CONTAINER && - commandType != GUI_COMMAND_BEACON_DELETE && - commandType != GUI_COMMAND_SET_RALLY_POINT && - commandType != GUI_COMMAND_STOP && - commandType != GUI_COMMAND_SWITCH_WEAPON ) - { - if( getCommandAvailability( command, obj, win, applyToWin, TRUE ) == COMMAND_HIDDEN ) - { - return COMMAND_HIDDEN; - } - return COMMAND_RESTRICTED; - } - } - - // if the command requires an upgrade and we don't have it we can't do it - if( BitIsSet( command->getOptions(), NEED_UPGRADE ) ) - { - const UpgradeTemplate *upgradeT = command->getUpgradeTemplate(); - if (upgradeT) - { - // upgrades come in the form of player upgrades and object upgrades - if( upgradeT->getUpgradeType() == UPGRADE_TYPE_PLAYER ) - { - if( player->hasUpgradeComplete( upgradeT ) == FALSE ) - return COMMAND_RESTRICTED; - } - else if( upgradeT->getUpgradeType() == UPGRADE_TYPE_OBJECT && - obj->hasUpgrade( upgradeT ) == FALSE ) - { - return COMMAND_RESTRICTED; - } - } - } - - ProductionUpdateInterface *pu = obj->getProductionUpdateInterface(); - if( pu && pu->firstProduction() && BitIsSet( command->getOptions(), NOT_QUEUEABLE ) ) - { - //This button is designated so that it is incapable of building this upgrade/object - //when anything is in the production queue. - return COMMAND_RESTRICTED; - } - - Bool queueMaxed = pu ? ( pu->getProductionCount() == MAX_BUILD_QUEUE_BUTTONS ) : FALSE; - - switch( command->getCommandType() ) - { - case GUI_COMMAND_DOZER_CONSTRUCT: - { - const ThingTemplate * whatToBuild = command->getThingTemplate(); - // if the command is a dozer construct task and the object dozer is building anything - // this command is not available - if(whatToBuild) - { - BuildableStatus bStatus = whatToBuild->getBuildable(); - if (bStatus == BSTATUS_NO || (bStatus == BSTATUS_ONLY_BY_AI && obj->getControllingPlayer()->getPlayerType() != PLAYER_COMPUTER)) - return COMMAND_HIDDEN; - } - - // sanity, non dozer object - if( obj->isKindOf( KINDOF_DOZER ) == FALSE ) - return COMMAND_RESTRICTED; - - // get the dozer ai update interface - DozerAIInterface* dozerAI = nullptr; - if( obj->getAIUpdateInterface() == nullptr ) - return COMMAND_RESTRICTED; - - dozerAI = obj->getAIUpdateInterface()->getDozerAIInterface(); - - DEBUG_ASSERTCRASH( dozerAI != nullptr, ("Something KINDOF_DOZER must have a Dozer-like AIUpdate") ); - if( dozerAI == nullptr ) - return COMMAND_RESTRICTED; - - // if building anything at all right now we can't build another - if( dozerAI->isTaskPending( DOZER_TASK_BUILD ) == TRUE ) - return COMMAND_RESTRICTED; - - // return whether or not the player can build this thing - if( player->canBuild( whatToBuild ) == FALSE ) - return COMMAND_RESTRICTED; - - if( !player->canAffordBuild( whatToBuild ) ) - { - return COMMAND_RESTRICTED;//COMMAND_CANT_AFFORD; - } - - break; - } - - case GUI_COMMAND_SELL: - { - // if this is a sell command, is the object marked as "This cannot be sold?" - // if so, remove the button, otherwise, its available - if (obj->testScriptStatusBit(OBJECT_STATUS_SCRIPT_UNSELLABLE)) - return COMMAND_HIDDEN; - - //since the container can be subdued, , M Lorenzen 8/11 - if ( obj->isDisabledByType( DISABLED_SUBDUED ) ) - return COMMAND_RESTRICTED; - - break; - } - - case GUI_COMMAND_UNIT_BUILD: - { - // command is a unit build - if(command->getThingTemplate()) - { - BuildableStatus bStatus = command->getThingTemplate()->getBuildable(); - if (bStatus == BSTATUS_NO || (bStatus == BSTATUS_ONLY_BY_AI && obj->getControllingPlayer()->getPlayerType() != PLAYER_COMPUTER)) - return COMMAND_HIDDEN; - } - - if( queueMaxed ) - { - return COMMAND_RESTRICTED; - } - - // return whether or not the player can build this thing - //NOTE: Player::canBuild() only checks prerequisites! - if( player->canBuild( command->getThingTemplate() ) == FALSE ) - return COMMAND_RESTRICTED; - - CanMakeType makeType = TheBuildAssistant->canMakeUnit( obj, command->getThingTemplate() ); - if( makeType == CANMAKE_MAXED_OUT_FOR_PLAYER || makeType == CANMAKE_PARKING_PLACES_FULL ) - { - //Disable the button if the player has a max amount of these units in build queue or existence. - return COMMAND_RESTRICTED; - } - if( makeType == CANMAKE_NO_MONEY ) - { - return COMMAND_RESTRICTED; //COMMAND_CANT_AFFORD; - } - - break; - } - - case GUI_COMMAND_PLAYER_UPGRADE: - { - if( queueMaxed ) - { - return COMMAND_RESTRICTED; - } - // if we can build it, we must also NOT already have it or be building it - if( player->hasUpgradeComplete( command->getUpgradeTemplate() ) == TRUE || - player->hasUpgradeInProduction( command->getUpgradeTemplate() ) == TRUE ) - return COMMAND_CANT_AFFORD;//COMMAND_RESTRICTED; - - // if this is an upgrade create we must be able to build it. - if( TheUpgradeCenter->canAffordUpgrade( player, command->getUpgradeTemplate() ) == FALSE ) - return COMMAND_RESTRICTED;//COMMAND_CANT_AFFORD; - - for( size_t i = 0; i < command->getScienceVec().size(); i++ ) - { - ScienceType st = command->getScienceVec()[ i ]; - if( !player->hasScience( st ) ) - { - return COMMAND_RESTRICTED; - } - } - break; - } - - case GUI_COMMAND_OBJECT_UPGRADE: - { - if( queueMaxed ) - { - return COMMAND_RESTRICTED; - } - // no production update, can't possibly do this command - if( pu == nullptr ) - { - DEBUG_CRASH(("Objects that have Object-Level Upgrades must also have ProductionUpdate. Just cuz.")); - return COMMAND_RESTRICTED; - } - - // - // if this object already has this upgrade, or is researching it already in the queue - // we will disable the button so you can't build another one - // - if( obj->hasUpgrade( command->getUpgradeTemplate() ) == TRUE || - pu->isUpgradeInQueue( command->getUpgradeTemplate() ) == TRUE || - obj->affectedByUpgrade( command->getUpgradeTemplate() ) == FALSE ) - return COMMAND_CANT_AFFORD;//COMMAND_RESTRICTED; - - if( TheUpgradeCenter->canAffordUpgrade( player, command->getUpgradeTemplate() ) == FALSE ) - return COMMAND_RESTRICTED;//COMMAND_CANT_AFFORD; - - for( size_t i = 0; i < command->getScienceVec().size(); i++ ) - { - ScienceType st = command->getScienceVec()[ i ]; - if( !player->hasScience( st ) ) - { - return COMMAND_RESTRICTED; - } - } - break; - } - - case GUI_COMMAND_FIRE_WEAPON: - { - AIUpdateInterface *ai = obj->getAIUpdateInterface(); - - // no ai, can't possibly fire weapon - if( ai == nullptr ) - return COMMAND_RESTRICTED; - - // ask the ai if the weapon is ready to fire - const Weapon* w = obj->getWeaponInWeaponSlot( command->getWeaponSlot() ); - - // changed this to Log rather than Crash, because this can legitimately happen now for - // dozers and workers with mine-clearing stuff... (srj) - //DEBUG_ASSERTLOG( w, ("Unit %s's CommandButton %s is trying to access weaponslot %d, but doesn't have a weapon there in its FactionUnit ini entry.", - // obj->getTemplate()->getName().str(), command->getName().str(), (Int)command->getWeaponSlot() ) ); - - UnsignedInt now = TheGameLogic->getFrame(); - - /// @Kris -- We need to show the button as always available for anything with a 0 clip reload time. - if( w && w->getClipReloadTime( obj ) == 0 ) - { - return COMMAND_AVAILABLE; - } - - if( w == nullptr // No weapon - || w->getStatus() != READY_TO_FIRE // Weapon not ready - || w->getPossibleNextShotFrame() == now // Weapon ready, but could fire this exact frame (handle button flicker since it may be going to fire anyway) -/// @todo srj -- not sure why this next check is necessary, but the Comanche missile buttons will flicker without it. figure out someday. -/// @todo ml -- and note: that the "now-1" below causes zero-clip-reload weapons to never be ready, so I added this -/// If you make changes to this code, make sure that the DragonTank's firewall weapon can be retargeted while active, -/// that is, while the tank is squirting out flames all over the floor, you can click the firewall button (or "F"), -/// and re-target the firewall without having to stop or move in-between.. Thanks for reading - || (w->getPossibleNextShotFrame()==now-1) - ) - { - if ( w != nullptr ) - { - // only draw the clock when reloading a clip, not when merely between shots, since that's usually a tiny amount of time - if ( w->getStatus() == RELOADING_CLIP) - { - Int percent = w->getPercentReadyToFire() * 100; - GadgetButtonDrawInverseClock( applyToWin, percent, m_buildUpClockColor ); - } - return COMMAND_NOT_READY; - } - else - { - // if this is a mine-clearing button but we don't have the right weaponset, - // just declare it available... we'll switch weaponsets when the time comes - if ( - (command->getOptions() & USES_MINE_CLEARING_WEAPONSET) != 0 - && !obj->testWeaponSetFlag(WEAPONSET_MINE_CLEARING_DETAIL) - ) - { - return COMMAND_AVAILABLE; - } - - // no weapon in the slot means "gray me out" - return COMMAND_RESTRICTED; - } - } - - break; - } - - case GUI_COMMAND_GUARD: - case GUI_COMMAND_GUARD_WITHOUT_PURSUIT: - case GUI_COMMAND_GUARD_FLYING_UNITS_ONLY: - // always available - break; - - case GUI_COMMAND_COMBATDROP: - { - if( getRappellerCount(obj) <= 0 ) - return COMMAND_RESTRICTED; - break; - } - - case GUI_COMMAND_EXIT_CONTAINER: - { - - // - // this method is really used as a per frame update to see if we should enable - // disable a control ... inventory of objects shows as buttons have that enable - // disable logic handled elsewhere, where if the contained count of the entire - // container changes the UI is completely repopulated - // - - //since the container can be subdued, the above is no longer true, M Lorenzen 8/11 - if ( obj->isDisabledByType( DISABLED_SUBDUED ) ) - return COMMAND_RESTRICTED; - - break; - } - - case GUI_COMMAND_EVACUATE: - { - - // if we have no contained objects we can't evacuate anything - if( !obj->getContain() || obj->getContain()->getContainCount() <= 0 ) - return COMMAND_RESTRICTED; - - if ( obj->isDisabledByType( DISABLED_SUBDUED ) ) - return COMMAND_RESTRICTED; - - break; - } - - case GUI_COMMAND_EXECUTE_RAILED_TRANSPORT: - { - DockUpdateInterface *dui = obj->getDockUpdateInterface(); - - // if the dock is closed or not present this command is invalid - if( dui == nullptr || dui->isDockOpen() == FALSE ) - return COMMAND_RESTRICTED; - break; - } - - case GUI_COMMAND_SPECIAL_POWER: - case GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT: - case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT: - case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT: - { - // sanity - DEBUG_ASSERTCRASH( command->getSpecialPowerTemplate() != nullptr, - ("The special power in the command '%s' is null", command->getName().str()) ); - // get special power module from the object to execute it - SpecialPowerModuleInterface *mod = obj->getSpecialPowerModule( command->getSpecialPowerTemplate() ); - - if( mod == nullptr ) - { - // sanity ... we must have a module for the special power, if we don't somebody probably - // forgot to put it in the object - DEBUG_CRASH(( "Object %s does not contain special power module (%s) to execute. Did you forget to add it to the object INI?", - obj->getTemplate()->getName().str(), command->getSpecialPowerTemplate()->getName().str() )); - } - else if( mod->isReady() == FALSE ) - { - Int percent = mod->getPercentReady() * 100; - - GadgetButtonDrawInverseClock( applyToWin, percent, m_buildUpClockColor ); - return COMMAND_NOT_READY; - } - else if( SpecialAbilityUpdate *spUpdate = obj->findSpecialAbilityUpdate( command->getSpecialPowerTemplate()->getSpecialPowerType() ) ) - { - if( spUpdate && spUpdate->isPowerCurrentlyInUse( command ) ) - { - return COMMAND_RESTRICTED; - } - } - else if( mod->getSpecialPowerTemplate()->getSpecialPowerType() == SPECIAL_CHANGE_BATTLE_PLANS ) - { - static NameKeyType key_BattlePlanUpdate = NAMEKEY( "BattlePlanUpdate" ); - BattlePlanUpdate *update = (BattlePlanUpdate*)obj->findUpdateModule( key_BattlePlanUpdate ); - if( update && update->getCommandOption() & command->getOptions() ) - { - return COMMAND_ACTIVE; - } - } - - break; - } - - case GUI_COMMAND_TOGGLE_OVERCHARGE: - { - OverchargeBehaviorInterface *obi; - // search object behavior mdoules - for( BehaviorModule **bmi = obj->getBehaviorModules(); *bmi; ++bmi ) - { - // we're looking for the overcharge interface - obi = (*bmi)->getOverchargeBehaviorInterface(); - if( obi ) - { - if( obi->isOverchargeActive() ) - return COMMAND_ACTIVE; - } - } - break; - } - - // switch weapon command - case GUI_COMMAND_SWITCH_WEAPON: - { - // ask the ai which weapon is in the current slot - const Weapon* w = obj->getWeaponInWeaponSlot( command->getWeaponSlot() ); - - DEBUG_ASSERTCRASH( w, ("Unit %s's CommandButton %s is trying to access weaponslot %d, but doesn't have a weapon there in its FactionUnit ini entry.", - obj->getTemplate()->getName().str(), command->getName().str(), (Int)command->getWeaponSlot() ) ); - - if( w == nullptr) - return COMMAND_RESTRICTED; - - const DrawableList *selected = TheInGameUI->getAllSelectedDrawables(); - for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it ) - { - Drawable *draw = *it; - if( draw && draw->getObject() && draw->getObject()->isLocallyControlled() && draw->getObject()->getCurrentWeapon()) - { - WeaponSlotType wslot = draw->getObject()->getCurrentWeapon()->getWeaponSlot(); - if (wslot != command->getWeaponSlot()) - return COMMAND_AVAILABLE; - } - } - - return COMMAND_ACTIVE; - } - - case GUI_COMMAND_HACK_INTERNET: - { - AIUpdateInterface *ai = obj->getAI(); - if( ai ) - { - HackInternetAIInterface *hackAI = ai->getHackInternetAIInterface(); - if( hackAI && hackAI->isHackingPackingOrUnpacking() ) - { - return COMMAND_RESTRICTED; - } - } - return COMMAND_AVAILABLE; - } - - case GUI_COMMAND_STOP: - { - if( !BitIsSet( command->getOptions(), OPTION_ONE ) ) - { - return COMMAND_AVAILABLE; - } - - //We're dealing with a strategy center stop button. Only show the button - //if we're in bombardment mode (to stop the artillery cannon). - static NameKeyType key_BattlePlanUpdate = NAMEKEY( "BattlePlanUpdate" ); - BattlePlanUpdate *bpUpdate = (BattlePlanUpdate*)obj->findUpdateModule( key_BattlePlanUpdate ); - if( bpUpdate && bpUpdate->getActiveBattlePlan() != PLANSTATUS_BOMBARDMENT ) - { - return COMMAND_RESTRICTED; - } - return COMMAND_AVAILABLE; - } - - case GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE: - { - //We can *always* select a unit :) - return COMMAND_AVAILABLE; - } - } - - // all is well with the command - return COMMAND_AVAILABLE; - -} - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp deleted file mode 100644 index ebe753f7680..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp +++ /dev/null @@ -1,907 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarCommandProcessing.cpp ////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: This file contain just the method responsible for processing the actual command -// clicks from the window controls in the UI -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/BuildAssistant.h" -#include "Common/Money.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/Science.h" -#include "Common/SpecialPower.h" -#include "Common/ThingTemplate.h" -#include "Common/Upgrade.h" -#include "Common/PlayerTemplate.h" - -#include "GameClient/CommandXlat.h" -#include "GameClient/ControlBar.h" -#include "GameClient/Drawable.h" -#include "GameClient/Eva.h" -#include "GameClient/GameClient.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/InGameUI.h" -#include "GameClient/AnimateWindowManager.h" - -#include "GameLogic/GameLogic.h" -#include "GameLogic/Object.h" -#include "GameLogic/Module/ProductionUpdate.h" - - - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -struct SelectObjectsInfo -{ - const ThingTemplate *thingTemplate; - GameMessage *msg; -}; - -//------------------------------------------------------------------------------------------------- - -static void selectObjectOfType( Object* obj, void* selectObjectsInfo ) -{ - SelectObjectsInfo *soInfo = (SelectObjectsInfo*)selectObjectsInfo; - - //Do the templates match? - if( obj->getTemplate()->isEquivalentTo( soInfo->thingTemplate ) ) - { - //Okay, then add it to the selected group. - soInfo->msg->appendObjectIDArgument( obj->getID() ); - - Drawable *draw = obj->getDrawable(); - if( draw ) - { - TheInGameUI->selectDrawable( draw ); - } - } -} -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- - - -//------------------------------------------------------------------------------------------------- -/** Process a button transition message from the window system that should be for one of - * our GUI commands */ -//------------------------------------------------------------------------------------------------- -CBCommandStatus ControlBar::processCommandTransitionUI( GameWindow *control, GadgetGameMessage gadgetMessage ) -{ - // sanity, we won't process messages if we have no source object - if( m_currContext != CB_CONTEXT_MULTI_SELECT && - (m_currentSelectedDrawable == nullptr || - m_currentSelectedDrawable->getObject() == nullptr) ) - { - - if( m_currContext != CB_CONTEXT_NONE && - m_currContext != CB_CONTEXT_OBSERVER_INFO && - m_currContext != CB_CONTEXT_OBSERVER_LIST) - switchToContext( CB_CONTEXT_NONE, nullptr ); - return CBC_COMMAND_NOT_USED; - - } - - return CBC_COMMAND_USED; - -} - -//------------------------------------------------------------------------------------------------- -/** Process a button selected message from the window system that should be for one of - * our GUI commands */ -//------------------------------------------------------------------------------------------------- -CBCommandStatus ControlBar::processCommandUI( GameWindow *control, - GadgetGameMessage gadgetMessage ) -{ - // get the command pointer from the control user data we put in the button - const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(control); - if( !commandButton ) - { - DEBUG_CRASH( ("ControlBar::processCommandUI() -- Button activated has no data. Ignoring...") ); - return CBC_COMMAND_NOT_USED; - } - - // sanity, we won't process messages if we have no source object, - // unless we're CB_CONTEXT_PURCHASE_SCIENCE or GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT - if( m_currContext != CB_CONTEXT_MULTI_SELECT && - commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE && - commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT && - commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT && - commandButton->getCommandType() != GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE && - (m_currentSelectedDrawable == nullptr || m_currentSelectedDrawable->getObject() == nullptr) ) - { - - if( m_currContext != CB_CONTEXT_NONE ) - switchToContext( CB_CONTEXT_NONE, nullptr ); - return CBC_COMMAND_NOT_USED; - - } - - // sanity - if( control == nullptr ) - return CBC_COMMAND_NOT_USED; - - // the context sensitive gui only is only made of buttons ... sanity - if( control->winGetInputFunc() != GadgetPushButtonInput ) - return CBC_COMMAND_NOT_USED; - - - if( commandButton == nullptr ) - return CBC_COMMAND_NOT_USED; - - // if the button is flashing, tell it to stop flashing - commandButton->setFlashCount(0); - setFlash( FALSE ); - - if( commandButton->getCommandType() != GUI_COMMAND_EXIT_CONTAINER ) - { - GadgetButtonSetEnabledImage( control, commandButton->getButtonImage() ); - } - - // - // get the object that is driving the context sensitive UI if we're not in a multi - // select context - // - Object *obj = nullptr; - if( m_currContext != CB_CONTEXT_MULTI_SELECT && - commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE && - commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT && - commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT && - commandButton->getCommandType() != GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE ) - obj = m_currentSelectedDrawable->getObject(); - - //@todo Kris -- Special case code so convoy trucks can detonate nuke trucks -- if other things need this, - //rethink it. - if( obj && BitIsSet( commandButton->getOptions(), SINGLE_USE_COMMAND ) ) - { - /** @todo Added obj check because Single Use and Multi Select crash when used together, but with this check - * they just won't work. When the "rethinking" occurs, this can get fixed. Right now it is unused. - * Convoy Truck needs Multi Select so Single Use is turned off, and noone else has it. - */ - - //Make sure the command button is marked as used if it's a single use command. That way - //we can never press the button again. This was added specifically for nuke convoy trucks. - //When you click to detonate the nuke, it takes a few seconds to detonate in order to play - //a sound. But we want to disable the button after the first click. - obj->markSingleUseCommandUsed(); //Yeah, an object can only use one single use command... - } - - TheInGameUI->placeBuildAvailable( nullptr, nullptr ); - - //Play any available unit specific sound for button - Player *player = ThePlayerList->getLocalPlayer(); - if( player ) - { - AudioEventRTS sound = *commandButton->getUnitSpecificSound(); - sound.setPlayerIndex( player->getPlayerIndex() ); - TheAudio->addAudioEvent( &sound ); - } - - if( BitIsSet( commandButton->getOptions(), COMMAND_OPTION_NEED_TARGET ) ) - { - if (commandButton->getOptions() & USES_MINE_CLEARING_WEAPONSET) - { - TheMessageStream->appendMessage( GameMessage::MSG_SET_MINE_CLEARING_DETAIL ); - } - - //June 06, 2002 -- Major change - //I've added support for specific context sensitive commands which need targets just like - //other options may need. When we need a target, the user must move the cursor to a position - //where he wants the GUI command to take place. Older commands such as napalm strikes or daisy - //cutter drops simply needed the user to click anywhere he desired. - // - //Now, we have new commands that will only work when the user clicks on valid targets to interact - //with. For example, the terrorist can jack a car and convert it into a carbomb, but he has to - //click on a valid car. In this case the doCommandOrHint code will determine if the mode is valid - //or not and the cursor modes will be set appropriately. - TheInGameUI->setGUICommand( commandButton ); - } - else switch( commandButton->getCommandType() ) - { - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_DOZER_CONSTRUCT: - { - - // sanity - if( m_currentSelectedDrawable == nullptr ) - break; - - //Kris: September 27, 2002 - //Make sure we have enough CASH to build it WHEN we click the button to build it, - //before actually previewing the purchase, otherwise, cancel altogether. - const ThingTemplate *whatToBuild = commandButton->getThingTemplate(); - CanMakeType cmt = TheBuildAssistant->canMakeUnit( obj, whatToBuild ); - if (cmt == CANMAKE_NO_MONEY) - { - TheEva->setShouldPlay(EVA_InsufficientFunds); - TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" ); - break; - } - else if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - else if (cmt == CANMAKE_PARKING_PLACES_FULL) - { - TheInGameUI->message( "GUI:ParkingPlacesFull" ); - break; - } - else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER ) - { - TheInGameUI->message( "GUI:UnitMaxedOut" ); - break; - } - - // tell the UI that we want to build something so we get a building at the cursor - TheInGameUI->placeBuildAvailable( commandButton->getThingTemplate(), m_currentSelectedDrawable ); - - break; - - } - - - case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT: - { - //Determine the object that would construct it. - const SpecialPowerTemplate *spTemplate = commandButton->getSpecialPowerTemplate(); - DEBUG_ASSERTCRASH(spTemplate != nullptr, ("Special Power Button is missing Special Power template")); - - SpecialPowerType spType = spTemplate->getSpecialPowerType(); - Object* obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( spType ); - if( !obj ) - break; - Drawable *draw = obj->getDrawable(); - - const ThingTemplate *whatToBuild = commandButton->getThingTemplate(); - - CanMakeType cmt = TheBuildAssistant->canMakeUnit( obj, whatToBuild ); - if (cmt == CANMAKE_NO_MONEY) - { - TheEva->setShouldPlay(EVA_InsufficientFunds); - TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" ); - break; - } - else if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - else if (cmt == CANMAKE_PARKING_PLACES_FULL) - { - TheInGameUI->message( "GUI:ParkingPlacesFull" ); - break; - } - else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER ) - { - TheInGameUI->message( "GUI:UnitMaxedOut" ); - break; - } - - // tell the UI that we want to build something so we get a building at the cursor - TheInGameUI->placeBuildAvailable( commandButton->getThingTemplate(), draw ); - - ProductionUpdateInterface* pu = obj->getProductionUpdateInterface(); - if( pu ) - { - pu->setSpecialPowerConstructionCommandButton( commandButton ); - } - - break; - } - case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT: - { - // sanity - if( m_currentSelectedDrawable == nullptr ) - break; - - const ThingTemplate *whatToBuild = commandButton->getThingTemplate(); - - CanMakeType cmt = TheBuildAssistant->canMakeUnit( obj, whatToBuild ); - if (cmt == CANMAKE_NO_MONEY) - { - TheEva->setShouldPlay(EVA_InsufficientFunds); - TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" ); - break; - } - else if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - else if (cmt == CANMAKE_PARKING_PLACES_FULL) - { - TheInGameUI->message( "GUI:ParkingPlacesFull" ); - break; - } - else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER ) - { - TheInGameUI->message( "GUI:UnitMaxedOut" ); - break; - } - - // tell the UI that we want to build something so we get a building at the cursor - TheInGameUI->placeBuildAvailable( commandButton->getThingTemplate(), m_currentSelectedDrawable ); - - ProductionUpdateInterface* pu = obj->getProductionUpdateInterface(); - if( pu ) - { - pu->setSpecialPowerConstructionCommandButton( commandButton ); - } - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_DOZER_CONSTRUCT_CANCEL: - { - - // get the object we have selected - Object *building = obj; - if( building == nullptr ) - break; - - // sanity check, the building must be under our control to cancel construction - if( !building->isLocallyControlled() ) - break; - - // do the message - TheMessageStream->appendMessage( GameMessage::MSG_DOZER_CANCEL_CONSTRUCT ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_UNIT_BUILD: - { - const ThingTemplate *whatToBuild = commandButton->getThingTemplate(); - - // get the "factory" object that is going to make the thing - Object *factory = obj; - if( factory == nullptr ) - break; - - // sanity, we must have something to build - DEBUG_ASSERTCRASH( whatToBuild, ("Undefined BUILD command for object '%s'", - commandButton->getThingTemplate()->getName().str()) ); - - CanMakeType cmt = TheBuildAssistant->canMakeUnit(factory, whatToBuild); - - if (cmt == CANMAKE_NO_MONEY) - { - TheEva->setShouldPlay(EVA_InsufficientFunds); - TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" ); - break; - } - else if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - else if (cmt == CANMAKE_PARKING_PLACES_FULL) - { - TheInGameUI->message( "GUI:ParkingPlacesFull" ); - break; - } - else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER ) - { - TheInGameUI->message( "GUI:UnitMaxedOut" ); - break; - } - else if (cmt != CANMAKE_OK) - { - DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit", - whatToBuild->getName().str(), - factory->getTemplate()->getName().str()) ); - break; - } - - // get the production interface from the factory object - ProductionUpdateInterface *pu = factory->getProductionUpdateInterface(); - - // sanity, we can't build things if we can't produce units - if( pu == nullptr ) - { - - DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' is not capable of producing units", - whatToBuild->getName().str(), - factory->getTemplate()->getName().str()) ); - break; - - } - - // get a new production id to assign to this - ProductionID productionID = pu->requestUniqueUnitID(); - - // create a message to build this thing - - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UNIT_CREATE ); - msg->appendIntegerArgument( whatToBuild->getTemplateID() ); - msg->appendIntegerArgument( productionID ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_CANCEL_UNIT_BUILD: - { - Int i; - - // find out which index (i) in the queue represents the button clicked - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - if( m_queueData[ i ].control == control ) - break; - - // sanity, control not found - if( i == MAX_BUILD_QUEUE_BUTTONS ) - { - - DEBUG_CRASH( ("Control not found in build queue data") ); - break; - - } - - // sanity - if( m_queueData[ i ].type != PRODUCTION_UNIT ) - break; - - // the the production ID to cancel - ProductionID productionIDToCancel = m_queueData[ i ].productionID; - - // get the object that is the producer - Object *producer = obj; - if( producer == nullptr ) - break; - - // sanity, we must control the producer ... if this isn't true they might be hacking the game - if( !producer->isLocallyControlled() ) - break; - - // send a message to cancel that particular production entry - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_CANCEL_UNIT_CREATE ); - msg->appendIntegerArgument( productionIDToCancel ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_PLAYER_UPGRADE: - { - const UpgradeTemplate *upgradeT = commandButton->getUpgradeTemplate(); - DEBUG_ASSERTCRASH( upgradeT, ("Undefined upgrade '%s' in player upgrade command", "UNKNOWN") ); - - // sanity - if( obj == nullptr || upgradeT == nullptr ) - break; - - // make sure the player can really make this - if( TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeT, TRUE ) == FALSE ) - { - break; - } - - ProductionUpdateInterface* pu = obj ? obj->getProductionUpdateInterface() : nullptr; - if (pu != nullptr) - { - CanMakeType cmt = pu->canQueueUpgrade(upgradeT); - if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - } - - // send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UPGRADE ); - msg->appendObjectIDArgument( obj->getID() ); - msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_OBJECT_UPGRADE: - { - const UpgradeTemplate *upgradeT = commandButton->getUpgradeTemplate(); - DEBUG_ASSERTCRASH( upgradeT, ("Undefined upgrade '%s' in object upgrade command", "UNKNOWN") ); - // sanity - if( upgradeT == nullptr ) - break; - - //Make sure the player can really make this - if( TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeT, TRUE ) == FALSE ) - { - //Kris: Disabled because we can get a valid reason for not being able to afford the upgrade! - //TheInGameUI->message( "upgrade unsupported in commandprocessing." ); - break; - } - - ProductionUpdateInterface* pu = obj ? obj->getProductionUpdateInterface() : nullptr; - if (pu != nullptr) - { - CanMakeType cmt = pu->canQueueUpgrade(upgradeT); - if (cmt == CANMAKE_QUEUE_FULL) - { - TheInGameUI->message( "GUI:ProductionQueueFull" ); - break; - } - } - - ObjectID objID = INVALID_ID; - if (obj) - objID = obj->getID(); - - // make sure that the this object can actually build the upgrade - if( obj && (obj->hasUpgrade( upgradeT ) == TRUE || obj->affectedByUpgrade( upgradeT ) == FALSE) ) - break; - - // send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UPGRADE ); - msg->appendObjectIDArgument( objID ); - msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_CANCEL_UPGRADE: - { - Int i; - - // find out which index (i) in the queue represents the button clicked - for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ ) - if( m_queueData[ i ].control == control ) - break; - - // sanity, control not found - if( i == MAX_BUILD_QUEUE_BUTTONS ) - { - - DEBUG_CRASH( ("Control not found in build queue data") ); - break; - - } - - // sanity - if( m_queueData[ i ].type != PRODUCTION_UPGRADE ) - break; - - // get the upgrade to cancel - const UpgradeTemplate *upgradeT = m_queueData[ i ].upgradeToResearch; - - // get producer object (the thing driving our UI) - Object *producer = obj; - - // sanity - if( upgradeT == nullptr || producer == nullptr ) - break; - - // send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_CANCEL_UPGRADE ); - msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_ATTACK_MOVE: - TheMessageStream->appendMessage(GameMessage::MSG_META_TOGGLE_ATTACKMOVE); - break; - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_STOP: - { - // This message always works on the currently selected team - TheMessageStream->appendMessage(GameMessage::MSG_DO_STOP); - break; - } - - case GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE: - { - Player* localPlayer = ThePlayerList->getLocalPlayer(); - if( !localPlayer ) - { - break; - } - - const ThingTemplate *thing = commandButton->getThingTemplate(); - if( !thing ) - { - break; - } - - //deselect other units - TheInGameUI->deselectAllDrawables(); - - // create a new group. - GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP ); - - //New group or add to group? Passed in value is true if we are creating a new group. - teamMsg->appendBooleanArgument( TRUE ); - - //Iterate through the player's entire team and select each member that matches the template. - SelectObjectsInfo info; - info.thingTemplate = thing; - info.msg = teamMsg; - localPlayer->iterateObjects( selectObjectOfType, (void*)&info ); - - break; - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_WAYPOINTS: - break; - - //------------------------------------------------------------------------------------------------- - case GUI_COMMAND_EXIT_CONTAINER: - { - Int i; - // TheSuperHackers @fix Caball009/Mauller 23/05/2025 Fix uninitialized variable and control lookup behaviour to prevent a buffer-overflow when the control container is empty - ObjectID objID = INVALID_ID; - - // - // find the object ID that wants to exit by scanning through the transport data and looking - // for the matching control button - // - for (i = 0; i < MAX_COMMANDS_PER_SET; i++) - { - if (m_containData[i].control == control) - { - objID = m_containData[ i ].objectID; - break; - } - } - - if (objID == INVALID_ID) - break; - - // get the actual object - Object *objWantingExit = TheGameLogic->findObjectByID( objID ); - - // if the control container returns an object ID but the object is not found, remove the control entry and exit - if( objWantingExit == nullptr ) - { - - // - // remove from inventory data to avoid future matches ... the inventory update - // cycle of the UI will repopulate any buttons as the contents of objects - // change so this is only an edge case that will be visually corrected next frame - // - m_containData[ i ].control = nullptr; - m_containData[ i ].objectID = INVALID_ID; - break; // exit case - - } - - //what if container is subdued... assert a logic failure, perhaps? - - // send message to exit - GameMessage *exitMsg = TheMessageStream->appendMessage( GameMessage::MSG_EXIT ); - exitMsg->appendObjectIDArgument( objWantingExit->getID() ); // 0 is the thing inside coming out - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_EVACUATE: - { - // Cancel GUI command mode. - TheInGameUI->setGUICommand( nullptr ); - - if (BitIsSet(commandButton->getOptions(), NEED_TARGET_POS) == FALSE) { - pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_EVACUATE ); - TheMessageStream->appendMessage( GameMessage::MSG_EVACUATE ); - } - - break; - } - - // -------------------------------------------------------------------------------------------- - case GUI_COMMAND_EXECUTE_RAILED_TRANSPORT: - { - TheMessageStream->appendMessage( GameMessage::MSG_EXECUTE_RAILED_TRANSPORT ); - break; - } - - // -------------------------------------------------------------------------------------------- - case GUI_COMMAND_HACK_INTERNET: - { - pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_INTERNET_HACK ); - TheMessageStream->appendMessage( GameMessage::MSG_INTERNET_HACK ); - break; - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_SET_RALLY_POINT: - { - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_SELL: - { - - // command needs no additional data, send the message - TheMessageStream->appendMessage( GameMessage::MSG_SELL ); - break; - - } - - // -------------------------------------------------------------------------------------------- - case GUI_COMMAND_TOGGLE_OVERCHARGE: - { - - TheMessageStream->appendMessage( GameMessage::MSG_TOGGLE_OVERCHARGE ); - break; - - } - -#ifdef ALLOW_SURRENDER - // ------------------------------------------------------------------------------------------------ - case GUI_COMMAND_POW_RETURN_TO_PRISON: - { - - TheMessageStream->appendMessage( GameMessage::MSG_RETURN_TO_PRISON ); - break; - - } -#endif - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_BEACON_DELETE: - { - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_GUARD: - case GUI_COMMAND_GUARD_WITHOUT_PURSUIT: - case GUI_COMMAND_GUARD_FLYING_UNITS_ONLY: - case GUI_COMMAND_COMBATDROP: - { - DEBUG_CRASH(("hmm, should never occur")); - } - break; - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_SWITCH_WEAPON: - { - // command needs no additional data, send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SWITCH_WEAPONS ); - - //Play mode change acknowledgement - PickAndPlayInfo info; - WeaponSlotType slot = commandButton->getWeaponSlot(); - info.m_weaponSlot = &slot; - pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_SWITCH_WEAPONS, &info ); - - msg->appendIntegerArgument( commandButton->getWeaponSlot() ); - break; - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_FIRE_WEAPON: - { - // command needs no additional data, send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON ); - msg->appendIntegerArgument( commandButton->getWeaponSlot() ); - msg->appendIntegerArgument( commandButton->getMaxShotsToFire() ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT: - { - const SpecialPowerTemplate *spTemplate = commandButton->getSpecialPowerTemplate(); - SpecialPowerType spType = spTemplate->getSpecialPowerType(); - - Object* obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( spType ); - if( !obj ) - break; - - // command needs no additional data, send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_SPECIAL_POWER ); - msg->appendIntegerArgument( spTemplate->getID() ); - msg->appendIntegerArgument( commandButton->getOptions() ); - msg->appendObjectIDArgument( obj->getID() ); - break; - - } - - case GUI_COMMAND_SPECIAL_POWER: - { - // command needs no additional data, send the message - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_SPECIAL_POWER ); - msg->appendIntegerArgument( commandButton->getSpecialPowerTemplate()->getID() ); - msg->appendIntegerArgument( commandButton->getOptions() ); - msg->appendObjectIDArgument( INVALID_ID ); // no specific source - break; - - } - - //--------------------------------------------------------------------------------------------- - case GUI_COMMAND_PURCHASE_SCIENCE: - { - - // loop through all the sciences on the button and select the one we don't have - - ScienceType st = SCIENCE_INVALID; - Player *player = ThePlayerList->getLocalPlayer(); - for(size_t i = 0; i < commandButton->getScienceVec().size(); ++i) - { - st = commandButton->getScienceVec()[ i ]; - if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints()) - { - break; - } - } - - if( st == SCIENCE_INVALID) - { - switchToContext( CB_CONTEXT_NONE, nullptr ); - break; - } - - - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PURCHASE_SCIENCE ); - msg->appendIntegerArgument( st ); - - markUIDirty(); - - break; - - } - - //--------------------------------------------------------------------------------------------- - default: - - DEBUG_CRASH( ("Unknown command '%d'", commandButton->getCommandType()) ); - return CBC_COMMAND_NOT_USED; - - } - - return CBC_COMMAND_USED; - -} - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp deleted file mode 100644 index 1cdda2b5253..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarMultiSelect.cpp //////////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Context sensitive GUI for when you select multiple objects. What we do is show -// the commands that you can use between them all -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/ThingTemplate.h" -#include "GameClient/ControlBar.h" -#include "GameClient/Drawable.h" -#include "GameClient/GameClient.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GameWindow.h" -#include "GameClient/InGameUI.h" -#include "GameLogic/Object.h" - - - - -//------------------------------------------------------------------------------------------------- -/** Reset the common command data */ -//------------------------------------------------------------------------------------------------- -void ControlBar::resetCommonCommandData() -{ - Int i; - - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - m_commonCommands[ i ] = nullptr; - //Clear out any remnant overlays. - GadgetButtonDrawOverlayImage( m_commandWindows[ i ], nullptr ); - } - -} - -//------------------------------------------------------------------------------------------------- -/** add the common commands of this drawable to the common command set */ -//------------------------------------------------------------------------------------------------- -void ControlBar::addCommonCommands( Drawable *draw, Bool firstDrawable ) -{ - Int i; - const CommandButton *command; - - // sanity - if( draw == nullptr ) - return; - - Object* obj = draw->getObject(); - if (!obj) - return; - - if (obj->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys - return; - - // get the command set of this drawable - const CommandSet *commandSet = findCommandSet( obj->getCommandSetString() ); - if( commandSet == nullptr ) - { - - // - // if there is no command set for this drawable, none of the selected drawables - // can possibly have matching commands so we'll get rid of them all - // - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - - m_commonCommands[ i ] = nullptr; - if (m_commandWindows[ i ]) - { - m_commandWindows[ i ]->winHide( TRUE ); - } - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - - } - - return; - - } - - - // - // easy case, if we're adding the first drawable we simply just add any of the commands - // in its set that can be multi-select commands to the common command set - // - if( firstDrawable == TRUE ) - { - - // just add each command that is classified as a common command - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // get command - command = commandSet->getCommandButton(i); - - // add if present and can be used in a multi select - if( command && BitIsSet( command->getOptions(), OK_FOR_MULTI_SELECT ) == TRUE ) - { - - // put it in the common command set - m_commonCommands[ i ] = command; - - // show and enable this control - m_commandWindows[ i ]->winHide( FALSE ); - m_commandWindows[ i ]->winEnable( TRUE ); - - // set the command into the control - setControlCommand( m_commandWindows[ i ], command ); - - } - - } - - } - else - { - - // go through each command one by one - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // get the command - command = commandSet->getCommandButton(i); - - Bool attackMove = (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE) || - (m_commonCommands[ i ] && m_commonCommands[ i ]->getCommandType() == GUI_COMMAND_ATTACK_MOVE); - - // Kris: When any units have attack move, they all get it. This is to allow - // combat units to be selected with the odd dozer or pilot and still retain that ability. - if( attackMove && !m_commonCommands[ i ] ) - { - // put it in the common command set - m_commonCommands[ i ] = command; - - // show and enable this control - m_commandWindows[ i ]->winHide( FALSE ); - m_commandWindows[ i ]->winEnable( TRUE ); - - // set the command into the control - setControlCommand( m_commandWindows[ i ], command ); - } - else if( command != m_commonCommands[ i ] && !attackMove ) - { - // - // if this command does not match the command that is in the common command set then - // *neither* this command OR the command in the common command set are really common - // commands, so we will remove the one that has been stored in the common set - // - - // remove the common command - m_commonCommands[ i ] = nullptr; - - // - // hide the window control cause it should have been made visible from a command - // that was placed in this common 'slot' earlier - // - m_commandWindows[ i ]->winHide( TRUE ); - } - - } - - } - - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - -} - -//------------------------------------------------------------------------------------------------- -/** Populate the visible command bar with commands that are common to all the objects - * that are selected in the UI */ -//------------------------------------------------------------------------------------------------- -void ControlBar::populateMultiSelect() -{ - Drawable *draw; - Bool firstDrawable = TRUE; - Bool portraitSet = FALSE; - const Image *portrait = nullptr; - Object *portraitObj = nullptr; - - // first reset the common command data - resetCommonCommandData(); - - // by default, hide all the controls in the command section - for( Int i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - if (m_commandWindows[ i ]) - { - m_commandWindows[ i ]->winHide( TRUE ); - } - } - - // sanity - DEBUG_ASSERTCRASH( TheInGameUI->getSelectCount() > 1, - ("populateMultiSelect: Can't populate multiselect context cause there are only '%d' things selected", - TheInGameUI->getSelectCount()) ); - - // get the list of drawable IDs from the in game UI - const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables(); - - // sanity - DEBUG_ASSERTCRASH( selectedDrawables->empty() == FALSE, ("populateMultiSelect: Drawable list is empty") ); - - // loop through all the selected drawables - for( DrawableListCIt it = selectedDrawables->begin(); - it != selectedDrawables->end(); ++it ) - { - - // get the drawable - draw = *it; - - - if (draw->getObject()->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys - continue; - - - // - // add command for this drawable, note that we also sanity check to make sure the - // drawable has an object as all interesting drawables that we can select should - // actually have an object underneath it so that we can do interesting things with - // it ... otherwise we should have never selected it. - // NOTE that we're not considering objects that are currently in the process of - // being sold as those objects can't be issued anymore commands - // - if( draw && draw->getObject() && - !draw->getObject()->getStatusBits().test( OBJECT_STATUS_SOLD ) ) - { - - // add the common commands of this drawable to the common command set - addCommonCommands( draw, firstDrawable ); - - // not adding the first drawable anymore - firstDrawable = FALSE; - - // - // keep track of the portrait images, if all units selected have the same portrait - // we will display it in the right HUD, otherwise we won't - // - if( portraitSet == FALSE ) - { - - portrait = draw->getTemplate()->getSelectedPortraitImage(); - portraitObj = draw->getObject(); - portraitSet = TRUE; - - } - else if( draw->getTemplate()->getSelectedPortraitImage() != portrait ) - portrait = nullptr; - - } - - } - - // set the portrait image - setPortraitByObject( portraitObj ); - -} - -//------------------------------------------------------------------------------------------------- -/** Update logic for the multi select context sensitive GUI */ -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextMultiSelect() -{ - Drawable *draw; - Object *obj; - const CommandButton *command; - GameWindow *win; - Int objectsThatCanDoCommand[ MAX_COMMANDS_PER_SET ]; - Int i; - - // zero the array that counts how many objects can do each command - memset( objectsThatCanDoCommand, 0, sizeof( objectsThatCanDoCommand ) ); - - // sanity - DEBUG_ASSERTCRASH( TheInGameUI->getSelectCount() > 1, - ("updateContextMultiSelect: TheInGameUI only has '%d' things selected", - TheInGameUI->getSelectCount()) ); - - // get the list of drawable IDs from the in game UI - const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables(); - - // sanity - DEBUG_ASSERTCRASH( selectedDrawables->empty() == FALSE, ("populateMultiSelect: Drawable list is empty") ); - - // loop through all the selected drawable IDs - for( DrawableListCIt it = selectedDrawables->begin(); - it != selectedDrawables->end(); ++it ) - { - - // get the drawable from the ID - draw = *it; - - if (draw->getObject()->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys - continue; - - - // get the object - obj = draw->getObject(); - - // sanity - if( obj == nullptr ) - continue; - - // for each of the visible command windows make sure the object can execute the command - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - - // get the control window - win = m_commandWindows[ i ]; - - // our implementation doesn't necessarily make use of the max possible command buttons - if (!win) continue; - - // don't consider hidden windows - if( win->winIsHidden() == TRUE ) - continue; - - // get the command - command = (const CommandButton *)GadgetButtonGetData(win); - if( command == nullptr ) - continue; - - // can we do the command - CommandAvailability availability = getCommandAvailability( command, obj, win ); - - win->winClearStatus( WIN_STATUS_NOT_READY ); - win->winClearStatus( WIN_STATUS_ALWAYS_COLOR ); - - // enable/disable the window control - switch( availability ) - { - case COMMAND_HIDDEN: - win->winHide( TRUE ); - break; - case COMMAND_RESTRICTED: - win->winEnable( FALSE ); - break; - case COMMAND_NOT_READY: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_NOT_READY ); - break; - case COMMAND_CANT_AFFORD: - win->winEnable( FALSE ); - win->winSetStatus( WIN_STATUS_ALWAYS_COLOR ); - break; - default: - win->winEnable( TRUE ); - break; - } - - //If button is a CHECK_LIKE, then update it's status now. - if( BitIsSet( command->getOptions(), CHECK_LIKE ) ) - { - GadgetCheckLikeButtonSetVisualCheck( win, availability == COMMAND_ACTIVE ); - } - - if( availability == COMMAND_AVAILABLE || availability == COMMAND_ACTIVE ) - objectsThatCanDoCommand[ i ]++; - - } - - } - - // - // for each command, if any objects can do the command we enable the window, otherwise - // we disable it - // - for( i = 0; i < MAX_COMMANDS_PER_SET; i++ ) - { - // our implementation doesn't necessarily make use of the max possible command buttons - if (! m_commandWindows[ i ]) continue; - - // don't consider hidden commands - if( m_commandWindows[ i ]->winIsHidden() == TRUE ) - continue; - - // don't consider slots that don't have commands - if( m_commonCommands[ i ] == nullptr ) - continue; - - // check the count of objects that can do the command and enable/disable the control, - if( objectsThatCanDoCommand[ i ] > 0 ) - m_commandWindows[ i ]->winEnable( TRUE ); - else - m_commandWindows[ i ]->winEnable( FALSE ); - - } - - // After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images - // removed from multiplayer branch - //showCommandMarkers(); - - -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp deleted file mode 100644 index b7d34911ed4..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarOCLTimer.cpp ////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Methods specific to the control bar OCL Timer context -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/NameKeyGenerator.h" -#include "Common/ThingTemplate.h" -#include "GameLogic/Object.h" -#include "GameLogic/Module/OCLUpdate.h" -#include "GameClient/Drawable.h" -#include "GameClient/GameText.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetProgressBar.h" - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateOCLTimerTextDisplay( UnsignedInt totalSeconds, Real percent ) -{ - UnicodeString text; - static UnsignedInt descID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerStaticText" ); - GameWindow *descWindow = TheWindowManager->winGetWindowFromId( nullptr, descID ); - - static UnsignedInt barID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerProgressBar" ); - GameWindow *barWindow = TheWindowManager->winGetWindowFromId( nullptr, barID ); - - // sanity - DEBUG_ASSERTCRASH( descWindow, ("Under construction window not found") ); - - Int minutes = totalSeconds / 60; - Int seconds = totalSeconds - (minutes * 60); - - // format the message - if( seconds < 10 ) - text.format( TheGameText->fetch( "CONTROLBAR:OCLTimerDescWithPadding" ), minutes, seconds ); - else - text.format( TheGameText->fetch( "CONTROLBAR:OCLTimerDesc" ), minutes, seconds ); - - GadgetStaticTextSetText( descWindow, text ); - GadgetProgressBarSetProgress(barWindow, (percent * 100)); - - // record this as the last time displayed - m_displayedOCLTimerSeconds = totalSeconds; - -} - -//------------------------------------------------------------------------------------------------- -/** Populate the interface for an OCL Timer context. */ -//------------------------------------------------------------------------------------------------- -void ControlBar::populateOCLTimer( Object *creatorObject ) -{ - - // sanity - if( creatorObject == nullptr ) - return; - - // get our parent window - GameWindow *parent = m_contextParent[ CP_OCL_TIMER ]; - - // set the sell button -/// @todo srj -- remove hard-coding here, please - const CommandButton *commandButton = findCommandButton( "Command_Sell" ); - NameKeyType id; - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerSellButton" ); - GameWindow *win = TheWindowManager->winGetWindowFromId( parent, id ); - setControlCommand( win, commandButton ); - win->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - - - // set the text percent and bar of our timer we are displaying - updateContextOCLTimer(); - - // set the portrait for the thing being constructed - setPortraitByObject( creatorObject ); - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextOCLTimer() -{ - Object *obj = m_currentSelectedDrawable->getObject(); - - static const NameKeyType key_OCLUpdate = NAMEKEY( "OCLUpdate" ); - OCLUpdate *update = (OCLUpdate*)obj->findUpdateModule( key_OCLUpdate ); - - UnsignedInt frames = update->getRemainingFrames(); - UnsignedInt seconds = frames / LOGICFRAMES_PER_SECOND; - - Real percent = update->getCountdownPercent(); - - // if the time has changed since what was last shown to the user update the text - if( m_displayedOCLTimerSeconds != seconds ) - updateOCLTimerTextDisplay( seconds, percent ); - -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp deleted file mode 100644 index 56d8f878315..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarObserver.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Aug 2002 -// -// Filename: ControlBarObserver.cpp -// -// author: Chris Huybregts -// -// purpose: All things related to the Observer Control bar, are in here. -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/GameUtility.h" -#include "Common/NameKeyGenerator.h" -#include "Common/PlayerList.h" -#include "Common/Player.h" -#include "Common/PlayerTemplate.h" -#include "Common/KindOf.h" -#include "Common/Recorder.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GameText.h" -#include "GameNetwork/NetworkDefs.h" -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -enum { MAX_BUTTONS = 8}; -static NameKeyType buttonPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -static NameKeyType staticTextPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID, - NAMEKEY_INVALID,NAMEKEY_INVALID }; -static GameWindow *ObserverPlayerInfoWindow = nullptr; -static GameWindow *ObserverPlayerListWindow = nullptr; - -static GameWindow *buttonPlayer[MAX_BUTTONS] = {0}; -static GameWindow *staticTextPlayer[MAX_BUTTONS] = {0}; - - -static NameKeyType buttonCancelID = NAMEKEY_INVALID; - -static GameWindow *winFlag = nullptr; -static GameWindow *winGeneralPortrait = nullptr; -// TheSuperHackers @tweak Allow idle worker selection for observers. -static GameWindow *buttonIdleWorker = nullptr; -static GameWindow *staticTextNumberOfUnits = nullptr; -static GameWindow *staticTextNumberOfBuildings = nullptr; -static GameWindow *staticTextNumberOfUnitsKilled = nullptr; -static GameWindow *staticTextNumberOfUnitsLost = nullptr; -static GameWindow *staticTextPlayerName = nullptr; - -static NameKeyType s_replayObserverNameKey = NAMEKEY_INVALID; - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - - -void ControlBar::initObserverControls() -{ - ObserverPlayerInfoWindow = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerInfoWindow")); - ObserverPlayerListWindow = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerListWindow")); - - for (Int i = 0; i < MAX_BUTTONS; i++) - { - AsciiString tmpString; - tmpString.format("ControlBar.wnd:ButtonPlayer%d", i); - buttonPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - buttonPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, buttonPlayerID[i] ); - tmpString.format("ControlBar.wnd:StaticTextPlayer%d", i); - staticTextPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString ); - staticTextPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, staticTextPlayerID[i] ); - } - - staticTextNumberOfUnits = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnits")); - staticTextNumberOfBuildings = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfBuildings")); - staticTextNumberOfUnitsKilled = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsKilled")); - staticTextNumberOfUnitsLost = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsLost")); - staticTextPlayerName = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextPlayerName")); - winFlag = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinFlag")); - winGeneralPortrait = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinGeneralPortrait")); - buttonIdleWorker = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonIdleWorker")); - - buttonCancelID = TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonCancel"); - - s_replayObserverNameKey = TheNameKeyGenerator->nameToKey("ReplayObserver"); -} - -//------------------------------------------------------------------------------------------------- -void ControlBar::setObserverLookAtPlayer(Player *player) -{ - if (player != nullptr && player == ThePlayerList->findPlayerWithNameKey(s_replayObserverNameKey)) - { - // Looking at the observer. Treat as not looking at player. - m_observerLookAtPlayer = nullptr; - } - else - { - m_observerLookAtPlayer = player; - } -} - -//------------------------------------------------------------------------------------------------- -void ControlBar::setObservedPlayer(Player *player) -{ - if (player != nullptr && player == ThePlayerList->findPlayerWithNameKey(s_replayObserverNameKey)) - { - // Looking at the observer. Treat as not observing player. - m_observedPlayer = nullptr; - } - else - { - m_observedPlayer = player; - } -} - -//------------------------------------------------------------------------------------------------- -/** System callback for the ControlBarObserverSystem */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType ControlBarObserverSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - static NameKeyType buttonCommunicator = NAMEKEY_INVALID; - - switch( msg ) - { - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - break; - - } - - //--------------------------------------------------------------------------------------------- - case GBM_MOUSE_ENTERING: - case GBM_MOUSE_LEAVING: - { - break; - } - - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - case GBM_SELECTED_RIGHT: - { - GameWindow *control = (GameWindow *)mData1; - - Int controlID = control->winGetWindowId(); - if( controlID == buttonCancelID) - { - rts::changeObservedPlayer(nullptr); - - ObserverPlayerInfoWindow->winHide(TRUE); - ObserverPlayerListWindow->winHide(FALSE); - buttonIdleWorker->winHide(TRUE); - TheControlBar->populateObserverList(); - } - - for(Int i = 0; i (GadgetButtonGetData(buttonPlayer[i])); - rts::changeObservedPlayer(player); - - ObserverPlayerInfoWindow->winHide(FALSE); - ObserverPlayerListWindow->winHide(TRUE); - - if(TheControlBar->getObserverLookAtPlayer()) - TheControlBar->populateObserverInfoWindow(); - - return MSG_HANDLED; - } - } - - // if( controlID == buttonCommunicator && TheGameLogic->getGameMode() == GAME_INTERNET ) - /* - { - popupCommunicatorLayout = TheWindowManager->winCreateLayout( "Menus/PopupCommunicator.wnd" ); - popupCommunicatorLayout->runInit(); - popupCommunicatorLayout->hide( FALSE ); - popupCommunicatorLayout->bringForward(); - } -*/ - - break; - - } - - //--------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - - } - - return MSG_HANDLED; - -} - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -void ControlBar::populateObserverList() -{ - Int currentButton = 0, i; - if(TheRecorder->isMultiplayer()) - { - - for (i = 0; i < MAX_SLOTS; ++i) - { - AsciiString name; - name.format("player%d", i); - Player *p = ThePlayerList->findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(name)); - if(p) - { - if(p->isPlayerObserver()) - continue; - DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have")); - GadgetButtonSetData(buttonPlayer[currentButton], (void *)p); - GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() ); - //GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() ); - //GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() ); - //GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() ); - buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName()); - buttonPlayer[currentButton]->winHide(FALSE); - buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - - const GameSlot *slot = TheGameInfo->getConstSlot(i); - Color playerColor = p->getPlayerColor(); - Color backColor = GameMakeColor(0, 0, 0, 255); - staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor ); - staticTextPlayer[currentButton]->winHide(FALSE); - AsciiString teamStr; - teamStr.format("Team:%d", slot->getTeamNumber() + 1); - if (slot->isAI() && slot->getTeamNumber() == -1) - teamStr = "Team:AI"; - - UnicodeString text; - text.format(TheGameText->fetch("CONTROLBAR:ObsPlayerLabel"), p->getPlayerDisplayName().str(), - TheGameText->fetch(teamStr).str()); - - GadgetStaticTextSetText(staticTextPlayer[currentButton], text ); - - ++currentButton; - } - } - for(currentButton; currentButtonwinHide(TRUE); - staticTextPlayer[currentButton]->winHide(TRUE); - } - } - else - { - for(i =0; i < MAX_PLAYER_COUNT; ++i) - { - Player *p = ThePlayerList->getNthPlayer(i); - if(p && !p->isPlayerObserver() && p->getPlayerType() == PLAYER_HUMAN) - { - DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have")); - GadgetButtonSetData(buttonPlayer[currentButton], (void *)p); - GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() ); - //GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() ); - //GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() ); - //GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() ); - buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName()); - buttonPlayer[currentButton]->winHide(FALSE); - buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - - Color playerColor = p->getPlayerColor(); - Color backColor = GameMakeColor(0, 0, 0, 255); - staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor ); - staticTextPlayer[currentButton]->winHide(FALSE); - GadgetStaticTextSetText(staticTextPlayer[currentButton], p->getPlayerDisplayName()); - - ++currentButton; - break; - } - } - for(currentButton; currentButtonwinHide(TRUE); - staticTextPlayer[currentButton]->winHide(TRUE); - } - } -} - -void ControlBar::populateObserverInfoWindow () -{ - if(ObserverPlayerInfoWindow->winIsHidden()) - return; - - if( !m_observerLookAtPlayer ) - { - ObserverPlayerInfoWindow->winHide(TRUE); - ObserverPlayerListWindow->winHide(FALSE); - buttonIdleWorker->winHide(TRUE); - populateObserverList(); - return; - } - - UnicodeString uString; - KindOfMaskType mask,clearmask; - mask.set(KINDOF_SCORE); - clearmask.set(KINDOF_STRUCTURE); - - uString.format(L"%d",m_observerLookAtPlayer->countObjects(mask,clearmask)); - GadgetStaticTextSetText(staticTextNumberOfUnits, uString); - - Int numBuildings = 0; - mask.clear(); - mask.set(KINDOF_SCORE); - mask.set(KINDOF_STRUCTURE); - clearmask.clear(); - numBuildings = m_observerLookAtPlayer->countObjects(mask,clearmask); - mask.clear(); - mask.set(KINDOF_SCORE_CREATE); - mask.set(KINDOF_STRUCTURE); - numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask); - mask.clear(); - mask.set(KINDOF_SCORE_DESTROY); - mask.set(KINDOF_STRUCTURE); - numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask); - uString.format(L"%d",numBuildings); - GadgetStaticTextSetText(staticTextNumberOfBuildings, uString); - uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsDestroyed()); - GadgetStaticTextSetText(staticTextNumberOfUnitsKilled, uString); - uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsLost()); - GadgetStaticTextSetText(staticTextNumberOfUnitsLost, uString); - GadgetStaticTextSetText(staticTextPlayerName, m_observerLookAtPlayer->getPlayerDisplayName()); - Color color = m_observerLookAtPlayer->getPlayerColor(); - staticTextPlayerName->winSetEnabledTextColors(color, GameMakeColor(0,0,0,255)); - winFlag->winSetEnabledImage(0, m_observerLookAtPlayer->getPlayerTemplate()->getFlagWaterMarkImage()); - winGeneralPortrait->winHide(FALSE); - buttonIdleWorker->winHide(FALSE); -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp deleted file mode 100644 index 197205b5f47..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarPrintPositions.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Sep 2002 -// -// Filename: ControlBarPrintPositions.cpp -// -// author: Chris Huybregts -// -// purpose: Convenience function for degayifying the whole squished control bar -// process -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "GameClient/GameWindowManager.h" -#include "GameClient/WindowLayout.h" -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -void PrintInfoRecursive( GameWindow *win, FILE *fp) -{ - if(!win) - return; - ICoord2D pos, size; - win->winGetSize(&size.x, &size.y); - win->winGetPosition(&pos.x, &pos.y); - fprintf(fp, "ControlBarResizer %s\n",win->winGetInstanceData()->m_decoratedNameString.str()); - fprintf(fp, " AltPosition = X:%d Y:%d\n",pos.x, pos.y); - fprintf(fp, " AltSize = X:%d Y:%d\n",size.x, size.y); - fprintf(fp, "END\n\n"); - - PrintInfoRecursive(win->winGetChild(),fp); - PrintInfoRecursive(win->winGetNext(),fp); - -} - -void PrintOffsetsFromControlBarParent() -{ - GameWindow *controlBarParent = TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ControlBarParent" )); - if(!controlBarParent) - return; - - WindowLayout *layout = TheWindowManager->winCreateLayout("controlBarHidden.wnd"); - if(!layout) - return; - FILE *fp = fopen("ControlBarEasier.txt", "w"); - if(!fp) - return; - - PrintInfoRecursive(layout->getFirstWindow(), fp); - - fclose(fp); - layout->destroyWindows(); - deleteInstance(layout); -} - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp deleted file mode 100644 index f639cd61517..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarResizer.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Sep 2002 -// -// Filename: ControlBarResizer.cpp -// -// author: Chris Huybregts -// -// purpose: We want a "squished" control bar, this is the methods that will do it -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "GameClient/ControlBar.h" -#include "GameClient/ControlBarResizer.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/Display.h" -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -const FieldParse ControlBarResizer::m_controlBarResizerParseTable[] = -{ - { "AltPosition", INI::parseICoord2D, nullptr, offsetof( ResizerWindow, m_altPos ) }, - { "AltSize", INI::parseICoord2D, nullptr, offsetof( ResizerWindow, m_altSize ) }, - { nullptr, nullptr, nullptr, 0 } - -}; -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -ResizerWindow::ResizerWindow() -{ - m_defaultPos.x = m_defaultPos.y = 0; - m_defaultSize.x = m_defaultSize.y = 0; - m_altSize.x = m_altSize.y = 0; - m_altPos.x = m_altPos.y = 0; -} - -ControlBarResizer::ControlBarResizer() -{ - -} -ControlBarResizer::~ControlBarResizer() -{ - ResizerWindowList::iterator it = m_resizerWindowsList.begin(); - while (it != m_resizerWindowsList.end()) - { - ResizerWindow *rWin = *it; - if( !rWin ) - { - it = m_resizerWindowsList.erase(it); - continue; - } - delete rWin; - it = m_resizerWindowsList.erase(it); - } - m_resizerWindowsList.clear(); -} - -void ControlBarResizer::init() -{ - INI ini; - // Read from INI all the ControlBarSchemes - ini.loadFileDirectory( "Data\\INI\\ControlBarResizer", INI_LOAD_OVERWRITE, nullptr ); - -} - - -ResizerWindow *ControlBarResizer::findResizerWindow( AsciiString name ) -{ - ResizerWindowList::iterator it = m_resizerWindowsList.begin(); - - while (it != m_resizerWindowsList.end()) - { - ResizerWindow *rWin = *it; - if( !rWin ) - { - DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::findResizerWindow")); - it++; - continue; - } - // find the scheme that best matches our resolution - if(rWin->m_name.compare(name) == 0) - { - return rWin; - } - it ++; - } - return nullptr; -} - -ResizerWindow *ControlBarResizer::newResizerWindow( AsciiString name ) -{ - ResizerWindow *newRwin = NEW ResizerWindow; - if(!newRwin) - return nullptr; - - newRwin->m_name = name; - GameWindow *win = nullptr; - win = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey(name)); - if( !win ) - { - DEBUG_ASSERTCRASH(win,("ControlBarResizer::newResizerWindow could not find window %s Are you sure that window is loaded yet?", name.str()) ); - delete newRwin; - return nullptr; - } - win->winGetPosition(&newRwin->m_defaultPos.x,&newRwin->m_defaultPos.y); - win->winGetSize(&newRwin->m_defaultSize.x,&newRwin->m_defaultSize.y); - m_resizerWindowsList.push_back(newRwin); - return newRwin; -} -void ControlBarResizer::sizeWindowsDefault() -{ - ResizerWindowList::iterator it = m_resizerWindowsList.begin(); - GameWindow *win = nullptr; - while (it != m_resizerWindowsList.end()) - { - ResizerWindow *rWin = *it; - if( !rWin ) - { - DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault")); - it++; - continue; - } - win = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey(rWin->m_name)); - if(!win) - { - it++; - continue; - } - win->winSetPosition(rWin->m_defaultPos.x, rWin->m_defaultPos.y); - win->winSetSize(rWin->m_defaultSize.x, rWin->m_defaultSize.y); - DEBUG_LOG(("sizeWindowsDefault:%s pos X:%d pos Y: %d size X:%d sizeY: %d",rWin->m_name.str(),rWin->m_defaultPos.x, rWin->m_defaultPos.y,rWin->m_defaultSize.x, rWin->m_defaultSize.y )); - it ++; - } -} -void ControlBarResizer::sizeWindowsAlt() -{ - ResizerWindowList::iterator it = m_resizerWindowsList.begin(); - GameWindow *win = nullptr; - Real x = (Real)TheDisplay->getWidth() / DEFAULT_DISPLAY_WIDTH; - Real y = (Real)TheDisplay->getHeight() / DEFAULT_DISPLAY_HEIGHT; - while (it != m_resizerWindowsList.end()) - { - ResizerWindow *rWin = *it; - if( !rWin ) - { - DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault")); - it++; - continue; - } - win = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey(rWin->m_name)); - if(!win) - { - it++; - continue; - } - - win->winSetPosition(rWin->m_altPos.x * x, rWin->m_altPos.y * y); - if(rWin->m_altSize.x >0 || rWin->m_altSize.y > 0) - win->winSetSize(rWin->m_altSize.x *x, rWin->m_altSize.y *y); - DEBUG_LOG(("sizeWindowsAlt:%s pos X:%d pos Y: %d size X:%d sizeY: %d",rWin->m_name.str(), rWin->m_altPos.x*x, rWin->m_altPos.y*y,rWin->m_altSize.x*x, rWin->m_altSize.y *y)); - it ++; - } -} - - -void INI::parseControlBarResizerDefinition( INI* ini ) -{ -// AsciiString name; -// ResizerWindow *rWin = nullptr; -// -// // read the name -// const char* c = ini->getNextToken(); -// name.set( c ); -// -//// ControlBarResizer *resizer = TheControlBar->getControlBarResizer(); -// if( !resizer ) -// { -// //We don't need it if we're in the builder... which doesn't have this. -// return; -// } -// rWin = resizer->findResizerWindow( name ); -// if( rWin == nullptr ) -// { -// -// // image not found, create a new one -// rWin = resizer->newResizerWindow(name); -// DEBUG_ASSERTCRASH( rWin, ("parseControlBarResizerDefinition: unable to allocate ResizerWindow for '%s'", -// name.str()) ); -// -// } // end if -// -// // parse the ini definition -// ini->initFromINI( rWin, resizer->getFieldParse()); -// -} - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp deleted file mode 100644 index ec4a9ff2e9c..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp +++ /dev/null @@ -1,1233 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarScheme.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Apr 2002 -// -// Filename: ControlBarScheme.cpp -// -// author: Chris Huybregts -// -// purpose: Contains all the Command bar goodness in terms of how it looks -// For instructions on how to use, please see it's .h file -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/Player.h" -#include "Common/PlayerTemplate.h" -#include "Common/Recorder.h" -#include "GameClient/ControlBarScheme.h" -#include "GameClient/Display.h" -#include "GameClient/ControlBar.h" -#include "GameClient/Image.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetPushButton.h" - -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -enum{ - COMMAND_BAR_SIZE_OFFSET = 0 -}; - -const FieldParse ControlBarSchemeManager::m_controlBarSchemeFieldParseTable[] = -{ - - { "ImagePart", ControlBarSchemeManager::parseImagePart, nullptr, 0 }, - { "AnimatingPart", ControlBarSchemeManager::parseAnimatingPart, nullptr, 0 }, - { "ScreenCreationRes", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_ScreenCreationRes ) }, - { "Side", INI::parseAsciiString, nullptr, offsetof( ControlBarScheme, m_side ) }, - { "QueueButtonImage", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_buttonQueueImage ) }, - { "RightHUDImage", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_rightHUDImage ) }, - { "BuildUpClockColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_buildUpClockColor ) }, - { "ButtonBorderBuildColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_borderBuildColor ) }, - { "CommandBarBorderColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_commandBarBorderColor ) }, - { "ButtonBorderActionColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_borderActionColor ) }, - { "ButtonBorderUpgradeColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_borderUpgradeColor ) }, - { "ButtonBorderSystemColor", INI::parseColorInt, nullptr, offsetof( ControlBarScheme, m_borderSystemColor ) }, - { "OptionsButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_optionsButtonEnable ) }, - { "OptionsButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_optionsButtonHightlited ) }, - { "OptionsButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_optionsButtonPushed ) }, - { "OptionsButtonDisabled", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_optionsButtonDisabled ) }, - { "IdleWorkerButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_idleWorkerButtonEnable ) }, - { "IdleWorkerButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_idleWorkerButtonHightlited ) }, - { "IdleWorkerButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_idleWorkerButtonPushed ) }, - { "IdleWorkerButtonDisabled", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_idleWorkerButtonDisabled ) }, - { "BuddyButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_buddyButtonEnable ) }, - { "BuddyButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_buddyButtonHightlited ) }, - { "BuddyButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_buddyButtonPushed ) }, - { "BuddyButtonDisabled", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_buddyButtonDisabled) }, - { "BeaconButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_beaconButtonEnable ) }, - { "BeaconButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_beaconButtonHightlited ) }, - { "BeaconButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_beaconButtonPushed ) }, - { "BeaconButtonDisabled", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_beaconButtonDisabled ) }, - { "GenBarButtonIn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_genBarButtonIn ) }, - { "GenBarButtonOn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_genBarButtonOn ) }, - { "ToggleButtonUpIn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonUpIn ) }, - { "ToggleButtonUpOn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonUpOn ) }, - { "ToggleButtonUpPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonUpPushed ) }, - { "ToggleButtonDownIn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonDownIn ) }, - { "ToggleButtonDownOn", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonDownOn ) }, - { "ToggleButtonDownPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_toggleButtonDownPushed ) }, - - { "GeneralButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_generalButtonEnable ) }, - { "GeneralButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_generalButtonHightlited ) }, - { "GeneralButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_generalButtonPushed ) }, - { "GeneralButtonDisabled", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_generalButtonDisabled ) }, - - { "UAttackButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_uAttackButtonEnable ) }, - { "UAttackButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_uAttackButtonHightlited ) }, - { "UAttackButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_uAttackButtonPushed ) }, - - { "GenArrow", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_genArrow) }, - - { "MinMaxButtonEnable", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_minMaxButtonEnable ) }, - { "MinMaxButtonHightlited", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_minMaxButtonHightlited ) }, - { "MinMaxButtonPushed", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_minMaxButtonPushed ) }, - - { "MinMaxUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_minMaxUL ) }, - { "MinMaxLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_minMaxLR ) }, - - { "GeneralUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_generalUL ) }, - { "GeneralLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_generalLR ) }, - - { "UAttackUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_uAttackUL ) }, - { "UAttackLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_uAttackLR ) }, - - { "OptionsUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_optionsUL ) }, - { "OptionsLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_optionsLR ) }, - - { "WorkerUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_workerUL ) }, - { "WorkerLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_workerLR ) }, - - { "ChatUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_chatUL ) }, - { "ChatLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_chatLR ) }, - - { "BeaconUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_beaconUL ) }, - { "BeaconLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_beaconLR ) }, - - { "PowerBarUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_powerBarUL ) }, - { "PowerBarLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_powerBarLR ) }, - - { "MoneyUL", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_moneyUL ) }, - { "MoneyLR", INI::parseICoord2D, nullptr, offsetof( ControlBarScheme, m_moneyLR ) }, - - { "CommandMarkerImage", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_commandMarkerImage) }, - { "ExpBarForegroundImage", INI::parseMappedImage, nullptr, offsetof( ControlBarScheme, m_expBarForeground) }, - - { nullptr, nullptr, nullptr, 0 } - -}; - -// used to parse the anim types that each animation part of a scheme can have -static const LookupListRec AnimTypeNames[] = -{ - { "SLIDE_RIGHT", ControlBarSchemeAnimation::CB_ANIM_SLIDE_RIGHT }, - { nullptr, 0 } -}; -static_assert(ARRAY_SIZE(AnimTypeNames) == ControlBarSchemeAnimation::CB_ANIM_MAX + 1, "Incorrect array size"); - -static void animSlideRight( ControlBarSchemeAnimation *anim ); - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -ControlBarSchemeImage::ControlBarSchemeImage() -{ - m_name.clear(); - m_position.x = m_position.y = 0; - m_size.x = m_size.y = 0; - m_image = nullptr; - m_layer = 0; -} - -ControlBarSchemeImage::~ControlBarSchemeImage() -{ - m_image = nullptr; -} - -ControlBarSchemeAnimation::ControlBarSchemeAnimation() -{ - m_animDuration = 0; - m_finalPos.x = m_finalPos.y = 0; - m_name.clear(); - m_animType = 0; - m_animImage = nullptr; - m_startPos.x = m_startPos.y = 0; - m_currentFrame = 0; -} - -ControlBarSchemeAnimation::~ControlBarSchemeAnimation() -{ - m_animImage = nullptr; -} - - -void ControlBarScheme::reset() -{ - for (Int i = 0; i < MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS; i++) - { - ControlBarSchemeImageList::iterator it = m_layer[i].begin(); - - while (it != m_layer[i].end()) - { - ControlBarSchemeImage *im = *it; - delete im; - it ++; - } - m_layer[i].clear(); - - } - - - ControlBarSchemeAnimationList::iterator it = m_animations.begin(); - - while (it != m_animations.end()) - { - ControlBarSchemeAnimation *anim = *it; - delete anim; - it ++; - } - m_animations.clear(); - - m_name.clear(); - m_ScreenCreationRes.x = m_ScreenCreationRes.y = 0; - m_side.clear(); - m_buttonQueueImage = nullptr; - m_rightHUDImage = nullptr; - m_optionsButtonEnable = nullptr; - m_optionsButtonHightlited = nullptr; - m_optionsButtonPushed = nullptr; - m_optionsButtonDisabled = nullptr; - - m_idleWorkerButtonEnable = nullptr; - m_idleWorkerButtonHightlited = nullptr; - m_idleWorkerButtonPushed = nullptr; - m_idleWorkerButtonDisabled = nullptr; - - m_buddyButtonEnable = nullptr; - m_buddyButtonHightlited = nullptr; - m_buddyButtonPushed = nullptr; - m_buddyButtonDisabled = nullptr; - - m_beaconButtonEnable = nullptr; - m_beaconButtonHightlited = nullptr; - m_beaconButtonPushed = nullptr; - m_beaconButtonDisabled = nullptr; - - m_genBarButtonIn = nullptr; - m_genBarButtonOn = nullptr; - - m_toggleButtonUpIn = nullptr; - m_toggleButtonUpOn = nullptr; - m_toggleButtonUpPushed = nullptr; - m_toggleButtonDownIn = nullptr; - m_toggleButtonDownOn = nullptr; - m_toggleButtonDownPushed = nullptr; - - m_commandMarkerImage = nullptr; - m_expBarForeground = nullptr; - -} - -ControlBarScheme::~ControlBarScheme() -{ - reset(); -} - -ControlBarScheme::ControlBarScheme() -{ - - m_animations.clear(); - for (Int i = 0; i < MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS; i++) - m_layer[i].clear(); - m_name.clear(); - m_ScreenCreationRes.x = m_ScreenCreationRes.y = 0; - m_side.clear(); - m_buttonQueueImage = nullptr; - m_rightHUDImage = nullptr; - m_buildUpClockColor = GameMakeColor(0,0,0,100); - m_borderBuildColor = GAME_COLOR_UNDEFINED; - m_borderActionColor = GAME_COLOR_UNDEFINED; - m_borderUpgradeColor = GAME_COLOR_UNDEFINED; - m_borderSystemColor = GAME_COLOR_UNDEFINED; - //m_buttonQueueImage = TheMappedImageCollection("") - m_optionsButtonEnable = nullptr; - m_optionsButtonHightlited = nullptr; - m_optionsButtonPushed = nullptr; - m_optionsButtonDisabled = nullptr; - - m_commandBarBorderColor = 0; - - m_idleWorkerButtonEnable = nullptr; - m_idleWorkerButtonHightlited = nullptr; - m_idleWorkerButtonPushed = nullptr; - m_idleWorkerButtonDisabled = nullptr; - - m_buddyButtonEnable = nullptr; - m_buddyButtonHightlited = nullptr; - m_buddyButtonPushed = nullptr; - m_buddyButtonDisabled= nullptr; - - m_beaconButtonEnable = nullptr; - m_beaconButtonHightlited = nullptr; - m_beaconButtonPushed = nullptr; - m_beaconButtonDisabled= nullptr; - - m_genBarButtonIn = nullptr; - m_genBarButtonOn = nullptr; - - m_toggleButtonUpIn = nullptr; - m_toggleButtonUpOn = nullptr; - m_toggleButtonUpPushed = nullptr; - m_toggleButtonDownIn = nullptr; - m_toggleButtonDownOn = nullptr; - m_toggleButtonDownPushed = nullptr; - - m_commandMarkerImage = nullptr; - m_expBarForeground = nullptr; - - m_generalButtonEnable = nullptr; - m_generalButtonHightlited = nullptr; - m_generalButtonPushed = nullptr; - m_generalButtonDisabled = nullptr; - - m_uAttackButtonEnable = nullptr; - m_uAttackButtonHightlited = nullptr; - m_uAttackButtonPushed = nullptr; - - m_genArrow = nullptr; - - m_minMaxButtonEnable = nullptr; - m_minMaxButtonHightlited = nullptr; - m_minMaxButtonPushed = nullptr; - - m_minMaxUL.x = 0; - m_minMaxLR.x = 0; - - m_generalUL.x = 0; - m_generalLR.x = 0; - - m_uAttackUL.x = 0; - m_uAttackLR.x = 0; - - m_optionsUL.x = 0; - m_optionsLR.x = 0; - - m_workerUL.x = 0; - m_workerLR.x = 0; - - m_chatUL.x = 0; - m_chatLR.x = 0; - - m_beaconUL.x = 0; - m_beaconLR.x = 0; - - m_powerBarUL.x = 0; - m_powerBarLR.x = 0; - - m_minMaxUL.y = 0; - m_minMaxLR.y = 0; - - m_generalUL.y = 0; - m_generalLR.y = 0; - - m_uAttackUL.y = 0; - m_uAttackLR.y = 0; - - m_optionsUL.y = 0; - m_optionsLR.y = 0; - - m_workerUL.y = 0; - m_workerLR.y = 0; - - m_chatUL.y = 0; - m_chatLR.y = 0; - - m_beaconUL.y = 0; - m_beaconLR.y = 0; - - m_powerBarUL.y = 0; - m_powerBarLR.y = 0; - - m_moneyUL.x = 0; - m_moneyUL.y = 0; - - m_moneyLR.x = 0; - m_moneyLR.y = 0; -} - - -void ControlBarScheme::init() -{ - if(TheControlBar) - { - TheControlBar->switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); - TheControlBar->updateBuildQueueDisabledImages( m_buttonQueueImage ); - TheControlBar->updateRightHUDImage(m_rightHUDImage); - TheControlBar->updateBuildUpClockColor( m_buildUpClockColor ); - TheControlBar->updateCommandBarBorderColors(m_borderBuildColor, m_borderActionColor, m_borderUpgradeColor,m_borderSystemColor); - TheControlBar->updateBorderColor(m_commandBarBorderColor); - //TheControlBar->updateCommandMarkerImage(m_commandMarkerImage); - TheControlBar->updateSlotExitImage(m_commandMarkerImage); - TheControlBar->updateUpDownImages(m_toggleButtonUpIn, m_toggleButtonUpOn, m_toggleButtonUpPushed, m_toggleButtonDownIn, m_toggleButtonDownOn, m_toggleButtonDownPushed, m_generalButtonEnable, m_generalButtonHightlited); - TheControlBar->setArrowImage( m_genArrow); - } - GameWindow *win = nullptr; - Coord2D resMultiplier; - resMultiplier.x = TheDisplay->getWidth()/INT_TO_REAL(m_ScreenCreationRes.x) ; - resMultiplier.y = TheDisplay->getHeight()/INT_TO_REAL(m_ScreenCreationRes.y); - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PopupCommunicator" ) ); - if(win) - { -// DEBUG_ASSERTCRASH(m_buddyButtonEnable, ("No enable button image for communicator in scheme %s!", m_name.str())); -// DEBUG_ASSERTCRASH(m_buddyButtonHightlited, ("No hilite button image for communicator in scheme %s!", m_name.str())); -// DEBUG_ASSERTCRASH(m_buddyButtonPushed, ("No pushed button image for communicator in scheme %s!", m_name.str())); - GadgetButtonSetEnabledImage(win, m_buddyButtonEnable); - GadgetButtonSetHiliteImage(win, m_buddyButtonHightlited); - GadgetButtonSetHiliteSelectedImage(win, m_buddyButtonPushed); - GadgetButtonSetDisabledImage(win, m_buddyButtonDisabled); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_chatUL.x * resMultiplier.x - parX; - y = m_chatUL.y * resMultiplier.y - parY; - } - else - { - x = m_chatUL.x * resMultiplier.x; - y = m_chatUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_chatLR.x - m_chatUL.x)*resMultiplier.x + COMMAND_BAR_SIZE_OFFSET,(m_chatLR.y - m_chatUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonIdleWorker" ) ); - if(win) - { - GadgetButtonSetEnabledImage(win, m_idleWorkerButtonEnable); - GadgetButtonSetHiliteImage(win, m_idleWorkerButtonHightlited); - GadgetButtonSetHiliteSelectedImage(win, m_idleWorkerButtonPushed); - GadgetButtonSetDisabledImage(win, m_idleWorkerButtonDisabled); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_workerUL.x * resMultiplier.x - parX; - y = m_workerUL.y * resMultiplier.y - parY; - } - else - { - x = m_workerUL.x * resMultiplier.x; - y = m_workerUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - - win->winSetSize((m_workerLR.x - m_workerUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_workerLR.y - m_workerUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - - } - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ExpBarForeground" ) ); - if(win) - { - win->winSetEnabledImage(0, m_expBarForeground); - } - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonOptions" ) ); - if(win) - { - GadgetButtonSetEnabledImage(win, m_optionsButtonEnable); - GadgetButtonSetHiliteImage(win, m_optionsButtonHightlited); - GadgetButtonSetHiliteSelectedImage(win, m_optionsButtonPushed); - GadgetButtonSetDisabledImage(win, m_optionsButtonDisabled); - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_optionsUL.x * resMultiplier.x - parX; - y = m_optionsUL.y * resMultiplier.y - parY; - } - else - { - x = m_optionsUL.x * resMultiplier.x; - y = m_optionsUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_optionsLR.x - m_optionsUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_optionsLR.y - m_optionsUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonPlaceBeacon" ) ); - if(win) - { - GadgetButtonSetEnabledImage(win, m_beaconButtonEnable); - GadgetButtonSetHiliteImage(win, m_beaconButtonHightlited); - GadgetButtonSetHiliteSelectedImage(win, m_beaconButtonPushed); - GadgetButtonSetDisabledImage(win, m_beaconButtonDisabled); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_beaconUL.x * resMultiplier.x - parX; - y = m_beaconUL.y * resMultiplier.y - parY; - } - else - { - x = m_beaconUL.x * resMultiplier.x; - y = m_beaconUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_beaconLR.x - m_beaconUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_beaconLR.y - m_beaconUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:MoneyDisplay" ) ); - if(win) - { - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_moneyUL.x * resMultiplier.x - parX; - y = m_moneyUL.y * resMultiplier.y - parY; - } - else - { - x = m_moneyUL.x * resMultiplier.x; - y = m_moneyUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_moneyLR.x - m_moneyUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_moneyLR.y - m_moneyUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PowerWindow" ) ); - if(win) - { - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_powerBarUL.x * resMultiplier.x - parX; - y = m_powerBarUL.y * resMultiplier.y - parY; - } - else - { - x = m_powerBarUL.x * resMultiplier.x; - y = m_powerBarUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_powerBarLR.x - m_powerBarUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_powerBarLR.y - m_powerBarUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - DEBUG_LOG(("Power Bar UL X:%d Y:%d LR X:%d Y:%d size X:%d Y:%d",m_powerBarUL.x, m_powerBarUL.y,m_powerBarLR.x, m_powerBarLR.y, (m_powerBarLR.x - m_powerBarUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_powerBarLR.y - m_powerBarUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET )); - } - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonGeneral" ) ); - if(win) - { - - GadgetButtonSetEnabledImage(win, m_generalButtonEnable); - GadgetButtonSetHiliteImage(win, m_generalButtonHightlited); - GadgetButtonSetHiliteSelectedImage(win, m_generalButtonPushed); - GadgetButtonSetDisabledImage(win, m_generalButtonDisabled); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_generalUL.x * resMultiplier.x - parX; - y = m_generalUL.y * resMultiplier.y - parY; - } - else - { - x = m_generalUL.x * resMultiplier.x; - y = m_generalUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_generalLR.x - m_generalUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_generalLR.y - m_generalUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonLarge" ) ); - if(win) - { - // The images are set above -// GadgetButtonSetEnabledImage(win, m_minMaxButtonEnable); -// GadgetButtonSetHiliteImage(win, m_minMaxButtonHightlited); -// GadgetButtonSetHiliteSelectedImage(win, m_minMaxButtonPushed); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_minMaxUL.x * resMultiplier.x - parX; - y = m_minMaxUL.y * resMultiplier.y - parY; - } - else - { - x = m_minMaxUL.x * resMultiplier.x; - y = m_minMaxUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_minMaxLR.x - m_minMaxUL.x)*resMultiplier.x + COMMAND_BAR_SIZE_OFFSET,(m_minMaxLR.y - m_minMaxUL.y)*resMultiplier.y + COMMAND_BAR_SIZE_OFFSET); - } - - win= TheWindowManager->winGetWindowFromId( nullptr, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:WinUAttack" ) ); - if(win) - { - win->winSetEnabledImage(0,m_uAttackButtonEnable); - win->winSetDisabledImage(0,m_uAttackButtonHightlited); - - Int x, y; - GameWindow* parent =win->winGetParent(); - if(parent) - { - Int parX, parY; - parent->winGetScreenPosition(&parX, &parY); - x = m_uAttackUL.x * resMultiplier.x - parX; - y = m_uAttackUL.y * resMultiplier.y - parY; - } - else - { - x = m_uAttackUL.x * resMultiplier.x; - y = m_uAttackUL.y * resMultiplier.y; - } - win->winSetPosition(x,y ); - win->winSetSize((m_uAttackLR.x - m_uAttackUL.x)*resMultiplier.x+ COMMAND_BAR_SIZE_OFFSET,(m_uAttackLR.y - m_uAttackUL.y)*resMultiplier.y+ COMMAND_BAR_SIZE_OFFSET); - } -} - -// -// Add an animation to the animation list -//----------------------------------------------------------------------------- -void ControlBarScheme::addAnimation( ControlBarSchemeAnimation *schemeAnim ) -{ - if( !schemeAnim ) - { - DEBUG_CRASH(("Trying to add a null animation to the controlbarscheme")); - return; - } - m_animations.push_back( schemeAnim ); -} - -// -// Add an image to the proper layer list -//----------------------------------------------------------------------------- -void ControlBarScheme::addImage( ControlBarSchemeImage *schemeImage ) -{ - if( !schemeImage ) - { - DEBUG_CRASH(("Trying to add a null image to the controlbarscheme")); - return; - } - - if(schemeImage->m_layer < 0 || schemeImage->m_layer >= MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS) - { - DEBUG_CRASH(("SchemeImage %s attempted to be added to layer %d which is not Between to %d, %d", - schemeImage->m_name.str(), schemeImage->m_layer, 0, MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS)); - // bring the foobar to the front so we make it obvious that something's wrong - schemeImage->m_layer = 0; - } - - m_layer[schemeImage->m_layer].push_back(schemeImage); -} - -// -// Update the position of the image that's animating -//----------------------------------------------------------------------------- -void ControlBarScheme::updateAnim (ControlBarSchemeAnimation * anim) -{ - switch(anim->m_animType) - { - case ControlBarSchemeAnimation::CB_ANIM_SLIDE_RIGHT: - { - animSlideRight( anim ); - break; - } - default: - { - DEBUG_CRASH(("We tried to animate but not animate function was found %d", anim->m_animType)); - } - } -} - -// -// Add an image to the proper layer list -//----------------------------------------------------------------------------- -void ControlBarScheme::update() -{ - ControlBarSchemeAnimationList::iterator it = m_animations.begin(); - - while (it != m_animations.end()) - { - ControlBarSchemeAnimation *anim = *it; - if( !anim ) - { - DEBUG_CRASH(("THere's no Animation in the ControlBarSchemeAnimationList:m_animations")); - return; - } - updateAnim( anim ); - it ++; - } - -} - -// -// Loop through the proper lists and draw everything for the foreground -//----------------------------------------------------------------------------- -void ControlBarScheme::drawForeground( Coord2D multi, ICoord2D offset ) -{ - for(Int i = CONTROL_BAR_SCHEME_FOREGROUND_IMAGE_LAYERS - 1; i >= 0; i--) - { - ControlBarSchemeImageList::iterator it = m_layer[i].begin(); - while (it != m_layer[i].end()) - { - ControlBarSchemeImage *schemeImage = *it; - if( !schemeImage ) - { - DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list")); - it++; - continue; - } - - // if we dont' have an image, don't try to draw it - if(!schemeImage->m_image) - { - it++; - continue; - } - - // draw the image - TheDisplay->drawImage(schemeImage->m_image, schemeImage->m_position.x * multi.x + offset.x, - schemeImage->m_position.y * multi.y + offset.y, - (schemeImage->m_position.x + schemeImage->m_size.x) * multi.x + offset.x, - (schemeImage->m_position.y + schemeImage->m_size.y) * multi.y + offset.y); - - it ++; - } - } -} - -// -// Add an image to the proper layer list -//----------------------------------------------------------------------------- -void ControlBarScheme::drawBackground( Coord2D multi, ICoord2D offset ) -{ - - for(Int i = MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS - 1; i >= CONTROL_BAR_SCHEME_FOREGROUND_IMAGE_LAYERS; i--) - { - ControlBarSchemeImageList::iterator it = m_layer[i].begin(); - while (it != m_layer[i].end()) - { - ControlBarSchemeImage *schemeImage = *it; - if( !schemeImage ) - { - DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list")); - it++; - continue; - } - - // if we don't have an image, don't try to draw it - if(!schemeImage->m_image) - { - it++; - continue; - } - - // draw it - TheDisplay->drawImage(schemeImage->m_image, schemeImage->m_position.x * multi.x + offset.x, - schemeImage->m_position.y * multi.y + offset.y, - (schemeImage->m_position.x + schemeImage->m_size.x) * multi.x + offset.x, - (schemeImage->m_position.y + schemeImage->m_size.y) * multi.y + offset.y); - - it ++; - } - } -} - - -// -// Constructor for the manager -//----------------------------------------------------------------------------- -ControlBarSchemeManager::ControlBarSchemeManager() -{ - m_currentScheme = nullptr; - m_schemeList.clear(); - m_multiplier.x = m_multiplier.y = 1; -} - -// -// Destructor for the Manager -//----------------------------------------------------------------------------- -ControlBarSchemeManager::~ControlBarSchemeManager() -{ - ControlBarSchemeList::iterator it = m_schemeList.begin(); - - // iterate through the list and return the scheme that we're looking for - while (it != m_schemeList.end()) - { - ControlBarScheme *CBScheme = *it; - delete CBScheme; - it ++; - } - m_schemeList.clear(); - m_currentScheme = nullptr; - -} - -// -// Parse the Image Part of the command bar -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::parseImagePart(INI *ini, void *instance, void* /*store*/, const void* /*userData*/) -{ - static const FieldParse myFieldParse[] = - { - { "Position", INI::parseICoord2D, nullptr, offsetof( ControlBarSchemeImage, m_position ) }, - { "Size", INI::parseICoord2D, nullptr, offsetof( ControlBarSchemeImage, m_size ) }, - { "ImageName", INI::parseMappedImage, nullptr, offsetof( ControlBarSchemeImage, m_image ) }, - { "Layer", INI::parseInt, nullptr, offsetof( ControlBarSchemeImage, m_layer ) }, - { nullptr, nullptr, nullptr, 0 } - }; - - ControlBarSchemeImage *schemeImage = NEW ControlBarSchemeImage; - ini->initFromINI(schemeImage, myFieldParse); - ((ControlBarScheme*)instance)->addImage(schemeImage); - -} - -// -// each animation part contains and image, parse it -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::parseAnimatingPartImage(INI *ini, void *instance, void* /*store*/, const void* /*userData*/) -{ - static const FieldParse myFieldParse[] = - { - { "Position", INI::parseICoord2D, nullptr, offsetof( ControlBarSchemeImage, m_position ) }, - { "Size", INI::parseICoord2D, nullptr, offsetof( ControlBarSchemeImage, m_size ) }, - { "ImageName", INI::parseMappedImage, nullptr, offsetof( ControlBarSchemeImage, m_image ) }, - { "Layer", INI::parseInt, nullptr, offsetof( ControlBarSchemeImage, m_layer ) }, - { nullptr, nullptr, nullptr, 0 } - }; - - ControlBarSchemeImage *schemeImage = NEW ControlBarSchemeImage; - ini->initFromINI(schemeImage, myFieldParse); - ((ControlBarSchemeAnimation*)instance)->m_animImage = schemeImage; - -} - -// -// parse the animating part of the control bar scheme -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::parseAnimatingPart(INI *ini, void *instance, void* /*store*/, const void* /*userData*/) -{ - static const FieldParse myFieldParse[] = - { - { "Name", INI::parseAsciiString, nullptr, offsetof( ControlBarSchemeAnimation, m_name ) }, - { "Animation", INI::parseLookupList, AnimTypeNames, offsetof( ControlBarSchemeAnimation, m_animType ) }, - { "Duration", INI::parseDurationUnsignedInt, nullptr, offsetof( ControlBarSchemeAnimation, m_animDuration ) }, - { "FinalPos", INI::parseICoord2D, nullptr, offsetof( ControlBarSchemeAnimation, m_finalPos ) }, - { "ImagePart", ControlBarSchemeManager::parseAnimatingPartImage, nullptr, 0 }, - { nullptr, nullptr, nullptr, 0 } - }; - - ControlBarSchemeAnimation *schemeAnim = NEW ControlBarSchemeAnimation; - ini->initFromINI(schemeAnim, myFieldParse); - ((ControlBarScheme*)instance)->addAnimation(schemeAnim); - ((ControlBarScheme*)instance)->addImage(schemeAnim->m_animImage); -} - - -// -// Create a new control bar and return it. Link it into our control bar list -//----------------------------------------------------------------------------- -ControlBarScheme *ControlBarSchemeManager::newControlBarScheme( AsciiString name ) -{ - ControlBarScheme *cbScheme = findControlBarScheme(name); - if(cbScheme) - { - DEBUG_CRASH(("We're overwriting a previous control bar scheme %s",name.str())); - cbScheme->reset(); - cbScheme->m_name.set( name ); - cbScheme->m_name.toLower(); - return cbScheme; - } - - cbScheme = NEW ControlBarScheme; - - if( !cbScheme || name.isEmpty() ) - { - DEBUG_CRASH(("Could not create controlbar %s", name.str())); - return nullptr; - } - - cbScheme->m_name.set( name ); - cbScheme->m_name.toLower(); - - m_schemeList.push_back(cbScheme); - - return cbScheme; -} - -// -// Find a scheme based on name -//----------------------------------------------------------------------------- -ControlBarScheme *ControlBarSchemeManager::findControlBarScheme( AsciiString name ) -{ - name.toLower(); - - ControlBarSchemeList::iterator it = m_schemeList.begin(); - - // iterate through the list and return the scheme that we're looking for - while (it != m_schemeList.end()) - { - ControlBarScheme *CBScheme = *it; - if( !CBScheme ) - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList")); - return nullptr; - } - if(CBScheme->m_name.compareNoCase( name ) == 0) - return CBScheme; - it ++; - } - return nullptr; -} - -// -// Preload assets -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::preloadAssets( TimeOfDay timeOfDay ) -{ - for (ControlBarSchemeList::iterator it = m_schemeList.begin(); it != m_schemeList.end(); ++it) - { - ControlBarScheme *CBScheme = *it; - if( !CBScheme ) - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList")); - continue; - } - - if (CBScheme->m_buttonQueueImage) - { - TheDisplay->preloadTextureAssets(CBScheme->m_buttonQueueImage->getFilename()); - } - - if (CBScheme->m_rightHUDImage) - { - TheDisplay->preloadTextureAssets(CBScheme->m_rightHUDImage->getFilename()); - } - - for (Int layer = 0; layer < MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS; ++layer) - { - for (ControlBarScheme::ControlBarSchemeImageList::iterator listIt = CBScheme->m_layer[layer].begin(); listIt != CBScheme->m_layer[layer].end(); ++listIt) - { - ControlBarSchemeImage *cbImage = *listIt; - if (cbImage) - { - const Image *image = TheMappedImageCollection->findImageByName( cbImage->m_name ); - if (image) - { - TheDisplay->preloadTextureAssets(image->getFilename()); - } - } - } - } - } -} - -// -// Find a scheme based on name -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::init() -{ - - INI ini; - // Read from INI all the ControlBarSchemes - ini.loadFileDirectory( "Data\\INI\\Default\\ControlBarScheme", INI_LOAD_OVERWRITE, nullptr ); - ini.loadFileDirectory( "Data\\INI\\ControlBarScheme", INI_LOAD_OVERWRITE, nullptr ); - -// //Load the user modified control bar schemes -// WIN32_FIND_DATA findData; -// AsciiString userDataPath; -// if(TheGlobalData) -// { -// userDataPath.format("%sINI\\ControlBarScheme",TheGlobalData->getPath_UserData().str()); -// if (FindFirstFile(userDataPath.str(), &findData) !=INVALID_HANDLE_VALUE) -// ini.loadFileDirectory(userDataPath, INI_LOAD_OVERWRITE, nullptr ); -// } - if( m_schemeList.empty() ) - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file")); - return; - } - -} - -// -// only recommended to use if you know what you're doing, cause you could actually load in -// a control bar built for 16x12 into an 8x6 screen which would use a lot more memory then it should -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::setControlBarScheme(AsciiString schemeName) -{ - ControlBarScheme *tempScheme = findControlBarScheme( schemeName ); - if(tempScheme) - { - // setup the multiplier value - m_multiplier.x = TheDisplay->getWidth() / tempScheme->m_ScreenCreationRes.x; - m_multiplier.y = TheDisplay->getHeight() / tempScheme->m_ScreenCreationRes.y; - m_currentScheme = tempScheme; - } - else - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList")); - m_currentScheme = nullptr; - } - if(m_currentScheme) - m_currentScheme->init(); -} - -// -// Update calls all the animation update calls for the -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::update() -{ - if(m_currentScheme) - m_currentScheme->update(); -} - -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::drawForeground( ICoord2D offset ) -{ - if(m_currentScheme) - m_currentScheme->drawForeground( m_multiplier, offset); -} -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::drawBackground( ICoord2D offset ) -{ - if(m_currentScheme) - m_currentScheme->drawBackground( m_multiplier, offset ); -} - -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::setControlBarSchemeByPlayerTemplate( const PlayerTemplate *pt, Bool useSmall) -{ - if(!pt) - return; - AsciiString side = pt->getSide(); - if(useSmall) - side.concat("Small"); - if(m_currentScheme && (m_currentScheme->m_side.compare(side) == 0)) - { - m_currentScheme->init(); - - DEBUG_LOG(("setControlBarSchemeByPlayer already is using %s as its side", side.str())); - return; - } - - // if we don't have a side, set it to Observer shell - if(side.isEmpty()) - side.set("Observer"); - DEBUG_LOG(("setControlBarSchemeByPlayer used %s as its side", side.str())); - ControlBarScheme *tempScheme = nullptr; - - ControlBarSchemeList::iterator it = m_schemeList.begin(); - - // iterate through the list and return the scheme that we're looking for - while (it != m_schemeList.end()) - { - ControlBarScheme *CBScheme = *it; - if( !CBScheme ) - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList")); - it++; - continue; - } - // find the scheme that best matches our resolution - if(CBScheme->m_side.compareNoCase( side ) == 0) - { - - if((!tempScheme || tempScheme->m_ScreenCreationRes.x < CBScheme->m_ScreenCreationRes.x) )//&& TheDisplay->getWidth() >= CBScheme->m_ScreenCreationRes.x ) - tempScheme = CBScheme; - } - it ++; - } - - if(tempScheme) - { - // setup the multiplier value - m_multiplier.x = TheDisplay->getWidth() / (Real)tempScheme->m_ScreenCreationRes.x; - m_multiplier.y = TheDisplay->getHeight() / (Real)tempScheme->m_ScreenCreationRes.y; - m_currentScheme = tempScheme; - } - else - { - // well, we couldn't find - m_currentScheme = findControlBarScheme("Default"); - DEBUG_LOG(("There's no ControlBarScheme with a side of %s", side.str())); -// m_currentScheme = nullptr; - } - if(m_currentScheme) - m_currentScheme->init(); -} -//----------------------------------------------------------------------------- -void ControlBarSchemeManager::setControlBarSchemeByPlayer(Player *p) -{ - GameWindow *communicatorButton = TheWindowManager->winGetWindowFromId( nullptr, NAMEKEY("ControlBar.wnd:PopupCommunicator") ); - if (communicatorButton && TheControlBar) - { - if (TheRecorder->isMultiplayer()) - TheControlBar->setControlCommand(communicatorButton, TheControlBar->findCommandButton("NonCommand_Communicator") ); - else - TheControlBar->setControlCommand(communicatorButton, TheControlBar->findCommandButton("NonCommand_BriefingHistory") ); - } - - if(!p) - return; - AsciiString side = p->getSide(); - if(m_currentScheme && (m_currentScheme->m_side.compare(side) == 0)) - { - m_currentScheme->init(); - - DEBUG_LOG(("setControlBarSchemeByPlayer already is using %s as its side", side.str())); - return; - } - - // if we don't have a side, set it to Observer shell - if(side.isEmpty()) - side.set("Observer"); - DEBUG_LOG(("setControlBarSchemeByPlayer used %s as its side", side.str())); - ControlBarScheme *tempScheme = nullptr; - - ControlBarSchemeList::iterator it = m_schemeList.begin(); - - // iterate through the list and return the scheme that we're looking for - while (it != m_schemeList.end()) - { - ControlBarScheme *CBScheme = *it; - if( !CBScheme ) - { - DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList")); - it++; - continue; - } - // find the scheme that best matches our resolution - if(CBScheme->m_side.compareNoCase( side ) == 0) - { - - if((!tempScheme || tempScheme->m_ScreenCreationRes.x < CBScheme->m_ScreenCreationRes.x) )//&& TheDisplay->getWidth() >= CBScheme->m_ScreenCreationRes.x ) - tempScheme = CBScheme; - } - it ++; - } - - if(tempScheme) - { - // setup the multiplier value - m_multiplier.x = TheDisplay->getWidth() / (Real)tempScheme->m_ScreenCreationRes.x; - m_multiplier.y = TheDisplay->getHeight() / (Real)tempScheme->m_ScreenCreationRes.y; - m_currentScheme = tempScheme; - } - else - { - // well, we couldn't find - m_currentScheme = findControlBarScheme("Default"); - DEBUG_LOG(("There's no ControlBarScheme with a side of %s", side.str())); -// m_currentScheme = nullptr; - } - if(m_currentScheme) - m_currentScheme->init(); -} - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -static void animSlideRight( ControlBarSchemeAnimation *anim ) -{ - if(!anim->m_animImage || (anim->m_animDuration == 0)) - return; - - UnsignedInt currentFrame = anim->getCurrentFrame(); - ICoord2D startPos = anim->getStartPos(); - // if we're at the end, bring us to the beginning - if(currentFrame == anim->m_animDuration) - { - anim->m_animImage->m_position.x = startPos.x; - anim->m_animImage->m_position.y = startPos.y; - anim->setCurrentFrame( 0 ); - return; - } - else if(currentFrame == 0) - { - // if we're at the beginning, save off the start position - startPos.x = anim->m_animImage->m_position.x; - startPos.y = anim->m_animImage->m_position.y; - anim->setStartPos(startPos); - } - - // now lets animate this bad boy! - - // now increment the frame - currentFrame++; - anim->setCurrentFrame(currentFrame); - - // now lets find what position we should be at. - anim->m_animImage->m_position.x = startPos.x + (((anim->m_finalPos.x - startPos.x) * currentFrame) / anim->m_animDuration); - - -} - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp deleted file mode 100644 index 00ddbe78222..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarStructureInventory.cpp ///////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Methods specific to the control bar garrison display -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/NameKeyGenerator.h" -#include "Common/ThingTemplate.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "GameLogic/Object.h" -#include "GameLogic/Module/OpenContain.h" -#include "GameClient/InGameUI.h" -#include "GameClient/Drawable.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/HotKey.h" - - -#define STOP_ID 10 -#define EVACUATE_ID 11 - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -struct PopulateButtonInfo -{ - Object *source; - Int buttonIndex; - ControlBar* self; - GameWindow** inventoryButtons; -}; - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::populateButtonProc( Object *obj, void *userData ) -{ - PopulateButtonInfo* info = (PopulateButtonInfo*)userData; - - // sanity - DEBUG_ASSERTCRASH( info->buttonIndex < MAX_STRUCTURE_INVENTORY_BUTTONS, - ("Too many objects inside '%s' for the inventory buttons to hold", - info->source->getTemplate()->getName().str()) ); - - // put object in inventory data - info->self->m_containData[ info->buttonIndex ].control = info->inventoryButtons[ info->buttonIndex ]; - info->self->m_containData[ info->buttonIndex ].objectID = obj->getID(); - - // set the UI button that will allow us to press it and cause the object to exit the container - const Image *image; - image = obj->getTemplate()->getButtonImage(); - GadgetButtonSetEnabledImage( info->inventoryButtons[ info->buttonIndex ], image ); - - //Show the auto-contained object's veterancy symbol! - image = calculateVeterancyOverlayForObject( obj ); - GadgetButtonDrawOverlayImage( info->inventoryButtons[ info->buttonIndex ], image ); - - // Enable the button - info->inventoryButtons[ info->buttonIndex ]->winEnable( TRUE ); - - // move to the next button index - info->buttonIndex++; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::populateStructureInventory( Object *building ) -{ - Int i; - - // reset the inventory data - resetContainData(); - - // reset hotkeys -- seeing it only is reset in switching contexts. This is a special case - // because we are building the hotkeys on the fly sort of... and it changes as guys enter - // and leave. Taking this call out will cause multiple hotkeys to be added. - if(TheHotKeyManager) - TheHotKeyManager->reset(); - - // get the contain module of the object - ContainModuleInterface *contain = building->getContain(); - DEBUG_ASSERTCRASH( contain, ("Object in structure inventory does not contain a Contain Module") ); - if (!contain) - return; - - /// @todo srj -- remove hard-coding here, please - const CommandButton *evacuateCommand = findCommandButton( "Command_Evacuate" ); - setControlCommand( m_commandWindows[ EVACUATE_ID ], evacuateCommand ); - m_commandWindows[ EVACUATE_ID ]->winEnable( FALSE ); - - /// @todo srj -- remove hard-coding here, please - const CommandButton *stopCommand = findCommandButton( "Command_Stop" ); - setControlCommand( m_commandWindows[ STOP_ID ], stopCommand ); - m_commandWindows[ STOP_ID ]->winEnable( FALSE ); - - // get the inventory exit command to assign into the button - /// @todo srj -- remove hard-coding here, please - const CommandButton *exitCommand = findCommandButton( "Command_StructureExit" ); - - // get window handles for each of the inventory buttons - AsciiString windowName; - for( i = 0; i < MAX_STRUCTURE_INVENTORY_BUTTONS; i++ ) - { - // show the window - m_commandWindows[ i ]->winHide( FALSE ); - - // - // disable the button for now, it will be enabled if there is something there - // for its contents - // - m_commandWindows[ i ]->winEnable( FALSE ); - m_commandWindows[ i ]->winSetStatus( WIN_STATUS_ALWAYS_COLOR ); - m_commandWindows[ i ]->winClearStatus( WIN_STATUS_NOT_READY ); - - // set an inventory command into the game window UI element - setControlCommand( m_commandWindows[ i ], exitCommand ); - - // Clear any veterancy icon incase the unit leaves! - GadgetButtonDrawOverlayImage( m_commandWindows[ i ], nullptr ); - // - // if the structure can hold a lesser amount inside it than what the GUI displays - // we will completely hide the buttons that can't contain anything - // - if( i + 1 > contain->getContainMax() ) - m_commandWindows[ i ]->winHide( TRUE ); - - - } - - // show the window - m_commandWindows[ EVACUATE_ID ]->winHide( FALSE ); - m_commandWindows[ STOP_ID ]->winHide( FALSE ); - - // if there is at least one item in there enable the evacuate and stop buttons - if( contain->getContainCount() != 0 ) - { - m_commandWindows[ EVACUATE_ID ]->winEnable( TRUE ); - m_commandWindows[ STOP_ID ]->winEnable( TRUE ); - } - - // - // iterate each of the objects inside the container and put them in a button, note - // we're iterating in reverse order here - // - PopulateButtonInfo info; - info.source = building; - info.buttonIndex = 0; - info.self = this; - info.inventoryButtons = m_commandWindows; - contain->iterateContained(populateButtonProc, &info, FALSE ); - - // - // save how many items were contained by the object at this time so that we can update - // it if they change in the future while selected - // - m_lastRecordedInventoryCount = contain->getContainCount(); - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextStructureInventory() -{ - Object *source = m_currentSelectedDrawable->getObject(); - - // - // we're visible, so there is something selected. It is possible that we had a building - // selected that can be garrisoned, and while it was selected the enemy occupied it. - // in that case we want to unselect the building so that we can't see the contents - // - Player *localPlayer = ThePlayerList->getLocalPlayer(); - if( source->isLocallyControlled() == FALSE && - localPlayer->getRelationship( source->getTeam() ) != NEUTRAL ) - { - Drawable *draw = source->getDrawable(); - - if( draw ) - TheInGameUI->deselectDrawable( draw ); - return; - - } - - // - // if the object being displayed in the interface has a different count than we last knew - // about we need to repopulate the buttons of the interface - // - ContainModuleInterface *contain = source->getContain(); - DEBUG_ASSERTCRASH( contain, ("No contain module defined for object in the inventory bar") ); - if (!contain) - return; - - if( m_lastRecordedInventoryCount != contain->getContainCount() ) - populateStructureInventory( source ); - -} - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp deleted file mode 100644 index 5bbe5fe01ec..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarUnderConstruction.cpp ////////////////////////////////////////////////////////// -// Author: Colin Day, March 2002 -// Desc: Methods specific to the control bar under construction context -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/NameKeyGenerator.h" -#include "Common/ThingTemplate.h" - -#include "GameLogic/Object.h" -#include "GameLogic/Module/UpdateModule.h" - -#include "GameClient/Drawable.h" -#include "GameClient/GameText.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GadgetStaticText.h" - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateConstructionTextDisplay( Object *obj ) -{ - UnicodeString text; - static UnsignedInt descID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:UnderConstructionDesc" ); - GameWindow *descWindow = TheWindowManager->winGetWindowFromId( nullptr, descID ); - - // sanity - DEBUG_ASSERTCRASH( descWindow, ("Under construction window not found") ); - - // format the message - text.format( TheGameText->fetch( "CONTROLBAR:UnderConstructionDesc" ), - obj->getConstructionPercent() ); - GadgetStaticTextSetText( descWindow, text ); - - // record this as the last percentage displayed - m_displayedConstructPercent = obj->getConstructionPercent(); - -} - -//------------------------------------------------------------------------------------------------- -/** Populate the interface for an under construction context. */ -//------------------------------------------------------------------------------------------------- -void ControlBar::populateUnderConstruction( Object *objectUnderConstruction ) -{ - - // sanity - if( objectUnderConstruction == nullptr ) - return; - - // get our parent window - GameWindow *parent = m_contextParent[ CP_UNDER_CONSTRUCTION ]; - - // set the cancel construction button -/// @todo srj -- remove hard-coding here, please - const CommandButton *commandButton = findCommandButton( "Command_CancelConstruction" ); - NameKeyType id; - id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonCancelConstruction" ); - GameWindow *win = TheWindowManager->winGetWindowFromId( parent, id ); - - setControlCommand( win, commandButton ); - win->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES ); - - // set the text description of what is building - updateConstructionTextDisplay( objectUnderConstruction ); - - // set the portrait for the thing being constructed - setPortraitByObject( objectUnderConstruction ); - - // and show the rally point, if it should have one, - ExitInterface *exit = objectUnderConstruction->getObjectExitInterface(); - if( exit ) - showRallyPoint( exit->getRallyPoint() ); - - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void ControlBar::updateContextUnderConstruction() -{ - Object *obj = m_currentSelectedDrawable->getObject(); - - // if the object is no longer under construction switch to a new appropriate context - if( !obj->getStatusBits().test( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) - { - - evaluateContextUI(); - return; - - } - - // if the construction percent has changed since what was last shown to the user update the text - if( m_displayedConstructPercent != obj->getConstructionPercent() ) - updateConstructionTextDisplay( obj ); - -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp deleted file mode 100644 index c8ab842a340..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarCallback.cpp /////////////////////////////////////////////////////////////////// -// Author: Colin Day - October 2001 -// Desc: GUI Control bar at the bottom of the screen that houses the -// the build buttons, radar etc. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/GameUtility.h" -#include "Common/NameKeyGenerator.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/MessageStream.h" -#include "Common/ThingFactory.h" -#include "Common/ThingTemplate.h" -#include "Common/Radar.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/Drawable.h" -#include "GameClient/GameWindow.h" -#include "GameClient/Gadget.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GameClient.h" -#include "GameClient/GUICallbacks.h" -#include "GameClient/InGameUI.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/LanguageFilter.h" -#include "GameClient/CommandXlat.h" - -#include "GameLogic/GameLogic.h" -#include "GameLogic/ScriptEngine.h" - -//external declarations of the Gadgets the callbacks can use -WindowLayout *popupCommunicatorLayout = nullptr; - - -//------------------------------------------------------------------------------------------------- -/** Input procedure for the left HUD */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType LeftHUDInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - // - // if the player doesn't have a radar, or the radar is hidden, and the radar is not being - // forced to on, we just eat input over the radar window - // - if( !rts::localPlayerHasRadar() ) - return MSG_HANDLED; - - // If the middle mouse button is depressed, then just let the message fall all the - // way back to the usual middle mouse button processing. - // jkmcd - if( TheMouse->getMouseStatus()->middleState == MBS_Down ) - return MSG_IGNORED; - - switch( msg ) - { - - /** @todo - This is wrong. The radar should be in the message stream, and eat all messages and propagate them - as a new message with the coords converted to world coords and the message flagged as being from - the radar. This would let all of the normal processing occur, and allow individual commands to easily - reject being used on the radar. - */ - - // ------------------------------------------------------------------------ - case GWM_NONE: - case GWM_MOUSE_ENTERING: - case GWM_MOUSE_LEAVING: - { - - // - // consider changing the mouse cursor if we are not in the process of firing - // targeted "superweapons" which we can use the radar itself to fire - // - Bool targeting = FALSE; - const CommandButton *command = TheInGameUI->getGUICommand(); - if( command - && (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER) - && BitIsSet( command->getOptions(), NEED_TARGET_POS ) ) - targeting = TRUE; - - if( targeting == FALSE ) - { - const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables(); - Mouse::MouseCursor cur = Mouse::ARROW; - - if (!(drawableList->empty() || msg == GWM_MOUSE_LEAVING)) - { - if (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE) - { - cur = Mouse::ATTACKMOVETO; - } - else - { - cur = Mouse::MOVETO; - } - } - - // Groovy - TheMouse->setCursor(cur); - - } - - return MSG_HANDLED; - } - - // -------------------------------------------------------------------------------------------- - case GWM_MOUSE_POS: - { - - // get mouse position - ICoord2D mouse; - mouse.x = mData1 & 0xFFFF; - mouse.y = mData1 >> 16; - - // get window screen position - ICoord2D screenPos; - window->winGetScreenPosition( &screenPos.x, &screenPos.y ); - - // set mouse position to be relative to this window - mouse.x -= screenPos.x; - mouse.y -= screenPos.y; - - // is the mouse in the radar window - ICoord2D radar; - if( TheRadar->localPixelToRadar( &mouse, &radar ) ) - { - -/* -// -// this is an example piece of code to find the object under the pixel position -// of the radar ... should we in the future wish to allow commands to be executed -// on objects through the radar. note tho that this is extremely hard to do because -// the pixels on the radar are very small and it's hard to do accurate targeting -// - - Object *obj = TheRadar->objectUnderRadarPixel( &mouse ); - UnicodeString msg; - if( obj ) - msg.format( L"Object under mouse on radar '%S'(%d)", - obj->getTemplate()->getName().str(), obj->getID() ); - else - msg.format( L"Mouse (%d,%d) in Radar window L(%d,%d)", mouse.x, mouse.y, radar.x, radar.y ); - TheInGameUI->message( msg ); -*/ - - // keep the cursor for any context commands - const CommandButton *command = TheInGameUI->getGUICommand(); - if( command - && (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER) - && BitIsSet( command->getOptions(), NEED_TARGET_POS ) ) - { - Int index = TheMouse->getCursorIndex( command->getCursorName() ); - - if( index != Mouse::INVALID_MOUSE_CURSOR ) - TheMouse->setCursor( (Mouse::MouseCursor)index ); - else - TheMouse->setCursor( Mouse::CROSS ); - - } - else - { - // Else we are not super targeting, so we have to try to refresh the move cursor. - // We can't just do this on Enter and Exit, because hotkeys allow state to change - // while we are in the radar. - const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables(); - Mouse::MouseCursor cur = Mouse::ARROW; - - if (!(drawableList->empty() || msg == GWM_MOUSE_LEAVING)) - { - if (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE) - { - cur = Mouse::ATTACKMOVETO; - } - else - { - cur = Mouse::MOVETO; - } - } - - // Groovy - TheMouse->setCursor(cur); - } - - } - - break; - - } - - // ------------------------------------------------------------------------ - case GWM_RIGHT_UP:// Here to eat - case GWM_LEFT_UP:// Here to eat - break; - - case GWM_RIGHT_DOWN: - case GWM_LEFT_DOWN: - { - ICoord2D mouse; - ICoord2D radar; - ICoord2D size; - ICoord2D screenPos; - Coord3D world; - - // get window size - window->winGetSize( &size.x, &size.y ); - - // get mouse position - mouse.x = mData1 & 0xFFFF; - mouse.y = mData1 >> 16; - - // get window screen position - window->winGetScreenPosition( &screenPos.x, &screenPos.y ); - - // set mouse position to be relative to this window - mouse.x -= screenPos.x; - mouse.y -= screenPos.y; - - // - // translate mouse position to radar position ... we know that the mouse - // location given to us here is relative to the HUD window, which is - // completely drawn with the radar ... so it's just a translation from - // our window size we're drawing into to the radar cell size - // - if( TheRadar->localPixelToRadar( &mouse, &radar ) && - TheRadar->radarToWorld( &radar, &world ) ) - { - - // No drawables, or a right click automatically means its a look at. - // Having drawables and being in attack move mode means that we should attack move. - // Having drawables and not being in attack move mode means that we should move. - - const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables(); // locally-owned only - - - // see if the user wants to move the tactical view - if ( drawableList->empty() - || (! TheGlobalData->m_useAlternateMouse && msg == GWM_RIGHT_DOWN) - || (TheGlobalData->m_useAlternateMouse && msg == GWM_LEFT_DOWN) ) - { - TheTacticalView->userLookAt( &world ); - break; - } - - // evaluate any special powers that can be executed from the radar - const CommandButton *command = TheInGameUI->getGUICommand(); - if( command - && (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER) - && BitIsSet( command->getOptions(), NEED_TARGET_POS ) - ) - { - - // do the command - TheGameClient->evaluateContextCommand( nullptr, &world, CommandTranslator::DO_COMMAND ); - - } - else if( command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE) - { - // Attack move has changed from a modifier to a command, so it moves up here. - - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_ATTACKMOVETO ); - msg->appendLocationArgument( world ); - - // Play the unit voice response - pickAndPlayUnitVoiceResponse(TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_ATTACKMOVETO); - } - else - { - GameMessage *newMsg = nullptr; - - // Do the superweapon stuff here, before issuing these other messages - - // GS Leaving commented out to show that isInAttackMoveToMode is NEVER SET. It's a command now, not a modifier. -// if (TheInGameUI->isInAttackMoveToMode()) -// { -// newMsg = TheMessageStream->appendMessage(GameMessage::MSG_DO_ATTACKMOVETO); -// newMsg->appendLocationArgument(world); -// // Play the unit voice response -// pickAndPlayUnitVoiceResponse(drawableList, GameMessage::MSG_DO_ATTACKMOVETO); -// break; -// } - - newMsg = TheMessageStream->appendMessage(GameMessage::MSG_DO_MOVETO); - newMsg->appendLocationArgument(world); - // Play the unit voice response - pickAndPlayUnitVoiceResponse(drawableList, GameMessage::MSG_DO_MOVETO); - - } - - } - - - break; - - } - - // ------------------------------------------------------------------------ - default: - return MSG_IGNORED; - - } - - TheInGameUI->clearAttackMoveToMode(); - return MSG_HANDLED; - -} - -//------------------------------------------------------------------------------------------------- -/** Input procedure for the control bar */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType ControlBarInput( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - return MSG_IGNORED; - -} -void ToggleQuitMenu(); -//------------------------------------------------------------------------------------------------- -/** System callback for the control bar parent */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType ControlBarSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - static NameKeyType buttonCommunicator = NAMEKEY_INVALID; - if(TheScriptEngine && TheScriptEngine->isGameEnding()) - return MSG_IGNORED; - switch( msg ) - { - // -------------------------------------------------------------------------------------------- - case GWM_CREATE: - { - - // get ids for our children controls - buttonCommunicator = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PopupCommunicator" ); - - break; - - } - - //--------------------------------------------------------------------------------------------- - case GBM_MOUSE_ENTERING: - case GBM_MOUSE_LEAVING: - { - GameWindow *control = (GameWindow *)mData1; - - TheControlBar->processContextSensitiveButtonTransition( control, (GadgetGameMessage)msg); - break; - } - - //--------------------------------------------------------------------------------------------- - case GBM_SELECTED: - case GBM_SELECTED_RIGHT: - { - GameWindow *control = (GameWindow *)mData1; - static NameKeyType beaconPlacementButtonID = NAMEKEY("ControlBar.wnd:ButtonPlaceBeacon"); - static NameKeyType beaconDeleteButtonID = NAMEKEY("ControlBar.wnd:ButtonDeleteBeacon"); - static NameKeyType beaconClearTextButtonID = NAMEKEY("ControlBar.wnd:ButtonClearBeaconText"); - static NameKeyType beaconGeneralButtonID = NAMEKEY("ControlBar.wnd:ButtonGeneral"); -// static NameKeyType buttonSmallID = NAMEKEY("ControlBar.wnd:ButtonSmall"); -// static NameKeyType buttonMediumID = NAMEKEY("ControlBar.wnd:ButtonMedium"); - static NameKeyType buttonLargeID = NAMEKEY("ControlBar.wnd:ButtonLarge"); - static NameKeyType buttonOptions = NAMEKEY("ControlBar.wnd:ButtonOptions"); - static NameKeyType buttonIdleWorker = NAMEKEY("ControlBar.wnd:ButtonIdleWorker"); - - Int controlID = control->winGetWindowId(); - if( controlID == buttonCommunicator ) - { - ToggleDiplomacy(FALSE); - } - else if( controlID == beaconPlacementButtonID && TheGameLogic->isInMultiplayerGame() && - ThePlayerList->getLocalPlayer()->isPlayerActive()) - { - const CommandButton *commandButton = TheControlBar->findCommandButton( "Command_PlaceBeacon" ); - TheInGameUI->setGUICommand( commandButton ); - } - else if( controlID == beaconDeleteButtonID && TheGameLogic->isInMultiplayerGame() ) - { - TheMessageStream->appendMessage( GameMessage::MSG_REMOVE_BEACON ); - } - else if( controlID == beaconClearTextButtonID && TheGameLogic->isInMultiplayerGame() ) - { - static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText"); - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr, textID); - if (win) - { - GadgetTextEntrySetText( win, UnicodeString::TheEmptyString ); - } - } - else if( controlID == beaconGeneralButtonID) - { - HideQuitMenu(); - TheControlBar->togglePurchaseScience(); - } - //else if( controlID == buttonSmallID) - // { - // TheControlBar->switchControlBarStage( CONTROL_BAR_STAGE_LOW ); - // } - // else if( controlID == buttonMediumID) - // { - // TheControlBar->switchControlBarStage( CONTROL_BAR_STAGE_SQUISHED ); - // } - - else if( controlID == buttonLargeID) - { - TheControlBar->toggleControlBarStage(); - } - else if( controlID == buttonOptions) - { - ToggleQuitMenu(); - } - else if( controlID == buttonIdleWorker) - { - HideQuitMenu(); - TheInGameUI->selectNextIdleWorker(); - } - else - { - // - // all buttons from all the context sensitive user interface windows are part of the - // control bar, send the button processing that way - // - TheControlBar->processContextSensitiveButtonClick( control, (GadgetGameMessage)msg ); - } - break; - - } - - //--------------------------------------------------------------------------------------------- - case GEM_EDIT_DONE: - { - GameWindow *control = (GameWindow *)mData1; - Int controlID = control->winGetWindowId(); - static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText"); - if (controlID == textID) - { - // set beacon text - if (TheInGameUI->getSelectCount() == 1) - { - GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SET_BEACON_TEXT ); - UnicodeString newText = GadgetTextEntryGetText( control ); - TheLanguageFilter->filterLine(newText); - const WideChar * c = newText.str(); - while ( c && *c ) - { - msg->appendWideCharArgument( *c++ ); - } - msg->appendWideCharArgument( L'\0' ); // trailing null - } - } - break; - } - - //--------------------------------------------------------------------------------------------- - default: - return MSG_IGNORED; - - } - - return MSG_HANDLED; - -} - -extern void showReplayControls(); -extern void hideReplayControls(); -extern void toggleReplayControls(); - -//------------------------------------------------------------------------------------------------- -/** Force the control bar to be shown */ -//------------------------------------------------------------------------------------------------- -void ShowControlBar( Bool immediate ) -{ - if (!TheWindowManager || !TheControlBar) - return; - - showReplayControls(); - - TheControlBar->showSpecialPowerShortcut(); - - Int id = (Int)TheNameKeyGenerator->nameToKey("ControlBar.wnd:ControlBarParent"); - GameWindow *window = TheWindowManager->winGetWindowFromId(nullptr, id); - - if (window) - { - TheControlBar->switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); - TheControlBar->setScaledViewportHeight(); - - if (TheControlBar->m_animateWindowManager && !immediate) - { - TheControlBar->m_animateWindowManager->reset(); - //TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM_TIMED, TRUE, 1000, 0); - TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 500, 0); - TheControlBar->animateSpecialPowerShortcut(TRUE); - } - - window->winHide(FALSE); - } - - // We want to get everything recalced since this is a major state change. - TheControlBar->markUIDirty(); -} - -//------------------------------------------------------------------------------------------------- -/** Force the control bar to be hidden */ -//------------------------------------------------------------------------------------------------- -void HideControlBar( Bool immediate ) -{ - if (!TheWindowManager || !TheControlBar) - return; - - hideReplayControls(); - - TheControlBar->hideSpecialPowerShortcut(); - - Int id = (Int)TheNameKeyGenerator->nameToKey("ControlBar.wnd:ControlBarParent"); - GameWindow *window = TheWindowManager->winGetWindowFromId(nullptr, id); - - if (window) - { -#ifdef SLIDE_LETTERBOX - TheControlBar->setScaledViewportHeight(); -#else - TheControlBar->setFullViewportHeight(); -#endif - if (immediate) - { - window->winHide(TRUE); - } - } - - if (TheControlBar->m_animateWindowManager && !immediate) - { - TheControlBar->m_animateWindowManager->reverseAnimateWindow(); - TheControlBar->animateSpecialPowerShortcut(FALSE); - } - - //Always get rid of the purchase science screen! - TheControlBar->hidePurchaseScience(); -} - -//------------------------------------------------------------------------------------------------- -/** Toggle the control bar on or off */ -//------------------------------------------------------------------------------------------------- -void ToggleControlBar( Bool immediate ) -{ - if (!TheWindowManager || !TheControlBar) - return; - - toggleReplayControls(); - - Int id = (Int)TheNameKeyGenerator->nameToKey("ControlBar.wnd:ControlBarParent"); - GameWindow *window = TheWindowManager->winGetWindowFromId(nullptr, id); - - if (window) - { - if (window->winIsHidden()) - { - TheControlBar->showSpecialPowerShortcut(); - - //now hidden, we're making it visible again so shrink viewport under the window - TheControlBar->setScaledViewportHeight(); - window->winHide(FALSE); - TheControlBar->switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT); - - if (TheControlBar->m_animateWindowManager && !immediate) - { - TheControlBar->m_animateWindowManager->reset(); - //TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM_TIMED, FALSE, 500, 0); - TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 500, 0); - TheControlBar->animateSpecialPowerShortcut(TRUE); - } - } - else - { - TheControlBar->hideSpecialPowerShortcut(); - TheControlBar->setFullViewportHeight(); - window->winHide(TRUE); - } - } -} - -//------------------------------------------------------------------------------------------------- -/** Resize the control bar */ -//------------------------------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp deleted file mode 100644 index 5e8837262ff..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp +++ /dev/null @@ -1,649 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: ControlBarPopupDescription.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Sep 2002 -// -// Filename: ControlBarPopupDescription.cpp -// -// author: Chris Huybregts -// -// purpose: -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - - -// INCLUDES /////////////////////////////////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/GlobalData.h" -#include "Common/BuildAssistant.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "Common/ProductionPrerequisite.h" -#include "Common/ThingTemplate.h" -#include "Common/Upgrade.h" -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/DisconnectMenu.h" -#include "GameClient/GameWindow.h" -#include "GameClient/Gadget.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GameClient.h" -#include "GameClient/GameText.h" -#include "GameClient/GUICallbacks.h" -#include "GameClient/InGameUI.h" -#include "GameClient/ControlBar.h" -#include "GameClient/DisplayStringManager.h" -#include "GameLogic/GameLogic.h" -#include "GameLogic/Module/OverchargeBehavior.h" -#include "GameLogic/Module/ProductionUpdate.h" -#include "GameLogic/ScriptEngine.h" - -#include "GameNetwork/NetworkInterface.h" - -static WindowLayout *theLayout = nullptr; -static GameWindow *theWindow = nullptr; -static AnimateWindowManager *theAnimateWindowManager = nullptr; -static GameWindow *prevWindow = nullptr; -static Bool useAnimation = FALSE; -void ControlBarPopupDescriptionUpdateFunc( WindowLayout *layout, void *param ) -{ - if(TheScriptEngine->isGameEnding()) - TheControlBar->hideBuildTooltipLayout(); - - if(theAnimateWindowManager && !TheControlBar->getShowBuildTooltipLayout() && !theAnimateWindowManager->isReversed()) - theAnimateWindowManager->reverseAnimateWindow(); - else if(!TheControlBar->getShowBuildTooltipLayout() && (!TheGlobalData->m_animateWindows || !useAnimation)) - TheControlBar->deleteBuildTooltipLayout(); - - - if ( useAnimation && theAnimateWindowManager && TheGlobalData->m_animateWindows) - { - Bool wasFinished = theAnimateWindowManager->isFinished(); - theAnimateWindowManager->update(); - if (theAnimateWindowManager->isFinished() && !wasFinished && theAnimateWindowManager->isReversed()) - { - delete theAnimateWindowManager; - theAnimateWindowManager = nullptr; - TheControlBar->deleteBuildTooltipLayout(); - } - } - -} - -// --------------------------------------------------------------------------------------- -void ControlBar::showBuildTooltipLayout( GameWindow *cmdButton ) -{ - if (TheInGameUI->areTooltipsDisabled() || TheScriptEngine->isGameEnding()) - { - return; - } - - Bool passedWaitTime = FALSE; - static Bool isInitialized = FALSE; - static UnsignedInt beginWaitTime; - if(prevWindow == cmdButton) - { - m_showBuildToolTipLayout = TRUE; - if(!isInitialized && beginWaitTime + cmdButton->getTooltipDelay() < timeGetTime()) - { - //DEBUG_LOG(("%d beginwaittime, %d tooltipdelay, %dtimegettime", beginWaitTime, cmdButton->getTooltipDelay(), timeGetTime())); - passedWaitTime = TRUE; - } - - if(!passedWaitTime) - return; - } - else if( !m_buildToolTipLayout->isHidden() ) - { - if(useAnimation && TheGlobalData->m_animateWindows && !theAnimateWindowManager->isReversed()) - theAnimateWindowManager->reverseAnimateWindow(); - else if( useAnimation && TheGlobalData->m_animateWindows && theAnimateWindowManager->isReversed()) - { - return; - } - else - { -// m_buildToolTipLayout->destroyWindows(); -// deleteInstance(m_buildToolTipLayout); -// m_buildToolTipLayout = nullptr; - m_buildToolTipLayout->hide(TRUE); - prevWindow = nullptr; - } - return; - } - - - // will only get here the firsttime through the function through this window - if(!passedWaitTime) - { - prevWindow = cmdButton; - beginWaitTime = timeGetTime(); - isInitialized = FALSE; - return; - } - isInitialized = TRUE; - - if(!cmdButton) - return; - if(BitIsSet(cmdButton->winGetStyle(), GWS_PUSH_BUTTON)) - { - const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(cmdButton); - - if(!commandButton) - return; - - // note that, in this branch, ENABLE_SOLO_PLAY is ***NEVER*** defined... - // this is so that we have a multiplayer build that cannot possibly be hacked - // to work as a solo game! - if (TheGameLogic->isInReplayGame()) - return; - - if (TheInGameUI->isQuitMenuVisible()) - return; - - if (TheDisconnectMenu && TheDisconnectMenu->isScreenVisible()) - return; - - // if (m_buildToolTipLayout) - // { - // m_buildToolTipLayout->destroyWindows(); - // deleteInstance(m_buildToolTipLayout); - // - // } - - m_showBuildToolTipLayout = TRUE; - // m_buildToolTipLayout = TheWindowManager->winCreateLayout( "ControlBarPopupDescription.wnd" ); - // m_buildToolTipLayout->setUpdate(ControlBarPopupDescriptionUpdateFunc); - - populateBuildTooltipLayout(commandButton); - } - else - { - // we're a generic window - if(!BitIsSet(cmdButton->winGetStyle(), GWS_USER_WINDOW) && !BitIsSet(cmdButton->winGetStyle(), GWS_STATIC_TEXT)) - return; - populateBuildTooltipLayout(nullptr, cmdButton); - } - m_buildToolTipLayout->hide(FALSE); - - if (useAnimation && TheGlobalData->m_animateWindows) - { - theAnimateWindowManager = NEW AnimateWindowManager; - theAnimateWindowManager->reset(); - theAnimateWindowManager->registerGameWindow( m_buildToolTipLayout->getFirstWindow(), WIN_ANIMATION_SLIDE_RIGHT_FAST, TRUE, 200 ); - } - - -} - - -void ControlBar::repopulateBuildTooltipLayout() -{ - if(!prevWindow || !m_buildToolTipLayout) - return; - if(!BitIsSet(prevWindow->winGetStyle(), GWS_PUSH_BUTTON)) - return; - const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(prevWindow); - populateBuildTooltipLayout(commandButton); -} - -void ControlBar::populateBuildTooltipLayout( const CommandButton *commandButton, GameWindow *tooltipWin) -{ - if(!m_buildToolTipLayout) - return; - - Player *player = ThePlayerList->getLocalPlayer(); - UnicodeString name, cost, descrip; - UnicodeString requiresFormat = UnicodeString::TheEmptyString, requiresList; - Bool firstRequirement = true; - const ProductionPrerequisite *prereq; - Bool fireScienceButton = false; - - if(commandButton) - { - const ThingTemplate *thingTemplate = commandButton->getThingTemplate(); - const UpgradeTemplate *upgradeTemplate = commandButton->getUpgradeTemplate(); - - ScienceType st = SCIENCE_INVALID; - if(commandButton->getScienceVec().size() > 1) - { - for(size_t j = 0; j < commandButton->getScienceVec().size(); ++j) - { - st = commandButton->getScienceVec()[ j ]; - - if( commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE ) - { - if( !player->hasScience( st ) && j > 0 ) - { - //If we're not looking at a command button that purchases a science, then - //it means we are looking at a command button that can USE the science. This - //means we want to get the description for the previous science -- the one - //we can use, not purchase! - st = commandButton->getScienceVec()[ j - 1 ]; - } - - //Now that we got the science for the button that executes the science, we need - //to generate a simpler help text! - fireScienceButton = true; - - break; - } - else if( !player->hasScience( st ) ) - { - //Purchase science case. The first science we run into that we don't have, that's the - //one we'll want to show! - break; - } - } - } - else if(commandButton->getScienceVec().size() == 1 ) - { - st = commandButton->getScienceVec()[ 0 ]; - } - - if( commandButton->getDescriptionLabel().isNotEmpty() ) - { - descrip = TheGameText->fetch(commandButton->getDescriptionLabel()); - - Drawable *draw = TheInGameUI->getFirstSelectedDrawable(); - Object *selectedObject = draw ? draw->getObject() : nullptr; - if( selectedObject ) - { - //Special case: Append status of overcharge on China power plant. - if( commandButton->getCommandType() == GUI_COMMAND_TOGGLE_OVERCHARGE ) - { - { - OverchargeBehaviorInterface *obi; - for( BehaviorModule **bmi = selectedObject->getBehaviorModules(); *bmi; ++bmi ) - { - obi = (*bmi)->getOverchargeBehaviorInterface(); - if( obi ) - { - descrip.concat( L"\n" ); - if( obi->isOverchargeActive() ) - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNukeReactorOverChargeIsOn" ) ); - else - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNukeReactorOverChargeIsOff" ) ); - } - } - } - } - - //Special case: When building units, the CanMakeType determines reasons for not being able to buy stuff. - else if( thingTemplate ) - { - CanMakeType makeType = TheBuildAssistant->canMakeUnit( selectedObject, commandButton->getThingTemplate() ); - switch( makeType ) - { - case CANMAKE_NO_MONEY: - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNotEnoughMoneyToBuild" ) ); - break; - case CANMAKE_QUEUE_FULL: - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotPurchaseBecauseQueueFull" ) ); - break; - case CANMAKE_PARKING_PLACES_FULL: - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildUnitBecauseParkingFull" ) ); - break; - case CANMAKE_MAXED_OUT_FOR_PLAYER: - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildUnitBecauseMaximumNumber" ) ); - break; - //case CANMAKE_NO_PREREQ: - // descrip.concat( L"\n\n" ); - // descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildDueToPrerequisites" ) ); - // break; - } - } - - //Special case: When building upgrades - else if( upgradeTemplate && !player->hasUpgradeInProduction( upgradeTemplate ) ) - { - if( commandButton->getCommandType() == GUI_COMMAND_PLAYER_UPGRADE || - commandButton->getCommandType() == GUI_COMMAND_OBJECT_UPGRADE ) - { - ProductionUpdateInterface *pui = selectedObject->getProductionUpdateInterface(); - if( pui && pui->getProductionCount() == MAX_BUILD_QUEUE_BUTTONS ) - { - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotPurchaseBecauseQueueFull" ) ); - } - else if( !TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeTemplate, FALSE ) ) - { - descrip.concat( L"\n\n" ); - descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNotEnoughMoneyToBuild" ) ); - } - } - } - - } - - } - - name = TheGameText->fetch(commandButton->getTextLabel().str()); - - if( thingTemplate && commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE ) - { - //We are either looking at building a unit or a structure that may or may not have any - //prerequisites. - - //Format the cost only when we have to pay for it. - cost.format(TheGameText->fetch("TOOLTIP:Cost"), thingTemplate->calcCostToBuild(player)); - - // ask each prerequisite to give us a list of the non satisfied prerequisites - for( Int i=0; igetPrereqCount(); i++ ) - { - prereq = thingTemplate->getNthPrereq(i); - requiresList = prereq->getRequiresList(player); - - if( requiresList != UnicodeString::TheEmptyString ) - { - // make sure to put in 'returns' to space things correctly - if (firstRequirement) - firstRequirement = false; - else - requiresFormat.concat(L", "); - } - requiresFormat.concat(requiresList); - } - if( !requiresFormat.isEmpty() ) - { - UnicodeString requireFormat = TheGameText->fetch("CONTROLBAR:Requirements"); - requiresFormat.format(requireFormat.str(), requiresFormat.str()); - if(!descrip.isEmpty()) - descrip.concat(L"\n"); - descrip.concat(requiresFormat); - - } - } - else if( upgradeTemplate ) - { - //We are looking at an upgrade purchase icon. Maybe we already purchased it? - - Bool hasUpgradeAlready = false; - Bool hasConflictingUpgrade = false; - Bool playerUpgradeButton = commandButton->getCommandType() == GUI_COMMAND_PLAYER_UPGRADE; - Bool objectUpgradeButton = commandButton->getCommandType() == GUI_COMMAND_OBJECT_UPGRADE; - - //Check if the local player has the specified upgrade - hasUpgradeAlready = player->hasUpgradeComplete( upgradeTemplate ); - - if( !hasUpgradeAlready ) - { - //Check if the first selected object has the specified upgrade. - Drawable *draw = TheInGameUI->getFirstSelectedDrawable(); - if( draw ) - { - Object *object = draw->getObject(); - if( object ) - { - hasUpgradeAlready = object->hasUpgrade( upgradeTemplate ); - if( objectUpgradeButton ) - { - hasConflictingUpgrade = !object->affectedByUpgrade( upgradeTemplate ); - } - } - } - } - if( hasConflictingUpgrade && !hasUpgradeAlready ) - { - if( commandButton->getConflictingLabel().isNotEmpty() ) - { - descrip = TheGameText->fetch( commandButton->getConflictingLabel() ); - } - else - { - descrip = TheGameText->fetch( "TOOLTIP:HasConflictingUpgradeDefault" ); - } - } - else if( hasUpgradeAlready && ( playerUpgradeButton || objectUpgradeButton ) ) - { - //See if we can fetch the "already upgraded" text for this upgrade. If not.... use the default "fill me in". - if( commandButton->getPurchasedLabel().isNotEmpty() ) - { - descrip = TheGameText->fetch( commandButton->getPurchasedLabel() ); - } - else - { - descrip = TheGameText->fetch( "TOOLTIP:AlreadyUpgradedDefault" ); - } - } - else if( !hasUpgradeAlready ) - { - //Determine the cost of the upgrade. - cost.format(TheGameText->fetch("TOOLTIP:Cost"),upgradeTemplate->calcCostToBuild(player)); - } - } - else if( st != SCIENCE_INVALID && !fireScienceButton ) - { - TheScienceStore->getNameAndDescription(st, name, descrip); - cost.format(TheGameText->fetch("TOOLTIP:ScienceCost"),TheScienceStore->getSciencePurchaseCost(st)); - - // ask each prerequisite to give us a list of the non satisfied prerequisites - if( thingTemplate ) - { - for( Int i=0; igetPrereqCount(); i++ ) - { - prereq = thingTemplate->getNthPrereq(i); - requiresList = prereq->getRequiresList(player); - - if( requiresList != UnicodeString::TheEmptyString ) - { - // make sure to put in 'returns' to space things correctly - if (firstRequirement) - firstRequirement = false; - else - requiresFormat.concat(L", "); - } - requiresFormat.concat(requiresList); - } - if( !requiresFormat.isEmpty() ) - { - UnicodeString requireFormat = TheGameText->fetch("CONTROLBAR:Requirements"); - requiresFormat.format(requireFormat.str(), requiresFormat.str()); - if(!descrip.isEmpty()) - descrip.concat(L"\n"); - descrip.concat(requiresFormat); - } - } - - } - } - else if(tooltipWin) - { - - if( tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:MoneyDisplay"))) - { - name = TheGameText->fetch("CONTROLBAR:Money"); - descrip = TheGameText->fetch("CONTROLBAR:MoneyDescription"); - } - else if(tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:PowerWindow")) ) - { - name = TheGameText->fetch("CONTROLBAR:Power"); - descrip = TheGameText->fetch("CONTROLBAR:PowerDescription"); - - Player* playerToDisplay = getCurrentlyViewedPlayer(); - - if( playerToDisplay && playerToDisplay->getEnergy() ) - { - Energy *energy = playerToDisplay->getEnergy(); - descrip.format(descrip, energy->getProduction(), energy->getConsumption()); - } - else - { - descrip.format(descrip, 0, 0); - } - } - else if(tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:GeneralsExp")) ) - { - name = TheGameText->fetch("CONTROLBAR:GeneralsExp"); - descrip = TheGameText->fetch("CONTROLBAR:GeneralsExpDescription"); - } - else - { - DEBUG_CRASH(("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows.")); - return; - } - - } - GameWindow *win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextName")); - if(win) - { - GadgetStaticTextSetText(win, name); - } - - win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextCost")); - if(win) - { - GadgetStaticTextSetText(win, cost); - } - win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextDescription")); - if(win) - { - - static NameKeyType winNamekey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" ); - static ICoord2D lastOffset = { 0, 0 }; - - ICoord2D size, newSize, pos; - Int diffSize; - - DisplayString *tempDString = TheDisplayStringManager->newDisplayString(); - win->winGetSize(&size.x, &size.y); - tempDString->setFont(win->winGetFont()); - tempDString->setWordWrap(size.x - 10); - tempDString->setText(descrip); - tempDString->getSize(&newSize.x, &newSize.y); - TheDisplayStringManager->freeDisplayString(tempDString); - tempDString = nullptr; - diffSize = newSize.y - size.y; - GameWindow *parent = m_buildToolTipLayout->getFirstWindow(); - if(!parent) - return; - - parent->winGetSize(&size.x, &size.y); - if(size.y + diffSize < 102) { - diffSize = 102 - size.y; - } - - parent->winSetSize(size.x, size.y + diffSize); - parent->winGetPosition(&pos.x, &pos.y); -// if(size.y + diffSize < 102) -// { -// -// parent->winSetPosition(pos.x, pos.y - (102 - (newSize.y + size.y + diffSize) )); -// } -// else - -// heightChange = controlBarPos.y - m_defaultControlBarPosition.y; - - GameWindow *marker = TheWindowManager->winGetWindowFromId(nullptr,winNamekey); - static ICoord2D basePos; - if(!marker) - { - return; - } - getBackgroundMarkerPos(&basePos.x, &basePos.y); - ICoord2D curPos, offset; - marker->winGetScreenPosition(&curPos.x,&curPos.y); - - offset.x = curPos.x - basePos.x; - offset.y = curPos.y - basePos.y; - - parent->winSetPosition(pos.x, (pos.y - diffSize) + (offset.y - lastOffset.y)); - - lastOffset.x = offset.x; - lastOffset.y = offset.y; - - win->winGetSize(&size.x, &size.y); - win->winSetSize(size.x, size.y + diffSize); - - GadgetStaticTextSetText(win, descrip); - } - m_buildToolTipLayout->hide(FALSE); -} - -// ------------------------------------------------------------------------------------------------ -// ------------------------------------------------------------------------------------------------ -void ControlBar::hideBuildTooltipLayout() -{ - if(theAnimateWindowManager && theAnimateWindowManager->isReversed()) - return; - if(useAnimation && theAnimateWindowManager && TheGlobalData->m_animateWindows) - theAnimateWindowManager->reverseAnimateWindow(); - else - deleteBuildTooltipLayout(); - -} - -void ControlBar::deleteBuildTooltipLayout() -{ - m_showBuildToolTipLayout = FALSE; - prevWindow= nullptr; - m_buildToolTipLayout->hide(TRUE); -// if(!m_buildToolTipLayout) -// return; -// -// m_buildToolTipLayout->destroyWindows(); -// deleteInstance(m_buildToolTipLayout); -// m_buildToolTipLayout = nullptr; - - delete theAnimateWindowManager; - theAnimateWindowManager = nullptr; - -} diff --git a/Generals/Code/GameEngineDevice/CMakeLists.txt b/Generals/Code/GameEngineDevice/CMakeLists.txt index 704352959cf..b7827514490 100644 --- a/Generals/Code/GameEngineDevice/CMakeLists.txt +++ b/Generals/Code/GameEngineDevice/CMakeLists.txt @@ -110,7 +110,7 @@ set(GAMEENGINEDEVICE_SRC # Source/W3DDevice/GameClient/GUI/Gadget/W3DTabControl.cpp # Source/W3DDevice/GameClient/GUI/Gadget/W3DTextEntry.cpp # Source/W3DDevice/GameClient/GUI/Gadget/W3DVerticalSlider.cpp - Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp +# Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMOTD.cpp Source/W3DDevice/GameClient/GUI/W3DGameFont.cpp diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp deleted file mode 100644 index fa6e7ba0d33..00000000000 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp +++ /dev/null @@ -1,1014 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: W3DControlBar.cpp //////////////////////////////////////////////////////////////////////// -// Author: Colin Day -// Desc: Control bar callbacks -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "Common/GameUtility.h" -#include "Common/GlobalData.h" -#include "Common/Radar.h" -#include "Common/Player.h" -#include "Common/PlayerList.h" -#include "GameClient/GameWindow.h" -#include "W3DDevice/GameClient/W3DGameWindow.h" -#include "GameClient/InGameUI.h" -#include "GameClient/Display.h" -#include "GameClient/ControlBar.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/ControlBarScheme.h" -#include "GameClient/MapUtil.h" -#include "GameLogic/GameLogic.h" - -//------------------------------------------------------------------------------------------------- -void W3DCameoMovieDraw( GameWindow *window, WinInstanceData *instData ) -{ - // draw video buffer - VideoBuffer *video = TheInGameUI->cameoVideoBuffer(); - if ( video ) - { - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - TheDisplay->drawVideoBuffer( video, pos.x, pos.y, pos.x + size.x, pos.y + size.y ); - } -} - - -//------------------------------------------------------------------------------------------------- -void W3DLeftHUDDraw( GameWindow *window, WinInstanceData *instData ) -{ - // draw the default stuff - // draw video buffer - VideoBuffer *video = TheInGameUI->videoBuffer(); - if ( video ) - { - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - TheDisplay->drawVideoBuffer( video, pos.x, pos.y, pos.x + size.x, pos.y + size.y ); - } - else if( rts::localPlayerHasRadar() ) - { - ICoord2D pos, size; - //W3DGameWinDefaultDraw( window, instData ); - // window position and size on the display - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - //TheDisplay->drawOpenRect(pos.x, pos.y, size.x,size.y, 1,GameMakeColor(100,100,255,255)); - // draw the radar on the screen now - TheRadar->draw( pos.x + 1, pos.y + 1, size.x - 2, size.y - 2 ); - - } -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void W3DRightHUDDraw( GameWindow *window, WinInstanceData *instData ) -{ - - // draw the default stuff - if( BitIsSet(window->winGetStatus(), WIN_STATUS_IMAGE )) - W3DGameWinDefaultDraw( window, instData ); - -} - -Real logN(Real value, Real logBase) -{ - return (Real)log10(value)/ log10(logBase); -} - -//------------------------------------------------------------------------------------------------- -/** Temporary power meter drawing ... there are some problems with this meter, that is - * what to do when the player doesn't have power, builds a building before a power plant - * etc, but I don't want to spend time on this since it's not a task right now and I'm - * sure it will be in the future. This is just down and dirty to see SOMETHING (CD) */ -//------------------------------------------------------------------------------------------------- -void W3DPowerDraw( GameWindow *window, WinInstanceData *instData ) -{ - //static const Image *endBarYellow = TheMappedImageCollection->findImageByName("PowerBarYellowEndR"); - //static const Image *beginBarYellow = TheMappedImageCollection->findImageByName("PowerBarYellowEndL"); - static const Image *centerBarYellow = TheMappedImageCollection->findImageByName("PowerPointY"); - //static const Image *endBarRed = TheMappedImageCollection->findImageByName("PowerBarRedEndR"); - //static const Image *beginBarRed = TheMappedImageCollection->findImageByName("PowerBarRedEndL"); - static const Image *centerBarRed = TheMappedImageCollection->findImageByName("PowerPointR"); - //static const Image *endBarGreen = TheMappedImageCollection->findImageByName("PowerBarGreenEndR"); - //static const Image *beginBarGreen = TheMappedImageCollection->findImageByName("PowerBarGreenEndL"); - static const Image *centerBarGreen = TheMappedImageCollection->findImageByName("PowerPointG"); - //const Image *endBar = nullptr; - //const Image *beginBar = nullptr; - const Image *centerBar = nullptr; - static const Image *slider = TheMappedImageCollection->findImageByName("PowerBarSlider"); - Player* player = TheControlBar->getCurrentlyViewedPlayer(); - - if(!player || !TheGlobalData) - return; - Energy *energy = player->getEnergy(); - if( energy == nullptr ) - return; - - Int consumption = energy->getConsumption(); - Int production = energy->getProduction(); - - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - static Real pixelsPerInterval = size.x / TheGlobalData->m_powerBarIntervals; - Int delta = TheGlobalData->m_powerBarYellowRange; - - if((consumption > energy->getProduction() - delta) && (consumption <= energy->getProduction())) - { - // 6 and 1 is Green, 6 and 2 is yellow, 6 and 6 is yellow - //endBar = endBarYellow; - //beginBar = beginBarYellow; - centerBar = centerBarYellow; - } - else if( consumption > production) - { - // endBar = endBarRed; -// beginBar = beginBarRed; - centerBar = centerBarRed; - } - else - { - // endBar = endBarGreen; -// beginBar = beginBarGreen; - centerBar = centerBarGreen; - } - //slider = TheMappedImageCollection->findImageByName("PowerBarSlider"); - if( !slider || !centerBar) - return; - - Int range; - range = logN(production, TheGlobalData->m_powerBarBase) * (size.x / TheGlobalData->m_powerBarIntervals); - if(range >= size.x) - range = size.x; -// if(range < endBar->getImageWidth() + beginBar->getImageWidth()) -// range = endBar->getImageWidth() + beginBar->getImageWidth(); - - - -// // get image sizes for the ends -// ICoord2D leftSize, rightSize, start, end; -// leftSize.x = beginBar->getImageWidth(); -// leftSize.y = beginBar->getImageHeight(); -// rightSize.x = endBar->getImageWidth(); -// rightSize.y = endBar->getImageHeight(); -// -// // get two key points used in the end drawing -// ICoord2D leftEnd, rightStart; -// leftEnd.x = pos.x + leftSize.x; -// leftEnd.y = pos.y + size.y; -// rightStart.x = pos.x + range - rightSize.x; -// rightStart.y = pos.y; - - // draw the center repeating bar - Int centerWidth, pieces; - - // get width we have to draw our repeating center in - centerWidth = range; //rightStart.x - leftEnd.x; - - if( centerWidth > 0) - { - - // how many whole repeating pieces will fit in that width - pieces = centerWidth / centerBar->getImageWidth(); - ICoord2D start, end; - // draw the pieces - start.x = pos.x; - start.y = pos.y; - end.y = start.y + size.y;// + yOffset; - for( Int i = 0; i < pieces; i++ ) - { - - end.x = start.x + centerBar->getImageWidth(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - start.x += centerBar->getImageWidth(); - - } - - // we will draw the image but clip the parts we don't want to show - IRegion2D reg; - reg.lo.x = start.x; - reg.lo.y = start.y; - reg.hi.x = pos.x + size.x;//rightStart.x; - reg.hi.y = pos.y + size.y; - centerWidth = pos.x +size.x - start.x; - if( centerWidth > 0) - { - TheDisplay->setClipRegion(®); - end.x = start.x + centerBar->getImageWidth(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - TheDisplay->enableClipping(FALSE); - } - -// // draw left end -// start.x = pos.x; -// start.y = pos.y; -// end = leftEnd; -// TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); -// -// // draw right end -// start = rightStart; -// end.x = start.x + rightSize.x; -// end.y = start.y + size.y; -// TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - Int posXstart; - Int posXend; - Real consumptionForNeedle = (consumption == 1) ? 1.5f : INT_TO_REAL(consumption);//Log(1) == 0, but we need to show something for 1 power used. - range = logN(consumptionForNeedle, TheGlobalData->m_powerBarBase) * (size.x / TheGlobalData->m_powerBarIntervals); - if(centerWidth <= 0 && range <= 0) - return; - if(range >= size.x) - { - posXstart = pos.x + size.x - slider->getImageWidth(); - posXend = pos.x + size.x; - } - else - { - posXstart = pos.x + range - slider->getImageWidth()/2; - posXend = pos.x + range + slider->getImageWidth()/2; - } - if(posXstart <=pos.x) - { - posXstart = pos.x; - posXend = pos.x + slider->getImageWidth(); - } - TheWindowManager->winDrawImage(slider, posXstart, pos.y + size.y - slider->getImageHeight(), posXend, pos.y + size.y); -} - -void W3DPowerDrawA( GameWindow *window, WinInstanceData *instData ) -{ - static const Image *endBarYellow = TheMappedImageCollection->findImageByName("PowerBarYellowEndR"); - static const Image *beginBarYellow = TheMappedImageCollection->findImageByName("PowerBarYellowEndL"); - static const Image *centerBarYellow = TheMappedImageCollection->findImageByName("PowerBarYellow"); - static const Image *endBarRed = TheMappedImageCollection->findImageByName("PowerBarRedEndR"); - static const Image *beginBarRed = TheMappedImageCollection->findImageByName("PowerBarRedEndL"); - static const Image *centerBarRed = TheMappedImageCollection->findImageByName("PowerBarRed"); - static const Image *endBarGreen = TheMappedImageCollection->findImageByName("PowerBarGreenEndR"); - static const Image *beginBarGreen = TheMappedImageCollection->findImageByName("PowerBarGreenEndL"); - static const Image *centerBarGreen = TheMappedImageCollection->findImageByName("PowerBarGreen"); - const Image *endBar = nullptr; - const Image *beginBar = nullptr; - const Image *centerBar = nullptr; - static const Image *slider = TheMappedImageCollection->findImageByName("PowerBarSlider"); - Player* player = TheControlBar->getCurrentlyViewedPlayer(); - - if(!player || !TheGlobalData) - return; - Energy *energy = player->getEnergy(); - if( energy == nullptr ) - return; - - Int consumption = energy->getConsumption(); - Int production = energy->getProduction(); - - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - static Real pixelsPerInterval = size.x / TheGlobalData->m_powerBarIntervals; - Int delta = TheGlobalData->m_powerBarYellowRange; - - if((consumption > energy->getProduction() - delta) && (consumption <= energy->getProduction())) - { - // 6 and 1 is Green, 6 and 2 is yellow, 6 and 6 is yellow - endBar = endBarYellow; - beginBar = beginBarYellow; - centerBar = centerBarYellow; - } - else if( consumption > production) - { - endBar = endBarRed; - beginBar = beginBarRed; - centerBar = centerBarRed; - } - else - { - endBar = endBarGreen; - beginBar = beginBarGreen; - centerBar = centerBarGreen; - } - //slider = TheMappedImageCollection->findImageByName("PowerBarSlider"); - if( !slider || !endBar || !beginBar || !centerBar) - return; - - Int range; - range = logN(production, TheGlobalData->m_powerBarBase) * (size.x / TheGlobalData->m_powerBarIntervals); - if(range >= size.x) - range = size.x; - if(range < endBar->getImageWidth() + beginBar->getImageWidth()) - range = endBar->getImageWidth() + beginBar->getImageWidth(); - - - - // get image sizes for the ends - ICoord2D leftSize, rightSize, start, end; - leftSize.x = beginBar->getImageWidth(); - leftSize.y = beginBar->getImageHeight(); - rightSize.x = endBar->getImageWidth(); - rightSize.y = endBar->getImageHeight(); - - // get two key points used in the end drawing - ICoord2D leftEnd, rightStart; - leftEnd.x = pos.x + leftSize.x; - leftEnd.y = pos.y + size.y; - rightStart.x = pos.x + range - rightSize.x; - rightStart.y = pos.y; - - // draw the center repeating bar - Int centerWidth, pieces; - - // get width we have to draw our repeating center in - centerWidth = rightStart.x - leftEnd.x; - - if( centerWidth <= 0) - { - // draw left end - start.x = pos.x; - start.y = pos.y; - end.y = leftEnd.y; - end.x = pos.x + range/2; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start.y = rightStart.y; - start.x = end.x; - end.x = pos.x + range; - end.y = start.y + size.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - else - { - - // how many whole repeating pieces will fit in that width - pieces = centerWidth / centerBar->getImageWidth(); - - // draw the pieces - start.x = leftEnd.x; - start.y = pos.y; - end.y = start.y + size.y; //centerImage->getImageHeight() + yOffset; - for( Int i = 0; i < pieces; i++ ) - { - - end.x = start.x + centerBar->getImageWidth(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - start.x += centerBar->getImageWidth(); - - } - - // we will draw the image but clip the parts we don't want to show - IRegion2D reg; - reg.lo.x = start.x; - reg.lo.y = start.y; - reg.hi.x = rightStart.x; - reg.hi.y = end.y; - centerWidth = rightStart.x - start.x; - if( centerWidth > 0) - { - TheDisplay->setClipRegion(®); - end.x = start.x + centerBar->getImageWidth(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - TheDisplay->enableClipping(FALSE); - } - - // draw left end - start.x = pos.x; - start.y = pos.y; - end = leftEnd; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start = rightStart; - end.x = start.x + rightSize.x; - end.y = start.y + size.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - Int posXstart; - Int posXend; - Real consumptionForNeedle = (consumption == 1) ? 1.5f : INT_TO_REAL(consumption);//Log(1) == 0, but we need to show something for 1 power used. - range = logN(consumptionForNeedle, TheGlobalData->m_powerBarBase) * (size.x / TheGlobalData->m_powerBarIntervals); - if(range >= size.x) - { - posXstart = pos.x + size.x - slider->getImageWidth(); - posXend = pos.x + size.x; - } - else - { - posXstart = pos.x + range - slider->getImageWidth()/2; - posXend = pos.x + range + slider->getImageWidth()/2; - } - if(posXstart <=pos.x) - { - posXstart = pos.x; - posXend = pos.x + slider->getImageWidth(); - } - TheWindowManager->winDrawImage(slider, posXstart, pos.y + size.y - slider->getImageHeight(), posXend, pos.y + size.y); -} - -void W3DCommandBarGridDraw( GameWindow *window, WinInstanceData *instData ) -{ - if( BitIsSet(window->winGetStatus(), WIN_STATUS_IMAGE )) - { - W3DGameWinDefaultDraw( window, instData ); - return; - } - - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - Color color = TheControlBar->getBorderColor(); - window->winSetEnabledBorderColor(0, color); - W3DGameWinDefaultDraw( window, instData ); - - TheDisplay->drawLine(pos.x, pos.y + size.y * .33, pos.x + size.x, pos.y+ size.y*.33, 1,color); - TheDisplay->drawLine(pos.x, pos.y + size.y * .66, pos.x + size.x, pos.y+ size.y*.66, 1,color); - TheDisplay->drawLine(pos.x + size.x * .33, pos.y, pos.x + size.x *.33, pos.y +size.y, 1,color); - TheDisplay->drawLine(pos.x + size.x * .66, pos.y, pos.x + size.x *.66, pos.y + size.y, 1,color); - - - - -} - -void W3DCommandBarGenExpDraw( GameWindow *window, WinInstanceData *instData ) -{ - // TheSuperHackers @bugfix Stubbjax 08/08/2025 Show the experience bar for observers - Player* player = TheControlBar->getCurrentlyViewedPlayer(); - - if (!player) - return; - - static const Image *endBar = TheMappedImageCollection->findImageByName("GenExpBarTop1"); - static const Image *beginBar = TheMappedImageCollection->findImageByName("GenExpBarBottom1"); - static const Image *centerBar = TheMappedImageCollection->findImageByName("GenExpBar1"); - Int progress = 0; - Int skillPointsRequired = player->getSkillPointsLevelUp() - player->getSkillPointsLevelDown(); - - // TheSuperHackers @bugfix Mauller 04/05/2025 Prevent possible division by zero - if ( skillPointsRequired > 0) - { - progress = ( ((player->getSkillPoints() - player->getSkillPointsLevelDown()) * 100) / skillPointsRequired ); - } - - if(progress <= 0) - return; - - // GS This should never be necessary, but scripts can change the points required or even disable a level. - // A disabled level will be -1 for points required. Just be totally safe and bind to 100, and we will - // fix the scripts to bind the points gained later. - if( progress > 100 ) - progress = 100; - - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - - - if( !endBar || !beginBar || !centerBar) - return; - - Int range; - range = size.y * progress / 100; - - - // get image sizes for the ends - ICoord2D topSize, bottomSize, start, end; - bottomSize.x = beginBar->getImageWidth(); - bottomSize.y = beginBar->getImageHeight(); - topSize.x = endBar->getImageWidth(); - topSize.y = endBar->getImageHeight(); - - // get two key points used in the end drawing - ICoord2D bottomEnd, topStart; - bottomEnd.x = pos.x + size.x; - bottomEnd.y = pos.y + size.y - bottomSize.y; - topStart.x = pos.x; - topStart.y = pos.y +size.y - range - topSize.y; - - // draw the center repeating bar - Int centerWidth, pieces; - - // get width we have to draw our repeating center in - centerWidth = bottomEnd.y - topStart.y; - - if( centerWidth <= 0) - { - // draw left end - start.x = pos.x; - start.y = pos.y + size.y - bottomSize.y; - end.y = pos.y + size.y; - end.x = pos.x + size.x; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start.y = pos.y + size.y - bottomSize.y - topSize.y; - start.x = pos.x; - end.x = pos.x + size.x; - end.y = start.y + topSize.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - else - { - - // how many whole repeating pieces will fit in that width - pieces = centerWidth / centerBar->getImageHeight(); - - // draw the pieces - start.x = pos.x; - start.y = topStart.y; - end.x = start.x + size.x; //centerImage->getImageHeight() + yOffset; - for( Int i = 0; i < pieces; i++ ) - { - - end.y = start.y + centerBar->getImageHeight(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - start.y += centerBar->getImageHeight(); - - } - - // we will draw the image but clip the parts we don't want to show - IRegion2D reg; - reg.lo.x = start.x; - reg.lo.y = start.y; - reg.hi.x = bottomEnd.x; - reg.hi.y = bottomEnd.y; - centerWidth = bottomEnd.y - start.y; - if( centerWidth > 0) - { - TheDisplay->setClipRegion(®); - end.y = start.y + centerBar->getImageHeight(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - TheDisplay->enableClipping(FALSE); - } - - // draw left end - end.x = pos.x + size.x; - end.y = pos.y + size.y; - start.x = pos.x; - start.y = bottomEnd.y; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start.x = pos.x; - start.y = pos.y +size.y - range; - end.x = pos.x + size.x; - end.y = pos.y +size.y - range - topSize.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - -} - -void W3DCommandBarTopDraw( GameWindow *window, WinInstanceData *instData ) -{ - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonGeneral")); - if(!win || win->winIsHidden() || !ThePlayerList->getLocalPlayer()->isPlayerActive()) - return; - -// TheControlBar->drawTransitionHandler(); - -// ICoord2D pos, size, imageStart, imageEnd; -// win->winGetScreenPosition(&pos.x, &pos.y); -// win->winGetSize(&size.x, &size.y); -//// const Image *image =TheControlBar->getStarImage(); -// imageStart.x = pos.x + size.x/2 - image->getImageWidth()/2; -// imageStart.y = pos.y + size.y/2 - image->getImageHeight()/2; -// imageEnd.x = imageStart.x + image->getImageWidth(); -// imageEnd.y = imageStart.y + image->getImageHeight(); -// TheDisplay->drawImage(TheControlBar->getStarImage(), imageStart.x, imageStart.y, imageEnd.x, imageEnd.y); -} - - -void W3DCommandBarBackgroundDraw( GameWindow *window, WinInstanceData *instData ) -{ - - ControlBarSchemeManager *man = TheControlBar->getControlBarSchemeManager(); - if(!man) - return; - static NameKeyType winNamekey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" ); - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr,winNamekey); - static ICoord2D basePos; - if(!win) - { - return; - //win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" )); - } - TheControlBar->getBackgroundMarkerPos(&basePos.x, &basePos.y); - ICoord2D pos, offset; - win->winGetScreenPosition(&pos.x,&pos.y); - offset.x = pos.x - basePos.x; - offset.y = pos.y - basePos.y; - - man->drawBackground(offset); -} - - -void W3DCommandBarForegroundDraw( GameWindow *window, WinInstanceData *instData ) -{ - - ControlBarSchemeManager *man = TheControlBar->getControlBarSchemeManager(); - if(!man) - return; - - static NameKeyType winNamekey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" ); - GameWindow *win = TheWindowManager->winGetWindowFromId(nullptr,winNamekey); - static ICoord2D basePos; - if(!win) - { - return; - //win = TheWindowManager->winGetWindowFromId(nullptr,TheNameKeyGenerator->nameToKey( "ControlBar.wnd:BackgroundMarker" )); - } - TheControlBar->getForegroundMarkerPos(&basePos.x, &basePos.y); - ICoord2D pos, offset; - win->winGetScreenPosition(&pos.x,&pos.y); - offset.x = pos.x - basePos.x; - offset.y = pos.y - basePos.y; - - man->drawForeground(offset); - -} - -void W3DNoDraw( GameWindow *window, WinInstanceData *instData ) -{ - - // draw the default stuff -// W3DGameWinDefaultDraw( window, instData ); - -} - -void drawSkinnyBorder( Int x, Int y, Int width, Int height); -void W3DDrawMapPreview( GameWindow *window, WinInstanceData *instData) -{ - MapMetaData *mmData = (MapMetaData *)window->winGetUserData(); - Int pixelX, pixelY, width, height; - // if the local player does not have a radar then we can't draw anything - window->winGetScreenPosition(&pixelX, &pixelY); - window->winGetSize(&width, &height); - if(!mmData) - { - W3DGameWinDefaultDraw( window, instData ); - drawSkinnyBorder(pixelX - 1, pixelY - 1, width + 2, height + 2); - return; - } - - - - - // - // given a upper left corner at pixelX|Y and a width and height to draw into, figure out - // where we should start and end the image so that the final drawn image has the - // same ratio as the map and isn't stretched or distorted - // - ICoord2D ul, lr; - findDrawPositions( pixelX, pixelY, width, height, mmData->m_extent, &ul, &lr ); - -// Int scaledWidth = lr.x - ul.x; -// Int scaledHeight = lr.y - ul.y; - - // draw black border areas where we need map - Color fillColor = GameMakeColor( 0, 0, 0, 255 ); - Color lineColor = GameMakeColor( 50, 50, 50, 255 ); - - if( mmData->m_extent.width()/width >= mmData->m_extent.height()/height ) - { - - // draw horizontal bars at top and bottom - TheDisplay->drawFillRect( pixelX, pixelY, width, ul.y - pixelY - 1, fillColor ); - TheDisplay->drawFillRect( pixelX, lr.y + 1, width, pixelY + height - lr.y - 1, fillColor); - TheDisplay->drawLine(pixelX, ul.y, pixelX + width, ul.y, 1, lineColor); - TheDisplay->drawLine(pixelX, lr.y + 1, pixelX + width, lr.y + 1, 1, lineColor); - - } - else - { - - // draw vertical bars to the left and right - TheDisplay->drawFillRect( pixelX, pixelY, ul.x - pixelX - 1, height, fillColor ); - TheDisplay->drawFillRect( lr.x + 1, pixelY, width - (lr.x - pixelX) - 1, height, fillColor ); - TheDisplay->drawLine(ul.x, pixelY, ul.x, pixelY + height, 1, lineColor); - TheDisplay->drawLine(lr.x + 1, pixelY, lr.x + 1, pixelY + height, 1, lineColor); - - } - - if(!BitIsSet(window->winGetStatus(), WIN_STATUS_IMAGE) || !window->winGetEnabledImage(0)) - TheDisplay->drawFillRect(ul.x, ul.y, lr.x -ul.x, lr.y-ul.y, lineColor); - else - TheDisplay->drawImage(window->winGetEnabledImage(0) , ul.x, ul.y, lr.x, lr.y ); - - const Image *image = TheMappedImageCollection->findImageByName("TecBuilding"); - ICoord2DList::iterator it = TheSupplyAndTechImageLocations.m_techPosList.begin(); - if(image) - while(it != TheSupplyAndTechImageLocations.m_techPosList.end()) - { - TheDisplay->drawImage(image, pixelX + it->x, pixelY + it->y, pixelX + it->x + SUPPLY_TECH_SIZE, pixelY + it->y +SUPPLY_TECH_SIZE); - it++; - } - - image = TheMappedImageCollection->findImageByName("Cash"); - it = TheSupplyAndTechImageLocations.m_supplyPosList.begin(); - if(image) - while(it != TheSupplyAndTechImageLocations.m_supplyPosList.end()) - { - TheDisplay->drawImage(image, pixelX + it->x, pixelY + it->y, pixelX + it->x + SUPPLY_TECH_SIZE, pixelY + it->y +SUPPLY_TECH_SIZE); - it++; - } - drawSkinnyBorder(pixelX - 1, pixelY - 1, width + 2, height + 2); -} - -void drawSkinnyBorder( Int x, Int y, Int width, Int height) -{ - - enum - { - BORDER_CORNER_SIZE = 5, - BORDER_LINE_SIZE = 5, - }; - Int Offset = 2; - Int OffsetLower = 5; - - // save original x, y - Int originalX = x; - Int originalY = y; - Int maxX = x + width; - Int maxY = y + height; - Int x2, y2; // used for simultaneous drawing of line pairs - Int size = 5; - Int halfSize = size / 2; - const Image *image1, *image2; - // Draw Horizontal Lines - // All border pieces are based on a 10 pixel offset from the centerline - y = originalY - Offset; - y2 = maxY - OffsetLower; - x2 = maxX - (OffsetLower + BORDER_LINE_SIZE); - image1 = TheMappedImageCollection->findImageByName("FrameT"); - image2 = TheMappedImageCollection->findImageByName("FrameB"); - for( x=(originalX + 3); x <= x2; x += BORDER_LINE_SIZE ) - { - - TheDisplay->drawImage( image1, - x, y, x + size, y + size ); - TheDisplay->drawImage( image2, - x, y2, x + size, y2 + size ); - - } - - x2 = maxX - 5;//BORDER_CORNER_SIZE; - - // x == place to draw remainder if any - if( (x2 - x) >= (BORDER_LINE_SIZE / 2) ) - { - - //Blit Half piece - TheDisplay->drawImage( image1, - x, y, x + halfSize, y + size ); - TheDisplay->drawImage( image2, - x, y2, x + halfSize, y2 + size ); - - x += (BORDER_LINE_SIZE / 2); - - } - - // x2 - x ... must now be less than a half piece - // check for equals and if not blit an adjusted half piece border pieces have - // a two pixel repeat so we will blit one pixel over if necessary to line up - // the art, but we'll cover-up the overlap with the corners - if( x < x2 ) - { - x -= ((BORDER_LINE_SIZE / 2) - (((x2 - x) + 1) & ~1)); - - //Blit Half piece - TheDisplay->drawImage(image1, - x, y, x + halfSize, y + size ); - TheDisplay->drawImage( image2, - x, y2, x + halfSize, y2 + size ); - - } - - // Draw Vertical Lines - // All border pieces are based on a 10 pixel offset from the centerline - image1 = TheMappedImageCollection->findImageByName("FrameL"); - image2 = TheMappedImageCollection->findImageByName("FrameR"); - - x = originalX - Offset; - x2 = maxX - OffsetLower; - y2 = maxY - (OffsetLower + BORDER_LINE_SIZE); - - for( y=(originalY + 3); y <= y2; y += BORDER_LINE_SIZE ) - { - - TheDisplay->drawImage( image1, - x, y, x + size, y + size ); - TheDisplay->drawImage( image2, - x2, y, x2 + size, y + size ); - - } - - y2 = maxY - OffsetLower;//BORDER_CORNER_SIZE; - - // y == place to draw remainder if any - if( (y2 - y) >= (BORDER_LINE_SIZE / 2) ) - { - - //Blit Half piece - TheDisplay->drawImage( image1, - x, y, x + size, y + halfSize ); - TheDisplay->drawImage( image2, - x2, y, x2 + size, y + halfSize ); - - y += (BORDER_LINE_SIZE / 2); - } - - // y2 - y ... must now be less than a half piece - // check for equals and if not blit an adjusted half piece border pieces have - // a two pixel repeat so we will blit one pixel over if necessary to line up - // the art, but we'll cover-up the overlap with the corners - if( y < y2 ) - { - y -= ((BORDER_LINE_SIZE / 2) - (((y2 - y) + 1) & ~1)); - - //Blit Half piece - TheDisplay->drawImage( image1, - x, y, x + size, y + halfSize ); - TheDisplay->drawImage( image2, - x2, y, x2 + size, y + halfSize ); - - } - - // Draw Corners - x = originalX - 2;//BORDER_CORNER_SIZE ; - y = originalY - 2;//BORDER_CORNER_SIZE; - image1 = TheMappedImageCollection->findImageByName("FrameCornerUL"); - TheDisplay->drawImage( image1, - x, y, x + size, y + size ); - x = maxX - 5;//BORDER_CORNER_SIZE; - y = originalY - 2;//BORDER_CORNER_SIZE; - image1 = TheMappedImageCollection->findImageByName("FrameCornerUR"); - TheDisplay->drawImage(image1, - x, y, x + size, y + size ); - x = originalX - 2;//BORDER_CORNER_SIZE; - y = maxY - 5;//BORDER_CORNER_SIZE; - image1 = TheMappedImageCollection->findImageByName("FrameCornerLL"); - TheDisplay->drawImage( image1, - x, y, x + size, y + size ); - x = maxX - 5;//BORDER_CORNER_SIZE; - y = maxY - 5;//BORDER_CORNER_SIZE; - image1 = TheMappedImageCollection->findImageByName("FrameCornerLR"); - TheDisplay->drawImage(image1, - x, y, x + size, y + size ); - - -} - - -void W3DCommandBarHelpPopupDraw( GameWindow *window, WinInstanceData *instData ) -{ - - static const Image *endBar = TheMappedImageCollection->findImageByName("Helpbox-top"); - static const Image *beginBar = TheMappedImageCollection->findImageByName("Helpbox-bottom"); - static const Image *centerBar = TheMappedImageCollection->findImageByName("Helpbox-middle"); - - ICoord2D pos, size; - window->winGetScreenPosition( &pos.x, &pos.y ); - window->winGetSize( &size.x, &size.y ); - - - - if( !endBar || !beginBar || !centerBar) - return; - - -// Int range; -// range = size.y; - - - // get image sizes for the ends - ICoord2D topSize, bottomSize, start, end; - bottomSize.x = beginBar->getImageWidth(); - bottomSize.y = beginBar->getImageHeight(); - topSize.x = endBar->getImageWidth(); - topSize.y = endBar->getImageHeight(); - - // get two key points used in the end drawing - ICoord2D bottomEnd, topStart; - bottomEnd.x = pos.x + size.x; - bottomEnd.y = pos.y + size.y - bottomSize.y; - topStart.x = pos.x; - topStart.y = pos.y +size.y - topSize.y; - - // draw the center repeating bar - Int centerWidth, pieces; - - // get width we have to draw our repeating center in - centerWidth = size.y - topSize.y - bottomSize.y; - - if( centerWidth <= 0) - { - // draw left end - start.x = pos.x; - start.y = pos.y + size.y - bottomSize.y; - end.y = pos.y + size.y; - end.x = pos.x + size.x; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start.y = pos.y + size.y - bottomSize.y - topSize.y; - start.x = pos.x; - end.x = pos.x + size.x; - end.y = start.y + topSize.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - else - { - - // how many whole repeating pieces will fit in that width - pieces = centerWidth / centerBar->getImageHeight(); - - // draw the pieces - start.x = pos.x; - start.y = pos.y + topSize.y ; - end.x = start.x + size.x; //centerImage->getImageHeight() + yOffset; - for( Int i = 0; i < pieces; i++ ) - { - - end.y = start.y + centerBar->getImageHeight(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - start.y += centerBar->getImageHeight(); - - } - - // we will draw the image but clip the parts we don't want to show - IRegion2D reg; - reg.lo.x = start.x; - reg.lo.y = start.y; - reg.hi.x = pos.x + size.x; - reg.hi.y = pos.y + size.y - bottomSize.y; - centerWidth = pos.y + size.y - bottomSize.y - start.y; - if( centerWidth > 0) - { - TheDisplay->setClipRegion(®); - end.y = start.y + centerBar->getImageHeight(); - TheWindowManager->winDrawImage( centerBar, - start.x, start.y, - end.x, end.y ); - TheDisplay->enableClipping(FALSE); - } - - // draw left end - end.x = pos.x + size.x; - end.y = pos.y + size.y; - start.x = pos.x; - start.y = pos.y + size.y - bottomSize.y; - TheWindowManager->winDrawImage(beginBar, start.x, start.y, end.x, end.y); - - // draw right end - start.x = pos.x; - start.y = pos.y ; - end.x = pos.x + size.x; - end.y = pos.y + topSize.y; - TheWindowManager->winDrawImage(endBar, start.x, start.y, end.x, end.y); - } - - -} diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt index 32edb03fdd2..6def3682d90 100644 --- a/GeneralsMD/Code/GameEngine/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt @@ -142,9 +142,9 @@ set(GAMEENGINE_SRC # Include/GameClient/ClientRandomValue.h # Include/GameClient/Color.h Include/GameClient/CommandXlat.h - Include/GameClient/ControlBar.h - Include/GameClient/ControlBarResizer.h - Include/GameClient/ControlBarScheme.h +# Include/GameClient/ControlBar.h +# Include/GameClient/ControlBarResizer.h +# Include/GameClient/ControlBarScheme.h # Include/GameClient/Credits.h # Include/GameClient/DebugDisplay.h Include/GameClient/Diplomacy.h @@ -696,18 +696,18 @@ set(GAMEENGINE_SRC # Source/GameClient/GraphDraw.cpp Source/GameClient/GUI/AnimateWindowManager.cpp # Source/GameClient/GUI/ChallengeGenerals.cpp - Source/GameClient/GUI/ControlBar/ControlBar.cpp - Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp - Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp - Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp - Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp - Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp - Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp - Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp - Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp - Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp - Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp - Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp +# Source/GameClient/GUI/ControlBar/ControlBar.cpp +# Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp +# Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp +# Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp +# Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp +# Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp +# Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp +# Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp +# Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp +# Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp +# Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp +# Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp Source/GameClient/GUI/DisconnectMenu/DisconnectMenu.cpp Source/GameClient/GUI/EstablishConnectionsMenu/EstablishConnectionsMenu.cpp # Source/GameClient/GUI/Gadget/GadgetCheckBox.cpp @@ -728,8 +728,8 @@ set(GAMEENGINE_SRC Source/GameClient/GUI/GameWindowManagerScript.cpp # Source/GameClient/GUI/GameWindowTransitions.cpp Source/GameClient/GUI/GameWindowTransitionsStyles.cpp - Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp - Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp +# Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp +# Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp Source/GameClient/GUI/GUICallbacks/GeneralsExpPoints.cpp diff --git a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt index 5cae369888c..46e0e9e9df8 100644 --- a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt @@ -129,7 +129,7 @@ set(GAMEENGINEDEVICE_SRC # Source/W3DDevice/GameClient/GUI/Gadget/W3DTabControl.cpp # Source/W3DDevice/GameClient/GUI/Gadget/W3DTextEntry.cpp # Source/W3DDevice/GameClient/GUI/Gadget/W3DVerticalSlider.cpp - Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp +# Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMainMenu.cpp Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DMOTD.cpp Source/W3DDevice/GameClient/GUI/W3DGameFont.cpp diff --git a/scripts/cpp/unify_move_files.py b/scripts/cpp/unify_move_files.py index 87e840d698d..ef6ba73a375 100644 --- a/scripts/cpp/unify_move_files.py +++ b/scripts/cpp/unify_move_files.py @@ -527,6 +527,25 @@ def main(): #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/Gadget/W3DTextEntry.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/Gadget/W3DTextEntry.cpp") #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/Gadget/W3DVerticalSlider.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/Gadget/W3DVerticalSlider.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ControlBar.h", Game.CORE, "GameEngine/Include/GameClient/ControlBar.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ControlBarResizer.h", Game.CORE, "GameEngine/Include/GameClient/ControlBarResizer.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ControlBarScheme.h", Game.CORE, "GameEngine/Include/GameClient/ControlBarScheme.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarMultiSelect.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarOCLTimer.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarObserver.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarPrintPositions.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarStructureInventory.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ControlBar/ControlBarUnderConstruction.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp") + #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/GUI/GUICallbacks/W3DControlBar.cpp") + return