Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ endif()
include(cmake/config.cmake)
include(cmake/gamespy.cmake)
include(cmake/lzhl.cmake)
include(cmake/stb.cmake)

if (IS_VS6_BUILD)
# The original max sdk does not compile against a modern compiler.
Expand Down
1 change: 1 addition & 0 deletions Core/GameEngine/Include/Common/OptionPreferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class OptionPreferences : public UserPreferences
Bool getAlternateMouseModeEnabled();
Bool getRetaliationModeEnabled();
Bool getDoubleClickAttackMoveEnabled();
Int getJPEGQuality();
Real getScrollFactor();
Bool getDrawScrollAnchor();
Bool getMoveScrollAnchor();
Expand Down
8 changes: 7 additions & 1 deletion Core/GameEngine/Include/GameClient/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
#include "GameClient/GameFont.h"
#include "GameClient/View.h"

enum ScreenshotFormat
{
SCREENSHOT_JPEG,
SCREENSHOT_PNG
};

struct ShroudLevel
{
Short m_currentShroud; ///< A Value of 1 means shrouded. 0 is not. Negative is the count of people looking.
Expand Down Expand Up @@ -172,7 +178,7 @@ class Display : public SubsystemInterface
virtual void preloadModelAssets( AsciiString model ) = 0; ///< preload model asset
virtual void preloadTextureAssets( AsciiString texture ) = 0; ///< preload texture asset

virtual void takeScreenShot() = 0; ///< saves screenshot to a file
virtual void takeScreenShot(ScreenshotFormat format) = 0; ///< saves screenshot in specified format
virtual void toggleMovieCapture() = 0; ///< starts saving frames to an avi or frame sequence
virtual void toggleLetterBox() = 0; ///< enabled letter-boxed display
virtual void enableLetterBox(Bool enable) = 0; ///< forces letter-boxed display on/off
Expand Down
10 changes: 10 additions & 0 deletions Core/GameEngine/Source/Common/OptionPreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,16 @@ Bool OptionPreferences::getDoubleClickAttackMoveEnabled()
return FALSE;
}

Int OptionPreferences::getJPEGQuality()
{
OptionPreferences::const_iterator it = find("JPEGQuality");
if (it == end())
return 80;

Int quality = atoi(it->second.str());
return clamp(1, quality, 100);
}

Real OptionPreferences::getScrollFactor()
{
OptionPreferences::const_iterator it = find("ScrollFactor");
Expand Down
4 changes: 4 additions & 0 deletions Core/GameEngineDevice/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ set(GAMEENGINEDEVICE_SRC
Include/W3DDevice/GameClient/W3DTreeBuffer.h
Include/W3DDevice/GameClient/W3DVideoBuffer.h
Include/W3DDevice/GameClient/W3DView.h
Include/W3DDevice/GameClient/W3DScreenshot.h
# Include/W3DDevice/GameClient/W3DVolumetricShadow.h
Include/W3DDevice/GameClient/W3DWater.h
Include/W3DDevice/GameClient/W3DWaterTracks.h
Expand Down Expand Up @@ -173,6 +174,8 @@ set(GAMEENGINEDEVICE_SRC
Source/W3DDevice/GameClient/W3DTreeBuffer.cpp
Source/W3DDevice/GameClient/W3DVideoBuffer.cpp
Source/W3DDevice/GameClient/W3DView.cpp
# Source/W3DDevice/GameClient/W3DScreenshot.cpp
Source/W3DDevice/GameClient/stb_image_write_impl.cpp
# Source/W3DDevice/GameClient/W3dWaypointBuffer.cpp
# Source/W3DDevice/GameClient/W3DWebBrowser.cpp
Source/W3DDevice/GameClient/Water/W3DWater.cpp
Expand Down Expand Up @@ -218,6 +221,7 @@ target_include_directories(corei_gameenginedevice_public INTERFACE
target_link_libraries(corei_gameenginedevice_private INTERFACE
corei_always
corei_main
stb
)

target_link_libraries(corei_gameenginedevice_public INTERFACE
Expand Down
24 changes: 24 additions & 0 deletions Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScreenshot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
** Command & Conquer Generals Zero Hour(tm)
Comment thread
bobtista marked this conversation as resolved.
Comment thread
bobtista marked this conversation as resolved.
** Copyright 2025 TheSuperHackers
**
** 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 <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "GameClient/Display.h"

void W3D_TakeCompressedScreenshot(ScreenshotFormat format, int quality = 0);

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 TheSuperHackers
**
** 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 <http://www.gnu.org/licenses/>.
*/

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

1 change: 1 addition & 0 deletions Generals/Code/GameEngine/Include/Common/GlobalData.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class GlobalData : public SubsystemInterface
Bool m_clientRetaliationModeEnabled;
Bool m_doubleClickAttackMove;
Bool m_rightMouseAlwaysScrolls;
Int m_jpegQuality;
Comment thread
bobtista marked this conversation as resolved.
Bool m_useWaterPlane;
Bool m_useCloudPlane;
Bool m_useShadowVolumes;
Expand Down
3 changes: 2 additions & 1 deletion Generals/Code/GameEngine/Include/Common/MessageStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ class GameMessage : public MemoryPoolObject
MSG_META_BEGIN_PREFER_SELECTION, ///< The Shift key has been depressed alone
MSG_META_END_PREFER_SELECTION, ///< The Shift key has been released.

MSG_META_TAKE_SCREENSHOT, ///< take screenshot
MSG_META_TAKE_SCREENSHOT, ///< take JPEG screenshot (F12)
MSG_META_TAKE_SCREENSHOT_PNG, ///< take PNG screenshot (CTRL+F12, lossless)
MSG_META_ALL_CHEER, ///< Yay! :)
MSG_META_TOGGLE_ATTACKMOVE, ///< enter attack-move mode

Expand Down
2 changes: 2 additions & 0 deletions Generals/Code/GameEngine/Source/Common/GlobalData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ GlobalData::GlobalData()
m_enableDynamicLOD = TRUE;
m_enableStaticLOD = TRUE;
m_rightMouseAlwaysScrolls = FALSE;
m_jpegQuality = 80;
m_useWaterPlane = FALSE;
m_useCloudPlane = FALSE;
m_downwindAngle = ( -0.785f );//Northeast!
Expand Down Expand Up @@ -1189,6 +1190,7 @@ void GlobalData::parseGameDataDefinition( INI* ini )
TheWritableGlobalData->m_useAlternateMouse = optionPref.getAlternateMouseModeEnabled();
TheWritableGlobalData->m_clientRetaliationModeEnabled = optionPref.getRetaliationModeEnabled();
TheWritableGlobalData->m_doubleClickAttackMove = optionPref.getDoubleClickAttackMoveEnabled();
TheWritableGlobalData->m_jpegQuality = optionPref.getJPEGQuality();
TheWritableGlobalData->m_keyboardScrollFactor = optionPref.getScrollFactor();
TheWritableGlobalData->m_drawScrollAnchor = optionPref.getDrawScrollAnchor();
TheWritableGlobalData->m_moveScrollAnchor = optionPref.getMoveScrollAnchor();
Expand Down
1 change: 1 addition & 0 deletions Generals/Code/GameEngine/Source/Common/MessageStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ const char *GameMessage::getCommandTypeAsString(GameMessage::Type t)
CASE_LABEL(MSG_META_BEGIN_PREFER_SELECTION)
CASE_LABEL(MSG_META_END_PREFER_SELECTION)
CASE_LABEL(MSG_META_TAKE_SCREENSHOT)
CASE_LABEL(MSG_META_TAKE_SCREENSHOT_PNG)
CASE_LABEL(MSG_META_ALL_CHEER)
CASE_LABEL(MSG_META_TOGGLE_ATTACKMOVE)
CASE_LABEL(MSG_META_BEGIN_CAMERA_ROTATE_LEFT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3420,7 +3420,15 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
case GameMessage::MSG_META_TAKE_SCREENSHOT:
{
if (TheDisplay)
TheDisplay->takeScreenShot();
TheDisplay->takeScreenShot(SCREENSHOT_JPEG);
disp = DESTROY_MESSAGE;
break;
}
Comment thread
bobtista marked this conversation as resolved.

case GameMessage::MSG_META_TAKE_SCREENSHOT_PNG:
{
if (TheDisplay)
TheDisplay->takeScreenShot(SCREENSHOT_PNG);
disp = DESTROY_MESSAGE;
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static const LookupListRec GameMessageMetaTypeNames[] =
{ "END_PREFER_SELECTION", GameMessage::MSG_META_END_PREFER_SELECTION },

{ "TAKE_SCREENSHOT", GameMessage::MSG_META_TAKE_SCREENSHOT },
{ "TAKE_SCREENSHOT_PNG", GameMessage::MSG_META_TAKE_SCREENSHOT_PNG },
{ "ALL_CHEER", GameMessage::MSG_META_ALL_CHEER },

{ "BEGIN_CAMERA_ROTATE_LEFT", GameMessage::MSG_META_BEGIN_CAMERA_ROTATE_LEFT },
Expand Down Expand Up @@ -812,6 +813,26 @@ void MetaMap::generateMetaMap()
map->m_usableIn = COMMANDUSABLE_GAME;
}
}
{
MetaMapRec *map = TheMetaMap->getMetaMapRec(GameMessage::MSG_META_TAKE_SCREENSHOT);
if (map->m_key == MK_NONE)
{
map->m_key = MK_F12;
map->m_transition = DOWN;
map->m_modState = NONE;
map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
}
}
Comment thread
bobtista marked this conversation as resolved.
{
MetaMapRec *map = TheMetaMap->getMetaMapRec(GameMessage::MSG_META_TAKE_SCREENSHOT_PNG);
if (map->m_key == MK_NONE)
{
map->m_key = MK_F12;
map->m_transition = DOWN;
map->m_modState = CTRL;
map->m_usableIn = COMMANDUSABLE_EVERYWHERE;
}
}

#if defined(RTS_DEBUG)
{
Expand Down
2 changes: 2 additions & 0 deletions Generals/Code/GameEngineDevice/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ set(GAMEENGINEDEVICE_SRC
Source/W3DDevice/GameClient/W3DDebugDisplay.cpp
Source/W3DDevice/GameClient/W3DDebugIcons.cpp
Source/W3DDevice/GameClient/W3DDisplay.cpp
Source/W3DDevice/GameClient/W3DScreenshot.cpp
Source/W3DDevice/GameClient/W3DDisplayString.cpp
Source/W3DDevice/GameClient/W3DDisplayStringManager.cpp
Source/W3DDevice/GameClient/W3DDynamicLight.cpp
Expand Down Expand Up @@ -200,6 +201,7 @@ target_link_libraries(g_gameenginedevice PRIVATE
corei_gameenginedevice_private
gi_always
gi_main
stb
)

target_link_libraries(g_gameenginedevice PUBLIC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class W3DDisplay : public Display

virtual VideoBuffer* createVideoBuffer() override; ///< Create a video buffer that can be used for this display

virtual void takeScreenShot() override; //save screenshot to file
virtual void takeScreenShot(ScreenshotFormat format) override; //save screenshot in specified format
virtual void toggleMovieCapture() override; //enable AVI or frame capture mode.

virtual void toggleLetterBox() override; ///<enabled letter-boxed display
Expand Down
Loading
Loading