From bfe72a2d567cbf35445634a19b7abdb1e5112706 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 17 Dec 2023 21:23:21 +0300 Subject: [PATCH 01/12] Don't interact with the transform layer if the image is a single layer. --- src/engine/image.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/engine/image.cpp b/src/engine/image.cpp index 0263c094350..d93813806b7 100644 --- a/src/engine/image.cpp +++ b/src/engine/image.cpp @@ -503,7 +503,10 @@ namespace fheroes2 if ( !empty() ) { const size_t totalSize = static_cast( _width ) * _height; memset( image(), value, totalSize ); - memset( transform(), static_cast( 0 ), totalSize ); + + if ( !_singleLayer ) { + memset( transform(), static_cast( 0 ), totalSize ); + } } } @@ -532,8 +535,11 @@ namespace fheroes2 if ( !empty() ) { const size_t totalSize = static_cast( _width ) * _height; memset( image(), static_cast( 0 ), totalSize ); - // Set the transform layer to skip all data. - memset( transform(), static_cast( 1 ), totalSize ); + + if ( !_singleLayer ) { + // Set the transform layer to skip all data. + memset( transform(), static_cast( 1 ), totalSize ); + } } } @@ -556,7 +562,7 @@ namespace fheroes2 _singleLayer = image._singleLayer; - memcpy( _data.get(), image._data.get(), size * 2 ); + memcpy( _data.get(), image._data.get(), _singleLayer ? size : size * 2 ); } Sprite::Sprite( const int32_t width_, const int32_t height_, const int32_t x_ /* = 0 */, const int32_t y_ /* = 0 */ ) From dc56af581d55420be6cd01a4125aee3c2e6f1bd5 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 24 Dec 2023 11:33:19 +0300 Subject: [PATCH 02/12] Add assertion to get transform layer only for double-layer images, fix setResolution() --- src/engine/image.cpp | 1 - src/engine/image.h | 7 +++++++ src/engine/screen.cpp | 5 ++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/engine/image.cpp b/src/engine/image.cpp index d93813806b7..0469310f43b 100644 --- a/src/engine/image.cpp +++ b/src/engine/image.cpp @@ -21,7 +21,6 @@ #include "image.h" #include -#include #include #include #include diff --git a/src/engine/image.h b/src/engine/image.h index 9a746cc2210..177872fcb3f 100644 --- a/src/engine/image.h +++ b/src/engine/image.h @@ -19,6 +19,7 @@ ***************************************************************************/ #pragma once +#include #include #include #include @@ -63,11 +64,17 @@ namespace fheroes2 uint8_t * transform() { + // Why do you want to get transform layer from the single-layer image? + assert( !_singleLayer ); + return _data.get() + width() * height(); } const uint8_t * transform() const { + // Why do you want to get transform layer from the single-layer image? + assert( !_singleLayer ); + return _data.get() + width() * height(); } diff --git a/src/engine/screen.cpp b/src/engine/screen.cpp index 240b022e758..7bb09fcd4cf 100644 --- a/src/engine/screen.cpp +++ b/src/engine/screen.cpp @@ -1349,10 +1349,9 @@ namespace fheroes2 } Image::resize( info.gameWidth, info.gameHeight ); - _screenSize = { info.screenWidth, info.screenHeight }; + Image::reset(); - // To detect some UI artifacts by invalid code let's put all transform data into pixel skipping mode. - std::fill( transform(), transform() + width() * height(), static_cast( 1 ) ); + _screenSize = { info.screenWidth, info.screenHeight }; } Display & Display::instance() From c7d6c6ecdb0142988e32e398e6a69742cdfbda68 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 24 Dec 2023 16:26:33 +0300 Subject: [PATCH 03/12] Fix fheroes2::Resize() for the case it in and out images have different number of layers --- src/engine/image.cpp | 110 ++++++++++++++++++++++------- src/fheroes2/game/game_credits.cpp | 1 + 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/engine/image.cpp b/src/engine/image.cpp index 0469310f43b..7c496bcfd0e 100644 --- a/src/engine/image.cpp +++ b/src/engine/image.cpp @@ -2688,7 +2688,18 @@ namespace fheroes2 const uint8_t * gamePalette = getGamePalette(); - if ( in.singleLayer() && out.singleLayer() ) { + if ( in.singleLayer() ) { + if ( !out.singleLayer() ) { + // In this case we make the output image fully non-transparent in the given output area. + + uint8_t * transformY = out.transform() + outY * widthOut + outX; + const uint8_t * transformYEnd = transformY + heightRoiOut * widthOut; + + for ( ; transformY != transformYEnd; transformY += widthOut ) { + memset( transformY, static_cast( 0 ), widthRoiOut ); + } + } + for ( int32_t y = 0; y < heightRoiOut; ++y, imageOutY += widthOut ) { const double posY = static_cast( y * heightRoiIn ) / heightRoiOut; const int32_t startY = static_cast( posY ); @@ -2729,9 +2740,10 @@ namespace fheroes2 } else { const uint8_t * transformInY = in.transform() + offsetInY; - uint8_t * transformOutY = out.transform() + offsetOutY; + const bool isOutNotSingleLayer = !out.singleLayer(); + uint8_t * transformOutY = isOutNotSingleLayer ? ( out.transform() + offsetOutY ) : nullptr; - for ( int32_t y = 0; y < heightRoiOut; ++y, imageOutY += widthOut, transformOutY += widthOut ) { + for ( int32_t y = 0; y < heightRoiOut; ++y, imageOutY += widthOut ) { const double posY = static_cast( y * heightRoiIn ) / heightRoiOut; const int32_t startY = static_cast( posY ); const double coeffY = posY - startY; @@ -2739,7 +2751,7 @@ namespace fheroes2 uint8_t * imageOutX = imageOutY; uint8_t * transformOutX = transformOutY; - for ( int32_t x = 0; x < widthRoiOut; ++x, ++imageOutX, ++transformOutX ) { + for ( int32_t x = 0; x < widthRoiOut; ++x, ++imageOutX ) { const double posX = positionX[x]; const int32_t startX = static_cast( posX ); const int32_t offsetIn = startY * widthIn + startX; @@ -2747,34 +2759,44 @@ namespace fheroes2 const uint8_t * imageInX = imageInY + offsetIn; const uint8_t * transformInX = transformInY + offsetIn; - if ( posX < widthIn - 1 && posY < heightRoiIn - 1 ) { - if ( *transformInX == 0 && *( transformInX + 1 ) == 0 && *( transformInX + widthRoiIn ) == 0 && *( transformInX + widthRoiIn + 1 ) == 0 ) { - const double coeffX = posX - startX; - const double coeff1 = ( 1 - coeffX ) * ( 1 - coeffY ); - const double coeff2 = coeffX * ( 1 - coeffY ); - const double coeff3 = ( 1 - coeffX ) * coeffY; - const double coeff4 = coeffX * coeffY; + if ( posX < widthIn - 1 && posY < heightRoiIn - 1 && *transformInX == 0 && *( transformInX + 1 ) == 0 && *( transformInX + widthRoiIn ) == 0 + && *( transformInX + widthRoiIn + 1 ) == 0 ) { + const double coeffX = posX - startX; + const double coeff1 = ( 1 - coeffX ) * ( 1 - coeffY ); + const double coeff2 = coeffX * ( 1 - coeffY ); + const double coeff3 = ( 1 - coeffX ) * coeffY; + const double coeff4 = coeffX * coeffY; - const uint8_t * id1 = gamePalette + static_cast( *imageInX ) * 3; - const uint8_t * id2 = gamePalette + static_cast( *( imageInX + 1 ) ) * 3; - const uint8_t * id3 = gamePalette + static_cast( *( imageInX + widthIn ) ) * 3; - const uint8_t * id4 = gamePalette + static_cast( *( imageInX + widthIn + 1 ) ) * 3; + const uint8_t * id1 = gamePalette + static_cast( *imageInX ) * 3; + const uint8_t * id2 = gamePalette + static_cast( *( imageInX + 1 ) ) * 3; + const uint8_t * id3 = gamePalette + static_cast( *( imageInX + widthIn ) ) * 3; + const uint8_t * id4 = gamePalette + static_cast( *( imageInX + widthIn + 1 ) ) * 3; - const double red = *id1 * coeff1 + *id2 * coeff2 + *id3 * coeff3 + *id4 * coeff4 + 0.5; - const double green = *( id1 + 1 ) * coeff1 + *( id2 + 1 ) * coeff2 + *( id3 + 1 ) * coeff3 + *( id4 + 1 ) * coeff4 + 0.5; - const double blue = *( id1 + 2 ) * coeff1 + *( id2 + 2 ) * coeff2 + *( id3 + 2 ) * coeff3 + *( id4 + 2 ) * coeff4 + 0.5; + const double red = *id1 * coeff1 + *id2 * coeff2 + *id3 * coeff3 + *id4 * coeff4 + 0.5; + const double green = *( id1 + 1 ) * coeff1 + *( id2 + 1 ) * coeff2 + *( id3 + 1 ) * coeff3 + *( id4 + 1 ) * coeff4 + 0.5; + const double blue = *( id1 + 2 ) * coeff1 + *( id2 + 2 ) * coeff2 + *( id3 + 2 ) * coeff3 + *( id4 + 2 ) * coeff4 + 0.5; - *imageOutX = GetPALColorId( static_cast( red ), static_cast( green ), static_cast( blue ) ); - } - else { + *imageOutX = GetPALColorId( static_cast( red ), static_cast( green ), static_cast( blue ) ); + } + else { + if ( isOutNotSingleLayer || *transformInX == 0 ) { + // Output image is double-layer or single-layer with non-transparent current pixel. *imageOutX = *imageInX; } + else if ( *transformInX != 1 ) { + // Apply a transformation. + *imageOutX = *( transformTable + ( *transformInX ) * 256 + *imageOutX ); + } } - else { - *imageOutX = *imageInX; + + if ( isOutNotSingleLayer ) { + *transformOutX = *transformInX; + ++transformOutX; } + } - *transformOutX = *transformInX; + if ( !isOutNotSingleLayer ) { + transformOutY += widthOut; } } } @@ -2789,7 +2811,18 @@ namespace fheroes2 positionX[x] = ( x * widthRoiIn ) / widthRoiOut; } - if ( in.singleLayer() && out.singleLayer() ) { + if ( in.singleLayer() ) { + if ( !out.singleLayer() ) { + // In this case we make the output image fully non-transparent in the given output area. + + uint8_t * transformY = out.transform() + outY * widthOut + outX; + const uint8_t * transformYEnd = transformY + heightRoiOut * widthOut; + + for ( ; transformY != transformYEnd; transformY += widthOut ) { + memset( transformY, static_cast( 0 ), widthRoiOut ); + } + } + for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, ++idY ) { uint8_t * imageOutX = imageOutY; @@ -2802,7 +2835,34 @@ namespace fheroes2 } } } + else if ( out.singleLayer() ) { + const uint8_t * transformInY = in.transform() + offsetInY; + + for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, ++idY ) { + uint8_t * imageOutX = imageOutY; + + const int32_t offset = ( ( idY * heightRoiIn ) / heightRoiOut ) * widthIn; + const uint8_t * imageInX = imageInY + offset; + const uint8_t * transformInX = transformInY + offset; + + for ( const int32_t posX : positionX ) { + const uint8_t * transformIn = transformInX + posX; + if ( *transformIn > 0 ) { + if ( *transformIn != 1 ) { + // Apply a transformation. + *imageOutX = *( transformTable + ( *transformIn ) * 256 + *imageOutX ); + } + } + else { + *imageOutX = *( imageInX + posX ); + } + + ++imageOutX; + } + } + } else { + // Both 'in' and 'out' are double-layer. const uint8_t * transformInY = in.transform() + offsetInY; uint8_t * transformOutY = out.transform() + offsetOutY; diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index 8f4fb387b2b..715294e8cfe 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -258,6 +258,7 @@ namespace fheroes2::Blit( goblin, output, output.width() - goblin.width() * 2, output.height() - goblin.height() - 10, true ); fheroes2::Image resizedOutput( 640, 480 ); + resizedOutput._disableTransformLayer(); fheroes2::Resize( output, 0, 0, output.width(), output.height(), resizedOutput, 0, 0, resizedOutput.width(), resizedOutput.height() ); return output; From ca8874d5092df7b2c865a34e35a3c5f5353a42e6 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 24 Dec 2023 17:45:48 +0300 Subject: [PATCH 04/12] Add assertions to more places where transform layer is accessed --- src/engine/h2d_file.cpp | 7 +++++-- src/engine/image_tool.cpp | 6 ++++++ src/engine/screen.cpp | 8 +++++++- src/fheroes2/gui/ui_font.cpp | 3 ++- src/fheroes2/gui/ui_tool.cpp | 2 +- src/fheroes2/maps/maps_tiles.cpp | 4 ++-- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/engine/h2d_file.cpp b/src/engine/h2d_file.cpp index 14cdd4c117d..e1c415df2c1 100644 --- a/src/engine/h2d_file.cpp +++ b/src/engine/h2d_file.cpp @@ -173,6 +173,9 @@ namespace fheroes2 bool readImageFromH2D( H2DReader & reader, const std::string & name, Sprite & image ) { + // TODO: Store in h2d images the 'isSingleLayer' state to disable and skip transform layer for such images. + assert( !image.singleLayer() ); + const std::vector & data = reader.getFile( name ); if ( data.size() < 4 + 4 + 4 + 4 + 1 ) { // Empty or invalid image. @@ -191,7 +194,6 @@ namespace fheroes2 const size_t size = static_cast( width * height ); image.resize( width, height ); memcpy( image.image(), data.data() + 4 + 4 + 4 + 4, size ); - // TODO: Store in h2d images the 'isSingleLayer' state to disable and skip transform layer for such images. memcpy( image.transform(), data.data() + 4 + 4 + 4 + 4 + size, size ); image.setPosition( x, y ); @@ -201,7 +203,8 @@ namespace fheroes2 bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image ) { - assert( !image.empty() ); + // TODO: Store in h2d images the 'isSingleLayer' state to disable and skip transform layer for such images. + assert( !image.empty() && !image.singleLayer() ); StreamBuf stream; stream.putLE32( static_cast( image.width() ) ); diff --git a/src/engine/image_tool.cpp b/src/engine/image_tool.cpp index 9349a5b15a2..e04a9eac5cb 100644 --- a/src/engine/image_tool.cpp +++ b/src/engine/image_tool.cpp @@ -155,6 +155,12 @@ namespace fheroes2 bool Load( const std::string & path, Image & image ) { + if ( image.singleLayer() ) { + // Output image should be double-layer! + assert( 0 ); + return false; + } + std::unique_ptr> surface( nullptr, SDL_FreeSurface ); std::unique_ptr> loadedSurface( nullptr, SDL_FreeSurface ); diff --git a/src/engine/screen.cpp b/src/engine/screen.cpp index 7bb09fcd4cf..ab62fa20708 100644 --- a/src/engine/screen.cpp +++ b/src/engine/screen.cpp @@ -363,6 +363,12 @@ namespace SDL_Surface * generateIconSurface( const fheroes2::Image & icon ) { + if ( icon.empty() || icon.singleLayer() ) { + // What are you trying to do? Icon should have not empty both image and transform layers. + assert( 0 ); + return nullptr; + } + SDL_Surface * surface = SDL_CreateRGBSurface( 0, icon.width(), icon.height(), 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 ); if ( surface == nullptr ) { ERROR_LOG( "Failed to create a surface of " << icon.width() << " x " << icon.height() << " size for cursor. The error: " << SDL_GetError() ) @@ -436,7 +442,7 @@ namespace void update( const fheroes2::Image & image, int32_t offsetX, int32_t offsetY ) override { - if ( image.empty() ) { + if ( image.empty() || image.singleLayer() ) { // What are you trying to do? Set an invisible cursor? Use hide() method! assert( 0 ); return; diff --git a/src/fheroes2/gui/ui_font.cpp b/src/fheroes2/gui/ui_font.cpp index ec07d28c9da..6afea99e502 100644 --- a/src/fheroes2/gui/ui_font.cpp +++ b/src/fheroes2/gui/ui_font.cpp @@ -53,7 +53,8 @@ namespace fheroes2::Sprite addContour( fheroes2::Sprite & input, const fheroes2::Point & contourOffset, const uint8_t colorId ) { - if ( input.empty() || contourOffset.x > 0 || contourOffset.y < 0 || ( -contourOffset.x >= input.width() ) || ( contourOffset.y >= input.height() ) ) { + if ( input.empty() || input.singleLayer() || contourOffset.x > 0 || contourOffset.y < 0 || ( -contourOffset.x >= input.width() ) + || ( contourOffset.y >= input.height() ) ) { return input; } diff --git a/src/fheroes2/gui/ui_tool.cpp b/src/fheroes2/gui/ui_tool.cpp index feff84667f8..10f9c34a77c 100644 --- a/src/fheroes2/gui/ui_tool.cpp +++ b/src/fheroes2/gui/ui_tool.cpp @@ -538,7 +538,7 @@ namespace fheroes2 Image CreateRippleEffect( const Image & in, const int32_t frameId, const double scaleX /* = 0.05 */, const double waveFrequency /* = 20.0 */ ) { - if ( in.empty() ) { + if ( in.empty() || in.singleLayer() ) { return {}; } diff --git a/src/fheroes2/maps/maps_tiles.cpp b/src/fheroes2/maps/maps_tiles.cpp index 8d4ef6c0c1c..0b73ff20a68 100644 --- a/src/fheroes2/maps/maps_tiles.cpp +++ b/src/fheroes2/maps/maps_tiles.cpp @@ -165,8 +165,8 @@ namespace // Define VERIFY_SHADOW_SPRITES macro to be able to use these functions. bool isShadowImage( const fheroes2::Image & image ) { - // The image can't be empty. - assert( !image.empty() ); + // The image can't be empty and must have transform layer. + assert( !image.empty() && !image.singleLayer() ); if ( image.empty() ) return false; From 309266e147c567c9904fc724b9cd8f823f2a4a19 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 24 Dec 2023 20:47:28 +0300 Subject: [PATCH 05/12] Do not allocate memory for transform() layer when image is single-layer --- src/engine/image.cpp | 17 +++++---- src/engine/image.h | 15 ++++---- src/engine/localevent.cpp | 10 +++--- src/engine/zzlib.cpp | 21 ++++++----- src/fheroes2/battle/battle_interface.cpp | 36 ++++++++++--------- src/fheroes2/castle/castle_town.cpp | 6 ++-- src/fheroes2/castle/castle_well.cpp | 3 +- .../editor/editor_interface_panel.cpp | 3 +- src/fheroes2/game/game_credits.cpp | 13 ++++--- src/fheroes2/gui/interface_gamearea.cpp | 4 +-- src/fheroes2/gui/interface_radar.cpp | 6 ++-- src/fheroes2/gui/interface_radar.h | 3 +- src/fheroes2/gui/ui_tool.cpp | 3 +- src/fheroes2/kingdom/view_world.cpp | 5 +-- 14 files changed, 81 insertions(+), 64 deletions(-) diff --git a/src/engine/image.cpp b/src/engine/image.cpp index 299eff48f0a..2a289c14830 100644 --- a/src/engine/image.cpp +++ b/src/engine/image.cpp @@ -504,6 +504,7 @@ namespace fheroes2 memset( image(), value, totalSize ); if ( !_singleLayer ) { + // For double-layer image: set the transform layer not to skip all data. memset( transform(), static_cast( 0 ), totalSize ); } } @@ -521,9 +522,10 @@ namespace fheroes2 return; } - const size_t size = static_cast( width_ ) * height_; + // Allocate memory only for the used layers. + const size_t size = static_cast( width_ ) * height_ * ( _singleLayer ? 1 : 2 ); - _data.reset( new uint8_t[size * 2] ); + _data.reset( new uint8_t[size] ); _width = width_; _height = height_; @@ -550,18 +552,19 @@ namespace fheroes2 return; } - const size_t size = static_cast( image._width ) * image._height; + // Allocate memory and copy data only for the used layers. + const size_t size = static_cast( image._width ) * image._height * ( _singleLayer ? 1 : 2 ); + + _singleLayer = image._singleLayer; if ( image._width != _width || image._height != _height ) { - _data.reset( new uint8_t[size * 2] ); + _data.reset( new uint8_t[size] ); _width = image._width; _height = image._height; } - _singleLayer = image._singleLayer; - - memcpy( _data.get(), image._data.get(), _singleLayer ? size : size * 2 ); + memcpy( _data.get(), image._data.get(), size ); } Sprite::Sprite( const int32_t width_, const int32_t height_, const int32_t x_ /* = 0 */, const int32_t y_ /* = 0 */ ) diff --git a/src/engine/image.h b/src/engine/image.h index 3325b7c932e..2184f3a4d26 100644 --- a/src/engine/image.h +++ b/src/engine/image.h @@ -29,7 +29,7 @@ namespace fheroes2 { - // Image contains image layer and transform layer. + // Image always contains an image layer and if image is not a single-layer then also a transform layer. // - image layer contains visible pixels which are copy to a destination image // - transform layer is used to apply some transformation to an image on which we draw the current one. For example, shadowing class Image @@ -83,14 +83,17 @@ namespace fheroes2 return !_data; } - void reset(); // makes image fully transparent (transform layer is set to 1) - void clear(); // makes the image empty + // Set all data in the image layer to 0 and make double-layer images fully transparent (transform layer is set to 1). + void reset(); - // Fill 'image' layer with given value, setting 'transform' layer to 0. + // Make the image empty. + void clear(); + + // Fill 'image' layer with given value, setting the double-layer images 'transform' layer to 0. void fill( const uint8_t value ); - // This is an optional indicator for image processing functions. - // The whole image still consists of 2 layers but transform layer might be ignored in computations. + // This is an indicator for image processing functions. + // The single-layer image can not contain transform layer so this layer is never accessed for such images. bool singleLayer() const { return _singleLayer; diff --git a/src/engine/localevent.cpp b/src/engine/localevent.cpp index 17c3d5ca43e..08f37888ec1 100644 --- a/src/engine/localevent.cpp +++ b/src/engine/localevent.cpp @@ -1231,14 +1231,14 @@ void LocalEvent::HandleRenderDeviceResetEvent() { // All textures has to be recreated. The only way to do it is to reset everything and render it back. fheroes2::Display & display = fheroes2::Display::instance(); - fheroes2::Image temp( display.width(), display.height() ); - if ( display.singleLayer() ) { - temp._disableTransformLayer(); - } + fheroes2::Image temp; + + assert( display.singleLayer() ); + + temp._disableTransformLayer(); fheroes2::Copy( display, temp ); display.release(); - display.resize( temp.width(), temp.height() ); fheroes2::Copy( temp, display ); } diff --git a/src/engine/zzlib.cpp b/src/engine/zzlib.cpp index d30fc7fcaee..d769f0b8ea3 100644 --- a/src/engine/zzlib.cpp +++ b/src/engine/zzlib.cpp @@ -195,27 +195,30 @@ bool ZStreamBuf::write( const std::string & fn, const bool append /* = false */ fheroes2::Image CreateImageFromZlib( int32_t width, int32_t height, const uint8_t * imageData, size_t imageSize, bool doubleLayer ) { - if ( imageData == nullptr || imageSize == 0 || width <= 0 || height <= 0 ) - return fheroes2::Image(); + if ( imageData == nullptr || imageSize == 0 || width <= 0 || height <= 0 ) { + return {}; + } const std::vector & uncompressedData = zlibDecompress( imageData, imageSize ); if ( doubleLayer && ( uncompressedData.size() & 1 ) == 1 ) { - return fheroes2::Image(); + return {}; } const size_t uncompressedSize = doubleLayer ? uncompressedData.size() / 2 : uncompressedData.size(); - if ( static_cast( width * height ) != uncompressedSize ) - return fheroes2::Image(); + if ( static_cast( width * height ) != uncompressedSize ) { + return {}; + } - fheroes2::Image out( width, height ); + fheroes2::Image out; + if ( !doubleLayer ) { + out._disableTransformLayer(); + } + out.resize( width, height ); std::memcpy( out.image(), uncompressedData.data(), uncompressedSize ); if ( doubleLayer ) { std::memcpy( out.transform(), uncompressedData.data() + uncompressedSize, uncompressedSize ); } - else { - std::fill( out.transform(), out.transform() + uncompressedSize, static_cast( 0 ) ); - } return out; } diff --git a/src/fheroes2/battle/battle_interface.cpp b/src/fheroes2/battle/battle_interface.cpp index 4f644cfca20..6688d24275d 100644 --- a/src/fheroes2/battle/battle_interface.cpp +++ b/src/fheroes2/battle/battle_interface.cpp @@ -1243,9 +1243,6 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex ) // Shadow that fits the hexagon grid. _hexagonGridShadow = DrawHexagonShadow( 4, 1 ); - // As '_mainSurface' is used to prepare battlefield screen to render on display it does not need to have a transform layer. - _mainSurface._disableTransformLayer(); - btn_auto.setICNInfo( ICN::TEXTBAR, 4, 5 ); btn_settings.setICNInfo( ICN::TEXTBAR, 6, 7 ); @@ -1278,14 +1275,14 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex ) } status.SetLogs( listlog.get() ); - // Battlefield area excludes the lower part where the status log is located. - _mainSurface.resize( area.width, battlefieldHeight ); - _battleGround.resize( area.width, battlefieldHeight ); - // As `_battleGround` and '_mainSurface' are used to prepare battlefield screen to render on display they do not need to have a transform layer. _battleGround._disableTransformLayer(); _mainSurface._disableTransformLayer(); + // Battlefield area excludes the lower part where the status log is located. + _mainSurface.resize( area.width, battlefieldHeight ); + _battleGround.resize( area.width, battlefieldHeight ); + AudioManager::ResetAudio(); } @@ -3058,8 +3055,9 @@ void Battle::Interface::FadeArena( const bool clearMessageLog ) Redraw(); const fheroes2::Rect srt = border.GetArea(); - fheroes2::Image top( srt.width, srt.height ); + fheroes2::Image top; top._disableTransformLayer(); + top.resize( srt.width, srt.height ); fheroes2::Copy( display, srt.x, srt.y, top, 0, 0, srt.width, srt.height ); fheroes2::FadeDisplayWithPalette( top, srt.getPosition(), 5, 300, 5 ); @@ -5493,8 +5491,9 @@ void Battle::Interface::RedrawActionDeathWaveSpell( const int32_t strength ) area.height -= listlog->GetArea().height; } - fheroes2::Image battleFieldCopy( area.width, area.height ); + fheroes2::Image battleFieldCopy; battleFieldCopy._disableTransformLayer(); + battleFieldCopy.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, 0, 0, battleFieldCopy, 0, 0, area.width, area.height ); // The death wave horizontal length in pixels. @@ -5518,9 +5517,10 @@ void Battle::Interface::RedrawActionDeathWaveSpell( const int32_t strength ) int32_t position = waveStep; fheroes2::Display & display = fheroes2::Display::instance(); - // Prepare the blank image for the Death Wave spell effect with the transform layer equal to "0" - fheroes2::Image spellEffect( waveLength, area.height ); + // Prepare the blank image for the Death Wave spell effect. + fheroes2::Image spellEffect; spellEffect._disableTransformLayer(); + spellEffect.resize( waveLength, area.height ); AudioManager::PlaySound( M82::MNRDEATH ); @@ -5623,8 +5623,9 @@ void Battle::Interface::RedrawActionHolyShoutSpell( const uint8_t strength ) area.height -= listlog->GetArea().height; } - fheroes2::Image battleFieldCopy( area.width, area.height ); + fheroes2::Image battleFieldCopy; battleFieldCopy._disableTransformLayer(); + battleFieldCopy.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, 0, 0, battleFieldCopy, 0, 0, area.width, area.height ); _currentUnit = nullptr; @@ -5759,12 +5760,12 @@ void Battle::Interface::RedrawActionArmageddonSpell() area.height -= 37; - fheroes2::Image spriteWhitening( area.width, area.height ); - fheroes2::Image spriteReddish( area.width, area.height ); + fheroes2::Image spriteWhitening; spriteWhitening._disableTransformLayer(); - spriteReddish._disableTransformLayer(); + spriteWhitening.resize( area.width, area.height ); + fheroes2::Copy( _mainSurface, area.x, area.y, spriteWhitening, 0, 0, area.width, area.height ); - fheroes2::Copy( _mainSurface, area.x, area.y, spriteReddish, 0, 0, area.width, area.height ); + fheroes2::Image spriteReddish = spriteWhitening; cursor.SetThemes( Cursor::WAR_POINTER ); @@ -5831,8 +5832,9 @@ void Battle::Interface::RedrawActionEarthQuakeSpell( const std::vectorPortraitRedraw( dst_pt.x, dst_pt.y, PORT_BIG, display ); } else { - fheroes2::Image noHeroPortrait( rectHero1.width, rectHero1.height ); + fheroes2::Image noHeroPortrait; noHeroPortrait._disableTransformLayer(); + noHeroPortrait.resize( rectHero1.width, rectHero1.height ); noHeroPortrait.fill( 0 ); fheroes2::Copy( noHeroPortrait, 0, 0, display, rectHero1.x, rectHero1.y, rectHero1.width, rectHero1.height ); } @@ -448,8 +449,9 @@ Castle::ConstructionDialogResult Castle::openConstructionDialog( uint32_t & dwel hero2->PortraitRedraw( dst_pt.x, dst_pt.y, PORT_BIG, display ); } else { - fheroes2::Image noHeroPortrait( rectHero2.width, rectHero2.height ); + fheroes2::Image noHeroPortrait; noHeroPortrait._disableTransformLayer(); + noHeroPortrait.resize( rectHero2.width, rectHero2.height ); noHeroPortrait.fill( 0 ); fheroes2::Copy( noHeroPortrait, 0, 0, display, rectHero2.x, rectHero2.y, rectHero2.width, rectHero2.height ); } diff --git a/src/fheroes2/castle/castle_well.cpp b/src/fheroes2/castle/castle_well.cpp index 2ce7a90dde6..49d455383cd 100644 --- a/src/fheroes2/castle/castle_well.cpp +++ b/src/fheroes2/castle/castle_well.cpp @@ -237,8 +237,9 @@ void Castle::OpenWell() fheroes2::RandomMonsterAnimation( castleMonster[2] ), fheroes2::RandomMonsterAnimation( castleMonster[3] ), fheroes2::RandomMonsterAnimation( castleMonster[4] ), fheroes2::RandomMonsterAnimation( castleMonster[5] ) }; - fheroes2::Image background( roi.width, roi.height ); + fheroes2::Image background; background._disableTransformLayer(); + background.resize( roi.width, roi.height ); _wellRedrawBackground( background ); LocalEvent & le = LocalEvent::Get(); diff --git a/src/fheroes2/editor/editor_interface_panel.cpp b/src/fheroes2/editor/editor_interface_panel.cpp index e1d72a8f2ce..2c03ebaf475 100644 --- a/src/fheroes2/editor/editor_interface_panel.cpp +++ b/src/fheroes2/editor/editor_interface_panel.cpp @@ -117,8 +117,9 @@ namespace fheroes2::Image makeInstrumentPanelBackground( const int32_t width, const int32_t height ) { - fheroes2::Image background( width, height ); + fheroes2::Image background; background._disableTransformLayer(); + background.resize( width, height ); fheroes2::StandardWindow::renderBackgroundImage( background, { 0, 0, width, height }, 0, Settings::Get().isEvilInterfaceEnabled() ); // Make background borders: it consists of rectangles with different transform shading. diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index 715294e8cfe..365d416b3dc 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -153,8 +153,9 @@ namespace const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); assert( background.height() < fheroes2::Display::DEFAULT_HEIGHT ); - fheroes2::Sprite output( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT - background.height() ); + fheroes2::Sprite output; output._disableTransformLayer(); + output.resize( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT - background.height() ); output.fill( 0 ); const fheroes2::Text caption( "fheroes2 engine (" + Settings::GetVersion() + ")", fheroes2::FontType::normalYellow() ); @@ -257,10 +258,6 @@ namespace const fheroes2::Sprite & goblin = fheroes2::AGG::GetICN( ICN::GOBLIN, 27 ); fheroes2::Blit( goblin, output, output.width() - goblin.width() * 2, output.height() - goblin.height() - 10, true ); - fheroes2::Image resizedOutput( 640, 480 ); - resizedOutput._disableTransformLayer(); - fheroes2::Resize( output, 0, 0, output.width(), output.height(), resizedOutput, 0, 0, resizedOutput.width(), resizedOutput.height() ); - return output; } @@ -729,14 +726,16 @@ void Game::ShowCredits( const bool keepMainMenuBorders ) // Resize the credits pages. 'creditsRoi' is made using Main Menu background parameters that were already properly calculated for the current resolution. const int32_t resizedPageHeight = creditsRoi.width * pages.front().height() / pages.front().width(); for ( fheroes2::Sprite & page : pages ) { - fheroes2::Sprite resizedPage( creditsRoi.width, resizedPageHeight ); + fheroes2::Sprite resizedPage; resizedPage._disableTransformLayer(); + resizedPage.resize( creditsRoi.width, resizedPageHeight ); fheroes2::Resize( page, resizedPage, false ); page = std::move( resizedPage ); } - fheroes2::Sprite header( creditsRoi.width, creditsRoi.height - resizedPageHeight ); + fheroes2::Sprite header; header._disableTransformLayer(); + header.resize( creditsRoi.width, creditsRoi.height - resizedPageHeight ); fheroes2::Resize( generateHeader(), header, false ); AnimationSequence sequence( static_cast( pages.size() ) ); diff --git a/src/fheroes2/gui/interface_gamearea.cpp b/src/fheroes2/gui/interface_gamearea.cpp index 968b2c11f8b..d8d97842c7c 100644 --- a/src/fheroes2/gui/interface_gamearea.cpp +++ b/src/fheroes2/gui/interface_gamearea.cpp @@ -855,8 +855,9 @@ fheroes2::Image Interface::GameArea::GenerateUltimateArtifactAreaSurface( const return fheroes2::Image(); } - fheroes2::Image result( 448, 448 ); + fheroes2::Image result; result._disableTransformLayer(); + result.resize( 448, 448 ); // Make a temporary copy GameArea gamearea = AdventureMap::Get().getGameArea(); @@ -874,7 +875,6 @@ fheroes2::Image Interface::GameArea::GenerateUltimateArtifactAreaSurface( const fheroes2::Blit( marker, result, markerPos.x, markerPos.y + 8 ); fheroes2::ApplyPalette( result, PAL::GetPalette( PAL::PaletteType::TAN ) ); - result._disableTransformLayer(); return result; } diff --git a/src/fheroes2/gui/interface_radar.cpp b/src/fheroes2/gui/interface_radar.cpp index 83c8ba5684b..c63c95e3a20 100644 --- a/src/fheroes2/gui/interface_radar.cpp +++ b/src/fheroes2/gui/interface_radar.cpp @@ -146,8 +146,9 @@ Interface::Radar::Radar( BaseInterface & interface ) , _radarType( RadarType::WorldMap ) , _interface( interface ) { - // Radar image can not be transparent so we disable the transform layer to speed up rendering. + // Initialize radar image (_map) as a single-layer image. _map._disableTransformLayer(); + _map.resize( RADARWIDTH, RADARWIDTH ); } Interface::Radar::Radar( const Radar & radar, const fheroes2::Display & display ) @@ -158,8 +159,9 @@ Interface::Radar::Radar( const Radar & radar, const fheroes2::Display & display , _zoom( radar._zoom ) , _hide( false ) { - // Radar image can not be transparent so we disable the transform layer to speed up rendering. + // Initialize radar image (_map) as a single-layer image. _map._disableTransformLayer(); + _map.resize( RADARWIDTH, RADARWIDTH ); } void Interface::Radar::SavePosition() diff --git a/src/fheroes2/gui/interface_radar.h b/src/fheroes2/gui/interface_radar.h index 46bbff24c2e..0493228bc04 100644 --- a/src/fheroes2/gui/interface_radar.h +++ b/src/fheroes2/gui/interface_radar.h @@ -26,7 +26,6 @@ #include -#include "gamedefs.h" #include "image.h" #include "interface_border.h" #include "math_base.h" @@ -101,7 +100,7 @@ namespace Interface RadarType _radarType; BaseInterface & _interface; - fheroes2::Image _map{ RADARWIDTH, RADARWIDTH }; + fheroes2::Image _map; fheroes2::MovableSprite _cursorArea; fheroes2::Rect _roi; double _zoom{ 1.0 }; diff --git a/src/fheroes2/gui/ui_tool.cpp b/src/fheroes2/gui/ui_tool.cpp index 10f9c34a77c..098ec21e64a 100644 --- a/src/fheroes2/gui/ui_tool.cpp +++ b/src/fheroes2/gui/ui_tool.cpp @@ -479,8 +479,9 @@ namespace fheroes2 const double redCoeff = 4.0 - darkredStrength / 280.0; const double greenBlueCoeff = 4.0 - darkredStrength / 80.0; - Image out( width, height ); + Image out; out._disableTransformLayer(); + out.resize( width, height ); uint8_t * imageOutX = out.image(); const uint8_t * imageIn = in.image(); diff --git a/src/fheroes2/kingdom/view_world.cpp b/src/fheroes2/kingdom/view_world.cpp index b1fff263aa4..faa8ef5706a 100644 --- a/src/fheroes2/kingdom/view_world.cpp +++ b/src/fheroes2/kingdom/view_world.cpp @@ -194,8 +194,8 @@ namespace explicit CacheForMapWithResources( const ViewWorldMode viewMode ) { for ( int32_t i = 0; i < zoomLevels; ++i ) { - cachedImages[i].resize( world.w() * tileSizePerZoomLevel[i], world.h() * tileSizePerZoomLevel[i] ); cachedImages[i]._disableTransformLayer(); + cachedImages[i].resize( world.w() * tileSizePerZoomLevel[i], world.h() * tileSizePerZoomLevel[i] ); } const int32_t blockSizeX = 18; @@ -214,8 +214,9 @@ namespace const int32_t redrawAreaCenterY = blockSizeY * TILEWIDTH / 2; // Create temporary image where we will draw blocks of the main map on - fheroes2::Image temporaryImg( redrawAreaWidth, redrawAreaHeight ); + fheroes2::Image temporaryImg; temporaryImg._disableTransformLayer(); + temporaryImg.resize( redrawAreaWidth, redrawAreaHeight ); Interface::GameArea gamearea = Interface::AdventureMap::Get().getGameArea(); gamearea.SetAreaPosition( 0, 0, redrawAreaWidth, redrawAreaHeight ); From 8782450769f45c1ee7e393a3f58f73b5327838dc Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Thu, 4 Jan 2024 13:43:14 +0300 Subject: [PATCH 06/12] Apply IWYU suggestion --- src/fheroes2/maps/maps_tiles_render.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fheroes2/maps/maps_tiles_render.cpp b/src/fheroes2/maps/maps_tiles_render.cpp index 1591a6f726e..9a5192fd431 100644 --- a/src/fheroes2/maps/maps_tiles_render.cpp +++ b/src/fheroes2/maps/maps_tiles_render.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "agg_image.h" From 8377456db4b3dfbb729d88a128fd51e399b866bb Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Thu, 4 Jan 2024 13:46:56 +0300 Subject: [PATCH 07/12] Revert "Apply IWYU suggestion" This reverts commit 8782450769f45c1ee7e393a3f58f73b5327838dc. --- src/fheroes2/maps/maps_tiles_render.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fheroes2/maps/maps_tiles_render.cpp b/src/fheroes2/maps/maps_tiles_render.cpp index 9a5192fd431..1591a6f726e 100644 --- a/src/fheroes2/maps/maps_tiles_render.cpp +++ b/src/fheroes2/maps/maps_tiles_render.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "agg_image.h" From 67edb14c894bfb1f3eacb0a81f18719606ec64b9 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Thu, 4 Jan 2024 13:51:09 +0300 Subject: [PATCH 08/12] Update copyrights ... can it be automated? :) --- src/engine/h2d_file.cpp | 2 +- src/engine/image.h | 2 +- src/engine/image_tool.cpp | 2 +- src/engine/screen.cpp | 2 +- src/fheroes2/game/game_credits.cpp | 2 +- src/fheroes2/gui/ui_font.cpp | 2 +- src/fheroes2/gui/ui_tool.cpp | 2 +- src/fheroes2/maps/maps_tiles.cpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/engine/h2d_file.cpp b/src/engine/h2d_file.cpp index e1c415df2c1..854f78666ce 100644 --- a/src/engine/h2d_file.cpp +++ b/src/engine/h2d_file.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2021 - 2023 * + * Copyright (C) 2021 - 2024 * * * * 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 * diff --git a/src/engine/image.h b/src/engine/image.h index 3325b7c932e..e7a5996dbc3 100644 --- a/src/engine/image.h +++ b/src/engine/image.h @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2020 - 2023 * + * Copyright (C) 2020 - 2024 * * * * 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 * diff --git a/src/engine/image_tool.cpp b/src/engine/image_tool.cpp index e04a9eac5cb..b04ef25e2d5 100644 --- a/src/engine/image_tool.cpp +++ b/src/engine/image_tool.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2020 - 2023 * + * Copyright (C) 2020 - 2024 * * * * 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 * diff --git a/src/engine/screen.cpp b/src/engine/screen.cpp index 64f14a0fa97..1db13f69c68 100644 --- a/src/engine/screen.cpp +++ b/src/engine/screen.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2020 - 2023 * + * Copyright (C) 2020 - 2024 * * * * 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 * diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index 715294e8cfe..f8918780d27 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2020 - 2023 * + * Copyright (C) 2020 - 2024 * * * * 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 * diff --git a/src/fheroes2/gui/ui_font.cpp b/src/fheroes2/gui/ui_font.cpp index 6afea99e502..b3e28ee4f8c 100644 --- a/src/fheroes2/gui/ui_font.cpp +++ b/src/fheroes2/gui/ui_font.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2022 - 2023 * + * Copyright (C) 2022 - 2024 * * * * 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 * diff --git a/src/fheroes2/gui/ui_tool.cpp b/src/fheroes2/gui/ui_tool.cpp index 10f9c34a77c..74d6b01eac5 100644 --- a/src/fheroes2/gui/ui_tool.cpp +++ b/src/fheroes2/gui/ui_tool.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2020 - 2023 * + * Copyright (C) 2020 - 2024 * * * * 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 * diff --git a/src/fheroes2/maps/maps_tiles.cpp b/src/fheroes2/maps/maps_tiles.cpp index 99758fa1698..d8b372e4768 100644 --- a/src/fheroes2/maps/maps_tiles.cpp +++ b/src/fheroes2/maps/maps_tiles.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * From dbb5fb8dc437ffba2844bd1a71aaa83dd660af01 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sun, 7 Jan 2024 14:08:30 +0300 Subject: [PATCH 09/12] Update copyright years where needed --- src/engine/zzlib.cpp | 2 +- src/fheroes2/castle/castle_town.cpp | 2 +- src/fheroes2/castle/castle_well.cpp | 2 +- src/fheroes2/gui/interface_gamearea.cpp | 2 +- src/fheroes2/gui/interface_radar.cpp | 2 +- src/fheroes2/gui/interface_radar.h | 2 +- src/fheroes2/kingdom/view_world.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/engine/zzlib.cpp b/src/engine/zzlib.cpp index d769f0b8ea3..d103b5cc484 100644 --- a/src/engine/zzlib.cpp +++ b/src/engine/zzlib.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/castle/castle_town.cpp b/src/fheroes2/castle/castle_town.cpp index 438fe76e783..05180740f89 100644 --- a/src/fheroes2/castle/castle_town.cpp +++ b/src/fheroes2/castle/castle_town.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/castle/castle_well.cpp b/src/fheroes2/castle/castle_well.cpp index 49d455383cd..74b9a979416 100644 --- a/src/fheroes2/castle/castle_well.cpp +++ b/src/fheroes2/castle/castle_well.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/gui/interface_gamearea.cpp b/src/fheroes2/gui/interface_gamearea.cpp index 2564b72532d..f195103396b 100644 --- a/src/fheroes2/gui/interface_gamearea.cpp +++ b/src/fheroes2/gui/interface_gamearea.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/gui/interface_radar.cpp b/src/fheroes2/gui/interface_radar.cpp index db9ab963d45..662c107df5e 100644 --- a/src/fheroes2/gui/interface_radar.cpp +++ b/src/fheroes2/gui/interface_radar.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/gui/interface_radar.h b/src/fheroes2/gui/interface_radar.h index 0493228bc04..cdd1f7f620a 100644 --- a/src/fheroes2/gui/interface_radar.h +++ b/src/fheroes2/gui/interface_radar.h @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2019 - 2023 * + * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * diff --git a/src/fheroes2/kingdom/view_world.cpp b/src/fheroes2/kingdom/view_world.cpp index 3b08c26451d..d80a4c5a18f 100644 --- a/src/fheroes2/kingdom/view_world.cpp +++ b/src/fheroes2/kingdom/view_world.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * - * Copyright (C) 2021 - 2023 * + * Copyright (C) 2021 - 2024 * * * * 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 * From 400b5cf7ce6d9002f7aa30305a6ef7509c83a0fa Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sat, 20 Jan 2024 10:14:05 +0300 Subject: [PATCH 10/12] Fix format --- src/fheroes2/game/game_credits.cpp | 1454 ++++++++++++++-------------- 1 file changed, 727 insertions(+), 727 deletions(-) diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index fa3c9b4d3e7..b057c20ae5f 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -48,756 +48,756 @@ namespace { - void transformToBlack(fheroes2::Image& out) - { - if (out.empty()) { - return; - } - - assert(!out.singleLayer()); - - uint8_t* image = out.image(); - const uint8_t* transform = out.transform(); - const uint8_t* imageEnd = image + out.width() * out.height(); - - for (; image != imageEnd; ++image, ++transform) { - if (*transform == 0) { - *image = 0; - } - } - } - - enum class AnimationState : int - { - FADING_IN, - NO_ACTION, - FADING_OUT - }; - - class AnimationSequence - { - public: - AnimationSequence() = delete; - explicit AnimationSequence(const int32_t imageCount) - : _imageCount(imageCount) - {} - - int32_t pageId() const - { - return _pageId; - } - - uint8_t alpha() const - { - return static_cast(_alphaValue); - } - - AnimationState state() const - { - return _animationState; - } - - void increment() - { - switch (_animationState) { - case AnimationState::FADING_IN: - _alphaValue += ALPHA_VALUE_STEP; - if (_alphaValue > 255) { - _alphaValue = 255; - _animationState = AnimationState::NO_ACTION; - _noActionCounter = 0; - } - break; - case AnimationState::NO_ACTION: - ++_noActionCounter; - if (_noActionCounter > NO_ACTION_COUNTER_LIMIT) { - _animationState = AnimationState::FADING_OUT; - } - break; - case AnimationState::FADING_OUT: - _alphaValue -= ALPHA_VALUE_STEP; - if (_alphaValue < 0) { - _alphaValue = 0; - _animationState = AnimationState::FADING_IN; - - ++_pageId; - if (_pageId >= _imageCount) { - _pageId = 0; - } - } - - break; - default: - assert(0); - break; - } - } - - private: - const int32_t _imageCount; - int32_t _alphaValue = 0; - int32_t _noActionCounter = 0; - int32_t _pageId = 0; - - AnimationState _animationState = AnimationState::FADING_IN; - - enum : int32_t - { - ALPHA_VALUE_STEP = 5, - NO_ACTION_COUNTER_LIMIT = 100 - }; - }; - - fheroes2::Sprite generateHeader() - { - const fheroes2::Sprite& background = fheroes2::AGG::GetICN(ICN::CBKGLAVA, 0); - assert(background.height() < fheroes2::Display::DEFAULT_HEIGHT); - - fheroes2::Sprite output; - output._disableTransformLayer(); - output.resize(fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT - background.height()); - output.fill(0); - - const fheroes2::Text caption("fheroes2 engine (" + Settings::GetVersion() + ")", fheroes2::FontType::normalYellow()); - caption.draw(output.width() / 2 - caption.width() / 2, 17, output); - - return output; - } - - int32_t renderText(fheroes2::Image& output, const int32_t offsetX, const int32_t offsetY, const int32_t textWidth, const char* titleText, const char* bodyText) - { - const fheroes2::Text title(titleText, fheroes2::FontType::normalYellow()); - const fheroes2::Text name(bodyText, fheroes2::FontType::normalWhite()); - - title.draw(offsetX, offsetY, textWidth, output); - const int32_t titleHeight = title.height(textWidth); - - name.draw(offsetX, offsetY + titleHeight, textWidth, output); - - return name.height(textWidth) + titleHeight; - } - - fheroes2::Sprite generateResurrectionCreditsFirstPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGLAVA, 0); - output._disableTransformLayer(); - - const int32_t columnStep = 210; - const int32_t textInitialOffsetY = 42; - const int32_t textWidth = 200; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Project Coordination and Core Development"), "Ihar Hubchyk"); - offsetY += 10; - - const fheroes2::Sprite& blackDragon = fheroes2::AGG::GetICN(ICN::DRAGBLAK, 5); - fheroes2::Blit(blackDragon, output, (columnStep - blackDragon.width()) / 2, offsetY); - offsetY += blackDragon.height() + 50; - - const int32_t secondAuthorLayerY = offsetY; - - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Development"), "Sergei Ivanov"); - offsetY += 10; - - const fheroes2::Sprite& minotaur = fheroes2::AGG::GetICN(ICN::MINOTAUR, 14); - fheroes2::Blit(minotaur, output, (columnStep - minotaur.width()) / 2, offsetY); - offsetY += minotaur.height(); - - offsetY += 40; - - const fheroes2::Text websiteInto(_("Visit us at "), fheroes2::FontType::normalWhite()); - const fheroes2::Text website("https://github.com/ihhub/fheroes2", fheroes2::FontType::normalYellow()); - - const int32_t websiteIntoWidth = websiteInto.width(); - const int32_t websiteWidth = website.width(); - const int32_t websiteHeight = website.height(); - const int32_t websiteOffsetX = (output.width() - websiteIntoWidth - websiteWidth) / 2; - websiteInto.draw(websiteOffsetX, offsetY, output); - website.draw(websiteOffsetX + websiteIntoWidth, offsetY, output); - - const fheroes2::Sprite& missile = fheroes2::AGG::GetICN(ICN::ARCH_MSL, 4); - fheroes2::Blit(missile, output, websiteOffsetX - 10 - missile.width(), offsetY + websiteHeight / 2 - missile.height() / 2); - fheroes2::Blit(missile, output, websiteOffsetX + websiteIntoWidth + websiteWidth + 10, offsetY + websiteHeight / 2 - missile.height() / 2, true); - - offsetY = textInitialOffsetY; - offsetX += columnStep; - - offsetY += renderText(output, offsetX, offsetY, textWidth, _("QA and Support"), "Igor Tsivilko"); - offsetY += 10; - - const fheroes2::Sprite& cyclop = fheroes2::AGG::GetICN(ICN::CYCLOPS, 38); - fheroes2::Blit(cyclop, output, offsetX + (columnStep - cyclop.width()) / 2, offsetY); - - offsetY = secondAuthorLayerY; + void transformToBlack( fheroes2::Image & out ) + { + if ( out.empty() ) { + return; + } + + assert( !out.singleLayer() ); + + uint8_t * image = out.image(); + const uint8_t * transform = out.transform(); + const uint8_t * imageEnd = image + out.width() * out.height(); + + for ( ; image != imageEnd; ++image, ++transform ) { + if ( *transform == 0 ) { + *image = 0; + } + } + } + + enum class AnimationState : int + { + FADING_IN, + NO_ACTION, + FADING_OUT + }; + + class AnimationSequence + { + public: + AnimationSequence() = delete; + explicit AnimationSequence( const int32_t imageCount ) + : _imageCount( imageCount ) + {} + + int32_t pageId() const + { + return _pageId; + } + + uint8_t alpha() const + { + return static_cast( _alphaValue ); + } + + AnimationState state() const + { + return _animationState; + } + + void increment() + { + switch ( _animationState ) { + case AnimationState::FADING_IN: + _alphaValue += ALPHA_VALUE_STEP; + if ( _alphaValue > 255 ) { + _alphaValue = 255; + _animationState = AnimationState::NO_ACTION; + _noActionCounter = 0; + } + break; + case AnimationState::NO_ACTION: + ++_noActionCounter; + if ( _noActionCounter > NO_ACTION_COUNTER_LIMIT ) { + _animationState = AnimationState::FADING_OUT; + } + break; + case AnimationState::FADING_OUT: + _alphaValue -= ALPHA_VALUE_STEP; + if ( _alphaValue < 0 ) { + _alphaValue = 0; + _animationState = AnimationState::FADING_IN; + + ++_pageId; + if ( _pageId >= _imageCount ) { + _pageId = 0; + } + } + + break; + default: + assert( 0 ); + break; + } + } + + private: + const int32_t _imageCount; + int32_t _alphaValue = 0; + int32_t _noActionCounter = 0; + int32_t _pageId = 0; + + AnimationState _animationState = AnimationState::FADING_IN; + + enum : int32_t + { + ALPHA_VALUE_STEP = 5, + NO_ACTION_COUNTER_LIMIT = 100 + }; + }; + + fheroes2::Sprite generateHeader() + { + const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); + assert( background.height() < fheroes2::Display::DEFAULT_HEIGHT ); + + fheroes2::Sprite output; + output._disableTransformLayer(); + output.resize( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT - background.height() ); + output.fill( 0 ); + + const fheroes2::Text caption( "fheroes2 engine (" + Settings::GetVersion() + ")", fheroes2::FontType::normalYellow() ); + caption.draw( output.width() / 2 - caption.width() / 2, 17, output ); + + return output; + } + + int32_t renderText( fheroes2::Image & output, const int32_t offsetX, const int32_t offsetY, const int32_t textWidth, const char * titleText, const char * bodyText ) + { + const fheroes2::Text title( titleText, fheroes2::FontType::normalYellow() ); + const fheroes2::Text name( bodyText, fheroes2::FontType::normalWhite() ); + + title.draw( offsetX, offsetY, textWidth, output ); + const int32_t titleHeight = title.height( textWidth ); + + name.draw( offsetX, offsetY + titleHeight, textWidth, output ); + + return name.height( textWidth ) + titleHeight; + } + + fheroes2::Sprite generateResurrectionCreditsFirstPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); + output._disableTransformLayer(); + + const int32_t columnStep = 210; + const int32_t textInitialOffsetY = 42; + const int32_t textWidth = 200; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Project Coordination and Core Development" ), "Ihar Hubchyk" ); + offsetY += 10; + + const fheroes2::Sprite & blackDragon = fheroes2::AGG::GetICN( ICN::DRAGBLAK, 5 ); + fheroes2::Blit( blackDragon, output, ( columnStep - blackDragon.width() ) / 2, offsetY ); + offsetY += blackDragon.height() + 50; + + const int32_t secondAuthorLayerY = offsetY; + + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Sergei Ivanov" ); + offsetY += 10; + + const fheroes2::Sprite & minotaur = fheroes2::AGG::GetICN( ICN::MINOTAUR, 14 ); + fheroes2::Blit( minotaur, output, ( columnStep - minotaur.width() ) / 2, offsetY ); + offsetY += minotaur.height(); + + offsetY += 40; + + const fheroes2::Text websiteInto( _( "Visit us at " ), fheroes2::FontType::normalWhite() ); + const fheroes2::Text website( "https://github.com/ihhub/fheroes2", fheroes2::FontType::normalYellow() ); + + const int32_t websiteIntoWidth = websiteInto.width(); + const int32_t websiteWidth = website.width(); + const int32_t websiteHeight = website.height(); + const int32_t websiteOffsetX = ( output.width() - websiteIntoWidth - websiteWidth ) / 2; + websiteInto.draw( websiteOffsetX, offsetY, output ); + website.draw( websiteOffsetX + websiteIntoWidth, offsetY, output ); + + const fheroes2::Sprite & missile = fheroes2::AGG::GetICN( ICN::ARCH_MSL, 4 ); + fheroes2::Blit( missile, output, websiteOffsetX - 10 - missile.width(), offsetY + websiteHeight / 2 - missile.height() / 2 ); + fheroes2::Blit( missile, output, websiteOffsetX + websiteIntoWidth + websiteWidth + 10, offsetY + websiteHeight / 2 - missile.height() / 2, true ); + + offsetY = textInitialOffsetY; + offsetX += columnStep; + + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "QA and Support" ), "Igor Tsivilko" ); + offsetY += 10; + + const fheroes2::Sprite & cyclop = fheroes2::AGG::GetICN( ICN::CYCLOPS, 38 ); + fheroes2::Blit( cyclop, output, offsetX + ( columnStep - cyclop.width() ) / 2, offsetY ); + + offsetY = secondAuthorLayerY; - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Development"), "Ivan Shibanov"); - offsetY += 10; + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Ivan Shibanov" ); + offsetY += 10; - const fheroes2::Sprite& crusader = fheroes2::AGG::GetICN(ICN::PALADIN2, 23); - fheroes2::Blit(crusader, output, offsetX + (columnStep - crusader.width()) / 2, offsetY); + const fheroes2::Sprite & crusader = fheroes2::AGG::GetICN( ICN::PALADIN2, 23 ); + fheroes2::Blit( crusader, output, offsetX + ( columnStep - crusader.width() ) / 2, offsetY ); - offsetY = textInitialOffsetY; - offsetX += columnStep; + offsetY = textInitialOffsetY; + offsetX += columnStep; - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Development"), "Oleg Derevenetz"); - offsetY += 10; + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Oleg Derevenetz" ); + offsetY += 10; - const fheroes2::Sprite& mage = fheroes2::AGG::GetICN(ICN::MAGE1, 24); - fheroes2::Blit(mage, output, offsetX + (columnStep - mage.width()) / 2, offsetY); + const fheroes2::Sprite & mage = fheroes2::AGG::GetICN( ICN::MAGE1, 24 ); + fheroes2::Blit( mage, output, offsetX + ( columnStep - mage.width() ) / 2, offsetY ); - offsetY = secondAuthorLayerY; + offsetY = secondAuthorLayerY; - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Dev and Support"), "Zense"); - offsetY += 10; + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Dev and Support" ), "Zense" ); + offsetY += 10; - const fheroes2::Sprite& phoenix = fheroes2::AGG::GetICN(ICN::PHOENIX, 4); - fheroes2::Blit(phoenix, output, offsetX + (columnStep - phoenix.width()) / 2, offsetY - 10); + const fheroes2::Sprite & phoenix = fheroes2::AGG::GetICN( ICN::PHOENIX, 4 ); + fheroes2::Blit( phoenix, output, offsetX + ( columnStep - phoenix.width() ) / 2, offsetY - 10 ); - const fheroes2::Sprite& goblin = fheroes2::AGG::GetICN(ICN::GOBLIN, 27); - fheroes2::Blit(goblin, output, output.width() - goblin.width() * 2, output.height() - goblin.height() - 10, true); + const fheroes2::Sprite & goblin = fheroes2::AGG::GetICN( ICN::GOBLIN, 27 ); + fheroes2::Blit( goblin, output, output.width() - goblin.width() * 2, output.height() - goblin.height() - 10, true ); - return output; - } + return output; + } - fheroes2::Sprite generateResurrectionCreditsSecondPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGLAVA, 0); - output._disableTransformLayer(); + fheroes2::Sprite generateResurrectionCreditsSecondPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); + output._disableTransformLayer(); - const int32_t textInitialOffsetX = output.width() / 2; - const int32_t textInitialOffsetY = 60; - const int32_t textWidth = 300; - const int32_t textOffsetX = (textInitialOffsetX - textWidth) / 2; + const int32_t textInitialOffsetX = output.width() / 2; + const int32_t textInitialOffsetY = 60; + const int32_t textWidth = 300; + const int32_t textOffsetX = ( textInitialOffsetX - textWidth ) / 2; - int32_t offsetY = textInitialOffsetY; + int32_t offsetY = textInitialOffsetY; - const fheroes2::Text title(_("Special Thanks to"), fheroes2::FontType::normalYellow()); - title.draw(textInitialOffsetX - title.width() / 2, offsetY, output); - offsetY += title.height() + 5; + const fheroes2::Text title( _( "Special Thanks to" ), fheroes2::FontType::normalYellow() ); + title.draw( textInitialOffsetX - title.width() / 2, offsetY, output ); + offsetY += title.height() + 5; - std::string contributors("LeHerosInconnu\n" - "undef21\n" - "shprotru\n" - "Arkadiy Illarionov\n" - "a1exsh\n" - "vincent-grosbois\n" - "eos428\n" - "Arthusppp\n" - "felix642\n" - "Vasilenko Alexey\n" - "Andrii Kurdiumov\n" - "Mr-Bajs\n" - "dimag0g\n" - "Effektus\n" - "Laserlicht\n" - "Stisen1\n" - "Mauri Mustonen\n" - "tau3\n"); + std::string contributors( "LeHerosInconnu\n" + "undef21\n" + "shprotru\n" + "Arkadiy Illarionov\n" + "a1exsh\n" + "vincent-grosbois\n" + "eos428\n" + "Arthusppp\n" + "felix642\n" + "Vasilenko Alexey\n" + "Andrii Kurdiumov\n" + "Mr-Bajs\n" + "dimag0g\n" + "Effektus\n" + "Laserlicht\n" + "Stisen1\n" + "Mauri Mustonen\n" + "tau3\n" ); - fheroes2::Text name(std::move(contributors), fheroes2::FontType::normalWhite()); - const int32_t constributorsHeight = name.height(textWidth); - const int32_t contributorCount = name.rows(textWidth); - name.draw(textOffsetX, offsetY, textWidth, output); + fheroes2::Text name( std::move( contributors ), fheroes2::FontType::normalWhite() ); + const int32_t constributorsHeight = name.height( textWidth ); + const int32_t contributorCount = name.rows( textWidth ); + name.draw( textOffsetX, offsetY, textWidth, output ); - std::string supporters("Aimi Lindschouw\n" - "Aleksei Mazur\n" - "Andrew Szucs\n" - "Benjamin Hughes\n" - "Brandon Wright\n" - "Connor Townsend\n" - "Hajler\n" - "Kiril Lipatov\n" - "Kresimir Condic\n" - "Kuza\n" - "Matt Taylor\n" - "slvclw\n" - "TechnoCore\n" - "William Hoskinson\n"); + std::string supporters( "Aimi Lindschouw\n" + "Aleksei Mazur\n" + "Andrew Szucs\n" + "Benjamin Hughes\n" + "Brandon Wright\n" + "Connor Townsend\n" + "Hajler\n" + "Kiril Lipatov\n" + "Kresimir Condic\n" + "Kuza\n" + "Matt Taylor\n" + "slvclw\n" + "TechnoCore\n" + "William Hoskinson\n" ); - name.set(std::move(supporters), fheroes2::FontType::normalWhite()); - const int32_t supportersHeight = name.height(textWidth); - const int32_t supporterCount = name.rows(textWidth); - const int32_t countDifference = (contributorCount - supporterCount); - const int32_t supportersOffset = (countDifference / 2) * (supportersHeight / supporterCount); + name.set( std::move( supporters ), fheroes2::FontType::normalWhite() ); + const int32_t supportersHeight = name.height( textWidth ); + const int32_t supporterCount = name.rows( textWidth ); + const int32_t countDifference = ( contributorCount - supporterCount ); + const int32_t supportersOffset = ( countDifference / 2 ) * ( supportersHeight / supporterCount ); - name.draw(textInitialOffsetX + textOffsetX, offsetY + supportersOffset, textWidth, output); + name.draw( textInitialOffsetX + textOffsetX, offsetY + supportersOffset, textWidth, output ); - offsetY += constributorsHeight; + offsetY += constributorsHeight; - name.set(_("and many other contributors!"), fheroes2::FontType::normalWhite()); - name.draw(10, offsetY, textWidth, output); - - name.set(_("and many-many other supporters!"), fheroes2::FontType::normalWhite()); - name.draw(textInitialOffsetX + textOffsetX, offsetY, textWidth, output); - - const fheroes2::Sprite& hydra = fheroes2::AGG::GetICN(ICN::HYDRA, 11); - - offsetY = output.height() - hydra.height() - 40; - - fheroes2::Blit(hydra, output, textInitialOffsetX - hydra.width() / 2, offsetY); - - return output; - } - - fheroes2::Sprite generateResurrectionCreditsThirdPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGSWMP, 0); - output._disableTransformLayer(); - - const int32_t textInitialOffsetX = output.width() / 2; - const int32_t textInitialOffsetY = 80; - const int32_t textWidth = 300; - - int32_t offsetX = (textInitialOffsetX - textWidth) / 2; - int32_t offsetY = textInitialOffsetY; - - offsetY += renderText(output, offsetX, offsetY, textWidth, _("Support us at"), _("local-donation-platform|https://www.patreon.com/fheroes2")); - offsetY += 30; - - const fheroes2::Sprite& wizard = fheroes2::AGG::GetICN(ICN::CMBTCAPZ, 4); - fheroes2::Blit(wizard, output, (textInitialOffsetX - wizard.width()) / 2, offsetY); - offsetY += wizard.height() + 20; - - offsetY - += renderText(output, offsetX, offsetY, textWidth - 10, _("Connect with us at"), _("local-social-network|https://www.facebook.com/groups/fheroes2")); - offsetY += 20; - - const fheroes2::Sprite& vampireLord = fheroes2::AGG::GetICN(ICN::VAMPIRE2, 22); - fheroes2::Blit(vampireLord, output, (textInitialOffsetX - vampireLord.width()) / 2, offsetY); - - offsetY = textInitialOffsetY; - offsetX += textInitialOffsetX; - - offsetY += renderText(output, offsetX, offsetY, textWidth - 10, _("Need help with the game?"), "https://discord.gg/xF85vbZ"); - offsetY += 10; - - fheroes2::Sprite labyrinth = fheroes2::AGG::GetICN(ICN::TWNWUP_3, 0); - fheroes2::ApplyPalette(labyrinth, 2); - fheroes2::Blit(labyrinth, output, textInitialOffsetX + (textInitialOffsetX - labyrinth.width()) / 2, offsetY); - - offsetY += labyrinth.height() + 50; - - const int32_t miniMonsterXOffset = textInitialOffsetX * 3 / 2; - - fheroes2::Text name(_("Original project before 0.7"), fheroes2::FontType::smallYellow()); - name.draw(offsetX, offsetY, textWidth - 10, output); - offsetY += name.height(textWidth - 10); - name.set("Andrey Afletdinov\nhttps://sourceforge.net/\nprojects/fheroes2/", fheroes2::FontType::smallWhite()); - name.draw(offsetX, offsetY, textWidth - 10, output); - - fheroes2::Sprite creature = fheroes2::AGG::GetICN(ICN::MAGE2, 4); - transformToBlack(creature); - - const int32_t creatureOffsetY = output.height() - 95; - fheroes2::Blit(creature, 0, 0, output, miniMonsterXOffset - creature.width() / 2, creatureOffsetY, creature.width(), creature.height()); - name.set("?", fheroes2::FontType::normalYellow()); - name.draw(miniMonsterXOffset - name.width() / 2, creatureOffsetY + creature.height() / 2 - 5, output); - - return output; - } - - fheroes2::Sprite generateSuccessionWarsCreditsFirstPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGWATR, 0); - fheroes2::ApplyPalette(output, PAL::GetPalette(PAL::PaletteType::DARKENING)); - output._disableTransformLayer(); - - const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); - - const fheroes2::Text title(_("Heroes of Might and Magic II: The Succession Wars team"), nameFontType); - title.draw((output.width() - title.width()) / 2, 10, output); - - const int32_t textInitialOffsetY = 35; - const int32_t textWidth = 320; - const int32_t titleOffsetY = 7; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Designed and Directed"), "Jon Van Caneghem"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Programming and Design"), "Phil Steinmeyer"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Executive Producer"), "Mark Caldwell"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Producer"), "Walt Hochbrueckner"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Additional Design"), - "Paul Rattner\n" - "Debbie Van Caneghem"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Additional Programming"), - "George Ruof\n" - "Todd Hendrix\n" - "Mark Caldwell"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Musical Production"), "Rob King"); - renderText(output, offsetX, offsetY, textWidth, _("Music and Sound Design"), - "Rob King\n" - "Steve Baca\n" - "Paul Romero"); - - offsetY = textInitialOffsetY; - offsetX += textWidth; - - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Vocalists"), - "Grant Youngblood\n" - "Kareen Meshagan"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Art Director"), "Julia Ulano"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Assistant Art Director"), "Bonita Long-Hemsath"); - renderText(output, offsetX, offsetY, textWidth, _("Artists"), - "Julie Bateman\n" - "Rebecca Christel\n" - "Shelly Garcia\n" - "Sam Hasson\n" - "Louis Henderson\n" - "Tracy Iwata\n" - "Steve Jasper\n" - "April Lee\n" - "Lieu Pham\n" - "Phelan Sykes\n" - "Steve Wasaff\n" - "Scott White"); - - return output; - } - - fheroes2::Sprite generateSuccessionWarsCreditsSecondPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGWATR, 0); - fheroes2::ApplyPalette(output, PAL::GetPalette(PAL::PaletteType::DARKENING)); - output._disableTransformLayer(); - - const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); - - const fheroes2::Text title(_("Heroes of Might and Magic II: The Succession Wars team"), nameFontType); - title.draw((output.width() - title.width()) / 2, 10, output); - - const int32_t textInitialOffsetY = 35; - const int32_t textWidth = 320; - const int32_t titleOffsetY = 7; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("QA Manager"), "Peter Ryu"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("QA"), - "David Botan\n" - "David Fernandez\n" - "Bill Nesemeier\n" - "Walter Johnson\n" - "Kate McClelland\n" - "Timothy Lang\n" - "Bryan Farina"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Writing"), "Paul Rattner"); - renderText(output, offsetX, offsetY, textWidth, _("Manual and Helpfile"), - "Bryan Farina\n" - "Rozita Tolouey\n" - "Bruce Schlickbernd"); - - offsetY = textInitialOffsetY; - offsetX += textWidth; - - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Scenarios"), - "Jon Van Caneghem\n" - "Debbie Van Caneghem\n" - "Clayton Retzer\n" - "Christian Vanover\n" - "Paul Rattner\n" - "Benjamin Bent\n" - "Bryan Farina\n" - "Eric Heffron\n" - "Mark Palczynski\n" - "Walt Hochbrueckner\n" - "Bruce Schlickbernd\n" - "Craig Konas"); - renderText(output, offsetX, offsetY, textWidth, _("Special Thanks to"), - "Scott McDaniel\n" - "Dean Rettig\n" - "Ted Chapman\n" - "Dean Frost"); - - return output; - } - - fheroes2::Sprite generatePriceOfLoyaltyCreditsFirstPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGGRAV, 0); - fheroes2::ApplyPalette(output, PAL::GetPalette(PAL::PaletteType::DARKENING)); - output._disableTransformLayer(); - - const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); - const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); - - fheroes2::Text title(_("Heroes of Might and Magic II: The Price of Loyalty team"), nameFontType); - title.draw((output.width() - title.width()) / 2, 10, output); - - title.set("Cyberlore Studios", titleFontType); - title.draw((output.width() - title.width()) / 2, 10 + title.height() * 2, output); - - const int32_t textInitialOffsetY = 35 + title.height() * 4; - const int32_t textWidth = 320; - const int32_t titleOffsetY = 7; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Executive Producer"), "Lester Humphreys"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Producer"), "Joe Minton"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Design Lead"), "Jim DuBois"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Designers"), - "Jesse King\n" - "Kris Greenia"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Programming Lead"), "Mike White"); - renderText(output, offsetX, offsetY, textWidth, _("Art Director"), "Seth Spaulding"); - - offsetY = textInitialOffsetY; - offsetX += textWidth; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Art Lead"), "Thomas Gale"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Artists"), - "Michael Clarke\n" - "Michael Baker\n" - "Julie Airoldi"); - renderText(output, offsetX, offsetY, textWidth, _("Playtesters"), - "Bart Simon\n" - "Fred Fredette\n" - "Rendall Koski\n" - "T.J. Andrzejczyk\n" - "Joanne Delphia"); - - return output; - } - - fheroes2::Sprite generatePriceOfLoyaltyCreditsSecondPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGGRAV, 0); - fheroes2::ApplyPalette(output, PAL::GetPalette(PAL::PaletteType::DARKENING)); - output._disableTransformLayer(); - - const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); - const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); - - fheroes2::Text title(_("Heroes of Might and Magic II: The Price of Loyalty team"), nameFontType); - title.draw((output.width() - title.width()) / 2, 10, output); - - title.set("New World Computing", titleFontType); - title.draw((output.width() - title.width()) / 2, 10 + title.height() * 2, output); - - const int32_t textInitialOffsetY = 35 + title.height() * 4; - const int32_t textWidth = 320; - const int32_t titleOffsetY = 7; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Designer"), "Jon Van Caneghem"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Executive Producer"), "Mark Caldwell"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Producers"), - "Peter Ryu\n" - "Deane Rettig"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Musical Production"), "Rob King"); - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("QA Managers"), - "Brian Gilmer\n" - "Peter Ryu"); - renderText(output, offsetX, offsetY, textWidth, _("Music"), - "Rob King\n" - "Paul Romero\n" - "Steve Baca"); - - offsetY = textInitialOffsetY; - offsetX += textWidth; - - offsetY += titleOffsetY - + renderText(output, offsetX, offsetY, textWidth, _("Sound Design"), - "Rob King\n" - "Steve Baca"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Town Themes"), "Paul Romero"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Alto Sax"), "Brock \"Saxman\" Summers"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Harpsichord and Piano"), "Paul Romero"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Basso Vocal"), "Reid Bruton"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Soprano Vocal"), "Karin Meshagin"); - - std::string recordedString = _("Recorded at %{recordingStudio}"); - StringReplace(recordedString, "%{recordingStudio}", "Green Street Studios"); - - title.set(recordedString, titleFontType); - title.draw(offsetX, offsetY, textWidth, output); - - return output; - } - - fheroes2::Sprite generatePriceOfLoyaltyCreditsThirdPage() - { - fheroes2::Sprite output = fheroes2::AGG::GetICN(ICN::CBKGGRAV, 0); - fheroes2::ApplyPalette(output, PAL::GetPalette(PAL::PaletteType::DARKENING)); - output._disableTransformLayer(); - - const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); - const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); - - fheroes2::Text title(_("Heroes of Might and Magic II: The Price of Loyalty team"), nameFontType); - title.draw((output.width() - title.width()) / 2, 10, output); - - title.set("New World Computing", titleFontType); - title.draw((output.width() - title.width()) / 2, 10 + title.height() * 2, output); - - const int32_t textInitialOffsetY = 35 + title.height() * 4; - const int32_t textWidth = 320; - const int32_t titleOffsetY = 7; - - int32_t offsetY = textInitialOffsetY; - int32_t offsetX = 0; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("credits|Manual"), "Bryan Farina"); - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("German Consultant"), "Dr. Brock H. Summers"); - renderText(output, offsetX, offsetY, textWidth, _("Map Designers"), - "Christian Vanover\n" - "Ben Bent\n" - "Tracy Iwata\n" - "Clay Ratzner\n" - "Walter Hochbrueckner\n" - "Paul Ratner"); - - offsetY = textInitialOffsetY; - offsetX += textWidth; - - offsetY += titleOffsetY + renderText(output, offsetX, offsetY, textWidth, _("Package Design"), "Rozita Tolouey"); - renderText(output, offsetX, offsetY, textWidth, _("Playtesters"), - "Mikeael Herauf\n" - "Walter Johnson\n" - "David Botan\n" - "David Fernandez\n" - "Kate McClelland\n" - "William Nesemeier\n" - "Tim Lang\n" - "Pavel Vesely\n" - "John Lencioni\n" - "Jason Wildblood"); - - return output; - } + name.set( _( "and many other contributors!" ), fheroes2::FontType::normalWhite() ); + name.draw( 10, offsetY, textWidth, output ); + + name.set( _( "and many-many other supporters!" ), fheroes2::FontType::normalWhite() ); + name.draw( textInitialOffsetX + textOffsetX, offsetY, textWidth, output ); + + const fheroes2::Sprite & hydra = fheroes2::AGG::GetICN( ICN::HYDRA, 11 ); + + offsetY = output.height() - hydra.height() - 40; + + fheroes2::Blit( hydra, output, textInitialOffsetX - hydra.width() / 2, offsetY ); + + return output; + } + + fheroes2::Sprite generateResurrectionCreditsThirdPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGSWMP, 0 ); + output._disableTransformLayer(); + + const int32_t textInitialOffsetX = output.width() / 2; + const int32_t textInitialOffsetY = 80; + const int32_t textWidth = 300; + + int32_t offsetX = ( textInitialOffsetX - textWidth ) / 2; + int32_t offsetY = textInitialOffsetY; + + offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Support us at" ), _( "local-donation-platform|https://www.patreon.com/fheroes2" ) ); + offsetY += 30; + + const fheroes2::Sprite & wizard = fheroes2::AGG::GetICN( ICN::CMBTCAPZ, 4 ); + fheroes2::Blit( wizard, output, ( textInitialOffsetX - wizard.width() ) / 2, offsetY ); + offsetY += wizard.height() + 20; + + offsetY + += renderText( output, offsetX, offsetY, textWidth - 10, _( "Connect with us at" ), _( "local-social-network|https://www.facebook.com/groups/fheroes2" ) ); + offsetY += 20; + + const fheroes2::Sprite & vampireLord = fheroes2::AGG::GetICN( ICN::VAMPIRE2, 22 ); + fheroes2::Blit( vampireLord, output, ( textInitialOffsetX - vampireLord.width() ) / 2, offsetY ); + + offsetY = textInitialOffsetY; + offsetX += textInitialOffsetX; + + offsetY += renderText( output, offsetX, offsetY, textWidth - 10, _( "Need help with the game?" ), "https://discord.gg/xF85vbZ" ); + offsetY += 10; + + fheroes2::Sprite labyrinth = fheroes2::AGG::GetICN( ICN::TWNWUP_3, 0 ); + fheroes2::ApplyPalette( labyrinth, 2 ); + fheroes2::Blit( labyrinth, output, textInitialOffsetX + ( textInitialOffsetX - labyrinth.width() ) / 2, offsetY ); + + offsetY += labyrinth.height() + 50; + + const int32_t miniMonsterXOffset = textInitialOffsetX * 3 / 2; + + fheroes2::Text name( _( "Original project before 0.7" ), fheroes2::FontType::smallYellow() ); + name.draw( offsetX, offsetY, textWidth - 10, output ); + offsetY += name.height( textWidth - 10 ); + name.set( "Andrey Afletdinov\nhttps://sourceforge.net/\nprojects/fheroes2/", fheroes2::FontType::smallWhite() ); + name.draw( offsetX, offsetY, textWidth - 10, output ); + + fheroes2::Sprite creature = fheroes2::AGG::GetICN( ICN::MAGE2, 4 ); + transformToBlack( creature ); + + const int32_t creatureOffsetY = output.height() - 95; + fheroes2::Blit( creature, 0, 0, output, miniMonsterXOffset - creature.width() / 2, creatureOffsetY, creature.width(), creature.height() ); + name.set( "?", fheroes2::FontType::normalYellow() ); + name.draw( miniMonsterXOffset - name.width() / 2, creatureOffsetY + creature.height() / 2 - 5, output ); + + return output; + } + + fheroes2::Sprite generateSuccessionWarsCreditsFirstPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGWATR, 0 ); + fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); + output._disableTransformLayer(); + + const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); + + const fheroes2::Text title( _( "Heroes of Might and Magic II: The Succession Wars team" ), nameFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10, output ); + + const int32_t textInitialOffsetY = 35; + const int32_t textWidth = 320; + const int32_t titleOffsetY = 7; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Designed and Directed" ), "Jon Van Caneghem" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Programming and Design" ), "Phil Steinmeyer" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Mark Caldwell" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Producer" ), "Walt Hochbrueckner" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Additional Design" ), + "Paul Rattner\n" + "Debbie Van Caneghem" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Additional Programming" ), + "George Ruof\n" + "Todd Hendrix\n" + "Mark Caldwell" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Musical Production" ), "Rob King" ); + renderText( output, offsetX, offsetY, textWidth, _( "Music and Sound Design" ), + "Rob King\n" + "Steve Baca\n" + "Paul Romero" ); + + offsetY = textInitialOffsetY; + offsetX += textWidth; + + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Vocalists" ), + "Grant Youngblood\n" + "Kareen Meshagan" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Art Director" ), "Julia Ulano" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Assistant Art Director" ), "Bonita Long-Hemsath" ); + renderText( output, offsetX, offsetY, textWidth, _( "Artists" ), + "Julie Bateman\n" + "Rebecca Christel\n" + "Shelly Garcia\n" + "Sam Hasson\n" + "Louis Henderson\n" + "Tracy Iwata\n" + "Steve Jasper\n" + "April Lee\n" + "Lieu Pham\n" + "Phelan Sykes\n" + "Steve Wasaff\n" + "Scott White" ); + + return output; + } + + fheroes2::Sprite generateSuccessionWarsCreditsSecondPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGWATR, 0 ); + fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); + output._disableTransformLayer(); + + const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); + + const fheroes2::Text title( _( "Heroes of Might and Magic II: The Succession Wars team" ), nameFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10, output ); + + const int32_t textInitialOffsetY = 35; + const int32_t textWidth = 320; + const int32_t titleOffsetY = 7; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "QA Manager" ), "Peter Ryu" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "QA" ), + "David Botan\n" + "David Fernandez\n" + "Bill Nesemeier\n" + "Walter Johnson\n" + "Kate McClelland\n" + "Timothy Lang\n" + "Bryan Farina" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Writing" ), "Paul Rattner" ); + renderText( output, offsetX, offsetY, textWidth, _( "Manual and Helpfile" ), + "Bryan Farina\n" + "Rozita Tolouey\n" + "Bruce Schlickbernd" ); + + offsetY = textInitialOffsetY; + offsetX += textWidth; + + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Scenarios" ), + "Jon Van Caneghem\n" + "Debbie Van Caneghem\n" + "Clayton Retzer\n" + "Christian Vanover\n" + "Paul Rattner\n" + "Benjamin Bent\n" + "Bryan Farina\n" + "Eric Heffron\n" + "Mark Palczynski\n" + "Walt Hochbrueckner\n" + "Bruce Schlickbernd\n" + "Craig Konas" ); + renderText( output, offsetX, offsetY, textWidth, _( "Special Thanks to" ), + "Scott McDaniel\n" + "Dean Rettig\n" + "Ted Chapman\n" + "Dean Frost" ); + + return output; + } + + fheroes2::Sprite generatePriceOfLoyaltyCreditsFirstPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); + fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); + output._disableTransformLayer(); + + const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); + const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); + + fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10, output ); + + title.set( "Cyberlore Studios", titleFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); + + const int32_t textInitialOffsetY = 35 + title.height() * 4; + const int32_t textWidth = 320; + const int32_t titleOffsetY = 7; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Lester Humphreys" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Producer" ), "Joe Minton" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Design Lead" ), "Jim DuBois" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Designers" ), + "Jesse King\n" + "Kris Greenia" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Programming Lead" ), "Mike White" ); + renderText( output, offsetX, offsetY, textWidth, _( "Art Director" ), "Seth Spaulding" ); + + offsetY = textInitialOffsetY; + offsetX += textWidth; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Art Lead" ), "Thomas Gale" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Artists" ), + "Michael Clarke\n" + "Michael Baker\n" + "Julie Airoldi" ); + renderText( output, offsetX, offsetY, textWidth, _( "Playtesters" ), + "Bart Simon\n" + "Fred Fredette\n" + "Rendall Koski\n" + "T.J. Andrzejczyk\n" + "Joanne Delphia" ); + + return output; + } + + fheroes2::Sprite generatePriceOfLoyaltyCreditsSecondPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); + fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); + output._disableTransformLayer(); + + const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); + const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); + + fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10, output ); + + title.set( "New World Computing", titleFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); + + const int32_t textInitialOffsetY = 35 + title.height() * 4; + const int32_t textWidth = 320; + const int32_t titleOffsetY = 7; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Designer" ), "Jon Van Caneghem" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Mark Caldwell" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Producers" ), + "Peter Ryu\n" + "Deane Rettig" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Musical Production" ), "Rob King" ); + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "QA Managers" ), + "Brian Gilmer\n" + "Peter Ryu" ); + renderText( output, offsetX, offsetY, textWidth, _( "Music" ), + "Rob King\n" + "Paul Romero\n" + "Steve Baca" ); + + offsetY = textInitialOffsetY; + offsetX += textWidth; + + offsetY += titleOffsetY + + renderText( output, offsetX, offsetY, textWidth, _( "Sound Design" ), + "Rob King\n" + "Steve Baca" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Town Themes" ), "Paul Romero" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Alto Sax" ), "Brock \"Saxman\" Summers" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Harpsichord and Piano" ), "Paul Romero" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Basso Vocal" ), "Reid Bruton" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Soprano Vocal" ), "Karin Meshagin" ); + + std::string recordedString = _( "Recorded at %{recordingStudio}" ); + StringReplace( recordedString, "%{recordingStudio}", "Green Street Studios" ); + + title.set( recordedString, titleFontType ); + title.draw( offsetX, offsetY, textWidth, output ); + + return output; + } + + fheroes2::Sprite generatePriceOfLoyaltyCreditsThirdPage() + { + fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); + fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); + output._disableTransformLayer(); + + const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); + const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); + + fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10, output ); + + title.set( "New World Computing", titleFontType ); + title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); + + const int32_t textInitialOffsetY = 35 + title.height() * 4; + const int32_t textWidth = 320; + const int32_t titleOffsetY = 7; + + int32_t offsetY = textInitialOffsetY; + int32_t offsetX = 0; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "credits|Manual" ), "Bryan Farina" ); + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "German Consultant" ), "Dr. Brock H. Summers" ); + renderText( output, offsetX, offsetY, textWidth, _( "Map Designers" ), + "Christian Vanover\n" + "Ben Bent\n" + "Tracy Iwata\n" + "Clay Ratzner\n" + "Walter Hochbrueckner\n" + "Paul Ratner" ); + + offsetY = textInitialOffsetY; + offsetX += textWidth; + + offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Package Design" ), "Rozita Tolouey" ); + renderText( output, offsetX, offsetY, textWidth, _( "Playtesters" ), + "Mikeael Herauf\n" + "Walter Johnson\n" + "David Botan\n" + "David Fernandez\n" + "Kate McClelland\n" + "William Nesemeier\n" + "Tim Lang\n" + "Pavel Vesely\n" + "John Lencioni\n" + "Jason Wildblood" ); + + return output; + } } -void Game::ShowCredits(const bool keepMainMenuBorders) +void Game::ShowCredits( const bool keepMainMenuBorders ) { - // Credits are shown in the place of Main Menu background which is correctly resized. - // We get the Main Menu background ROI to use it for credits ROI and leave borders unchanged. - const fheroes2::Sprite& mainMenuBackground = fheroes2::AGG::GetICN(ICN::HEROES, 0); - const fheroes2::Rect creditsRoi(mainMenuBackground.x(), mainMenuBackground.y(), mainMenuBackground.width(), mainMenuBackground.height()); - - // Hide mouse cursor. - const CursorRestorer cursorRestorer(false, Cursor::POINTER); - - std::unique_ptr restorer; + // Credits are shown in the place of Main Menu background which is correctly resized. + // We get the Main Menu background ROI to use it for credits ROI and leave borders unchanged. + const fheroes2::Sprite & mainMenuBackground = fheroes2::AGG::GetICN( ICN::HEROES, 0 ); + const fheroes2::Rect creditsRoi( mainMenuBackground.x(), mainMenuBackground.y(), mainMenuBackground.width(), mainMenuBackground.height() ); + + // Hide mouse cursor. + const CursorRestorer cursorRestorer( false, Cursor::POINTER ); + + std::unique_ptr restorer; - fheroes2::Display& display = fheroes2::Display::instance(); - - if (keepMainMenuBorders) { - // Make a copy of background image to restore it during fade after the credits. - restorer = std::make_unique(display, creditsRoi.x, creditsRoi.y, creditsRoi.width, creditsRoi.height); - - fheroes2::fadeOutDisplay(creditsRoi, false); - } - - AudioManager::PlayMusicAsync(MUS::VICTORY, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE); - - const uint64_t animationDelay = 50; - - std::vector pages; - pages.emplace_back(generateResurrectionCreditsFirstPage()); - pages.emplace_back(generateResurrectionCreditsSecondPage()); - pages.emplace_back(generateResurrectionCreditsThirdPage()); - - if (Settings::Get().isPriceOfLoyaltySupported()) { - pages.emplace_back(generatePriceOfLoyaltyCreditsFirstPage()); - pages.emplace_back(generatePriceOfLoyaltyCreditsSecondPage()); - pages.emplace_back(generatePriceOfLoyaltyCreditsThirdPage()); - } - - pages.emplace_back(generateSuccessionWarsCreditsFirstPage()); - pages.emplace_back(generateSuccessionWarsCreditsSecondPage()); - - // Resize the credits pages. 'creditsRoi' is made using Main Menu background parameters that were already properly calculated for the current resolution. - const int32_t resizedPageHeight = creditsRoi.width * pages.front().height() / pages.front().width(); - for (fheroes2::Sprite& page : pages) { - fheroes2::Sprite resizedPage; - resizedPage._disableTransformLayer(); - resizedPage.resize(creditsRoi.width, resizedPageHeight); - fheroes2::Resize(page, resizedPage); - page = std::move(resizedPage); - } - - fheroes2::Sprite header; - header._disableTransformLayer(); - header.resize(creditsRoi.width, creditsRoi.height - resizedPageHeight); - fheroes2::Resize(generateHeader(), header); - - AnimationSequence sequence(static_cast(pages.size())); - - bool fadeInHeader = true; - - // Immediately indicate that the delay has passed to render first frame immediately. - Game::passCustomAnimationDelay(animationDelay); - // Make sure that the first run is passed immediately. - assert(!Game::isCustomDelayNeeded(animationDelay)); - - LocalEvent& le = LocalEvent::Get(); - while (le.HandleEvents(Game::isCustomDelayNeeded(animationDelay))) { - if (le.KeyPress() || le.MouseClickLeft() || le.MouseClickMiddle() || le.MouseClickRight()) { - break; - } - - if (Game::validateCustomAnimationDelay(animationDelay)) { - if (sequence.state() == AnimationState::NO_ACTION) { - if (fadeInHeader) { - fadeInHeader = false; - } - - sequence.increment(); - continue; - } - - const uint8_t alpha = sequence.alpha(); - - if (fadeInHeader) { - fheroes2::ApplyAlpha(header, 0, 0, display, creditsRoi.x, creditsRoi.y, header.width(), header.height(), alpha); - } - - const fheroes2::Image& page = pages[sequence.pageId()]; - - if (alpha == 255) { - // This alpha is for fully bright image so there is no need to apply alpha. - Copy(page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height()); - } - else if (alpha == 0) { - // This alpha is for fully dark image so fill it with the black color. - Fill(display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), 0); - } - else { - fheroes2::ApplyAlpha(page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), alpha); - } - - display.render(); - - sequence.increment(); - } - } - - if (keepMainMenuBorders) { - fheroes2::fadeOutDisplay(creditsRoi, false); - - // Restore a copy of background image to fade it in. - restorer->restore(); - - fheroes2::fadeInDisplay(creditsRoi, false); - } - else { - fheroes2::fadeOutDisplay(); - } + fheroes2::Display & display = fheroes2::Display::instance(); + + if ( keepMainMenuBorders ) { + // Make a copy of background image to restore it during fade after the credits. + restorer = std::make_unique( display, creditsRoi.x, creditsRoi.y, creditsRoi.width, creditsRoi.height ); + + fheroes2::fadeOutDisplay( creditsRoi, false ); + } + + AudioManager::PlayMusicAsync( MUS::VICTORY, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); + + const uint64_t animationDelay = 50; + + std::vector pages; + pages.emplace_back( generateResurrectionCreditsFirstPage() ); + pages.emplace_back( generateResurrectionCreditsSecondPage() ); + pages.emplace_back( generateResurrectionCreditsThirdPage() ); + + if ( Settings::Get().isPriceOfLoyaltySupported() ) { + pages.emplace_back( generatePriceOfLoyaltyCreditsFirstPage() ); + pages.emplace_back( generatePriceOfLoyaltyCreditsSecondPage() ); + pages.emplace_back( generatePriceOfLoyaltyCreditsThirdPage() ); + } + + pages.emplace_back( generateSuccessionWarsCreditsFirstPage() ); + pages.emplace_back( generateSuccessionWarsCreditsSecondPage() ); + + // Resize the credits pages. 'creditsRoi' is made using Main Menu background parameters that were already properly calculated for the current resolution. + const int32_t resizedPageHeight = creditsRoi.width * pages.front().height() / pages.front().width(); + for ( fheroes2::Sprite & page : pages ) { + fheroes2::Sprite resizedPage; + resizedPage._disableTransformLayer(); + resizedPage.resize( creditsRoi.width, resizedPageHeight ); + fheroes2::Resize( page, resizedPage ); + page = std::move( resizedPage ); + } + + fheroes2::Sprite header; + header._disableTransformLayer(); + header.resize( creditsRoi.width, creditsRoi.height - resizedPageHeight ); + fheroes2::Resize( generateHeader(), header ); + + AnimationSequence sequence( static_cast( pages.size() ) ); + + bool fadeInHeader = true; + + // Immediately indicate that the delay has passed to render first frame immediately. + Game::passCustomAnimationDelay( animationDelay ); + // Make sure that the first run is passed immediately. + assert( !Game::isCustomDelayNeeded( animationDelay ) ); + + LocalEvent & le = LocalEvent::Get(); + while ( le.HandleEvents( Game::isCustomDelayNeeded( animationDelay ) ) ) { + if ( le.KeyPress() || le.MouseClickLeft() || le.MouseClickMiddle() || le.MouseClickRight() ) { + break; + } + + if ( Game::validateCustomAnimationDelay( animationDelay ) ) { + if ( sequence.state() == AnimationState::NO_ACTION ) { + if ( fadeInHeader ) { + fadeInHeader = false; + } + + sequence.increment(); + continue; + } + + const uint8_t alpha = sequence.alpha(); + + if ( fadeInHeader ) { + fheroes2::ApplyAlpha( header, 0, 0, display, creditsRoi.x, creditsRoi.y, header.width(), header.height(), alpha ); + } + + const fheroes2::Image & page = pages[sequence.pageId()]; + + if ( alpha == 255 ) { + // This alpha is for fully bright image so there is no need to apply alpha. + Copy( page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height() ); + } + else if ( alpha == 0 ) { + // This alpha is for fully dark image so fill it with the black color. + Fill( display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), 0 ); + } + else { + fheroes2::ApplyAlpha( page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), alpha ); + } + + display.render(); + + sequence.increment(); + } + } + + if ( keepMainMenuBorders ) { + fheroes2::fadeOutDisplay( creditsRoi, false ); + + // Restore a copy of background image to fade it in. + restorer->restore(); + + fheroes2::fadeInDisplay( creditsRoi, false ); + } + else { + fheroes2::fadeOutDisplay(); + } } From 46268db09b8b5b5f15c611e6c57d3a8dc7178d72 Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sat, 20 Jan 2024 10:16:31 +0300 Subject: [PATCH 11/12] Fix Clang-Tidy issue --- src/fheroes2/game/game_credits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index b057c20ae5f..b5530f452ed 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -58,7 +58,7 @@ namespace uint8_t * image = out.image(); const uint8_t * transform = out.transform(); - const uint8_t * imageEnd = image + out.width() * out.height(); + const uint8_t * imageEnd = image + static_cast( out.width() ) * out.height(); for ( ; image != imageEnd; ++image, ++transform ) { if ( *transform == 0 ) { From 4981b22885042da07a3f0a00805e0dfed368fcea Mon Sep 17 00:00:00 2001 From: "Sergei Ivanov (Districh)" Date: Sat, 20 Jan 2024 10:42:45 +0300 Subject: [PATCH 12/12] Revert changes in game_credits.cpp --- src/fheroes2/game/game_credits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fheroes2/game/game_credits.cpp b/src/fheroes2/game/game_credits.cpp index b5530f452ed..b057c20ae5f 100644 --- a/src/fheroes2/game/game_credits.cpp +++ b/src/fheroes2/game/game_credits.cpp @@ -58,7 +58,7 @@ namespace uint8_t * image = out.image(); const uint8_t * transform = out.transform(); - const uint8_t * imageEnd = image + static_cast( out.width() ) * out.height(); + const uint8_t * imageEnd = image + out.width() * out.height(); for ( ; image != imageEnd; ++image, ++transform ) { if ( *transform == 0 ) {