Skip to content

Commit bbdda28

Browse files
authored
Fix Editor buttons not being translated (#9557)
1 parent d4e4502 commit bbdda28

File tree

4 files changed

+75
-72
lines changed

4 files changed

+75
-72
lines changed

src/fheroes2/agg/agg_image.cpp

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -397,40 +397,14 @@ namespace
397397
return isReleasedState ? fheroes2::GetColorId( 180, 180, 180 ) : fheroes2::GetColorId( 144, 144, 144 );
398398
}
399399

400-
const char * getSupportedText( const char * text, const fheroes2::FontType font )
400+
void createNormalButton( fheroes2::Sprite & released, fheroes2::Sprite & pressed, const char * untranslatedText, const bool isEvilInterface,
401+
const int backgroundIcnId, fheroes2::Size buttonSize )
401402
{
402-
const char * translatedText = _( text );
403-
return fheroes2::isFontAvailable( translatedText, font ) ? translatedText : text;
404-
}
405-
406-
void renderTextOnButton( fheroes2::Image & releasedState, fheroes2::Image & pressedState, const char * text, const fheroes2::Point & releasedTextOffset,
407-
const fheroes2::Point & pressedTextOffset, const fheroes2::Size & buttonSize, const fheroes2::FontColor fontColor )
408-
{
409-
const fheroes2::FontType releasedFont{ fheroes2::FontSize::BUTTON_RELEASED, fontColor };
410-
const fheroes2::FontType pressedFont{ fheroes2::FontSize::BUTTON_PRESSED, fontColor };
411-
412-
const char * textSupported = getSupportedText( text, releasedFont );
413-
414-
const fheroes2::Text releasedText( textSupported, releasedFont );
415-
const fheroes2::Text pressedText( textSupported, pressedFont );
416-
417-
const fheroes2::Size releasedTextSize( releasedText.width( buttonSize.width ), releasedText.height( buttonSize.width ) );
418-
const fheroes2::Size pressedTextSize( pressedText.width( buttonSize.width ), pressedText.height( buttonSize.width ) );
419-
420-
releasedText.draw( releasedTextOffset.x, ( buttonSize.height - releasedTextSize.height ) / 2, buttonSize.width, releasedState );
421-
pressedText.draw( pressedTextOffset.x, ( buttonSize.height - pressedTextSize.height ) / 2 + 1, buttonSize.width, pressedState );
422-
}
423-
424-
void createNormalButton( fheroes2::Sprite & released, fheroes2::Sprite & pressed, const char * text, const bool isEvilInterface, const int backgroundIcnId,
425-
fheroes2::Size buttonSize )
426-
{
427-
fheroes2::Point releasedOffset;
428-
fheroes2::Point pressedOffset;
429-
fheroes2::getCustomNormalButton( released, pressed, isEvilInterface, buttonSize, releasedOffset, pressedOffset, backgroundIcnId );
430-
403+
// TODO: do not do translations for button generation. We shouldn't assume that we receive a non-translated string.
431404
const fheroes2::FontColor buttonFontColor = isEvilInterface ? fheroes2::FontColor::GRAY : fheroes2::FontColor::WHITE;
405+
const char * text = fheroes2::getSupportedText( untranslatedText, fheroes2::FontType{ fheroes2::FontSize::BUTTON_RELEASED, buttonFontColor } );
432406

433-
renderTextOnButton( released, pressed, text, releasedOffset, pressedOffset, buttonSize, buttonFontColor );
407+
fheroes2::makeButtonSprites( released, pressed, text, buttonSize, isEvilInterface, backgroundIcnId );
434408
}
435409

436410
void createCampaignButtonSet( const int campaignSetIcnId, const std::array<const char *, 5> & texts )
@@ -1610,8 +1584,8 @@ namespace
16101584
// Town and Castle buttons must have the same width.
16111585
// This is why we need to calculate text width for both buttons and then create a button with a needed width.
16121586
const fheroes2::FontType releasedFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE };
1613-
const int32_t townTextWidth = fheroes2::Text{ getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width();
1614-
const int32_t castleTextWidth = fheroes2::Text{ getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width();
1587+
const int32_t townTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width();
1588+
const int32_t castleTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width();
16151589

16161590
// Normal button width is 80 pixels so if the overall length is smaller than 80 then set the default value.
16171591
const int32_t width = std::max( 80, std::max( townTextWidth, castleTextWidth ) );
@@ -1628,8 +1602,8 @@ namespace
16281602
// Town and Castle buttons must have the same width.
16291603
// This is why we need to calculate text width for both buttons and then create a button with a needed width.
16301604
const fheroes2::FontType releasedFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE };
1631-
const int32_t townTextWidth = fheroes2::Text{ getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width();
1632-
const int32_t castleTextWidth = fheroes2::Text{ getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width();
1605+
const int32_t townTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width();
1606+
const int32_t castleTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width();
16331607

16341608
// Normal button width is 80 pixels so if the overall length is smaller than 80 then set the default value.
16351609
const int32_t width = std::max( 80, std::max( townTextWidth, castleTextWidth ) );
@@ -1822,7 +1796,9 @@ namespace
18221796

18231797
const ButtonFontOffsetRestorer fontRestorerReleased( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], -1 );
18241798
const ButtonFontOffsetRestorer fontRestorerPressed( _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], -1 );
1825-
renderTextOnButton( _icnVsSprite[id][0], _icnVsSprite[id][1], buttonText, { 3, 4 }, { 2, 5 }, { 23, 133 }, fheroes2::FontColor::WHITE );
1799+
1800+
const char * translatedText = fheroes2::getSupportedText( buttonText, fheroes2::FontType{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE } );
1801+
fheroes2::renderTextOnButton( _icnVsSprite[id][0], _icnVsSprite[id][1], translatedText, { 3, 4 }, { 2, 5 }, { 23, 133 }, fheroes2::FontColor::WHITE );
18261802

18271803
break;
18281804
}

src/fheroes2/editor/editor_interface.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,10 +1174,15 @@ namespace Interface
11741174
fheroes2::StandardWindow::Padding::CENTER_LEFT );
11751175
background.renderButton( buttonQuit, isEvilInterface ? ICN::BUTTON_QUIT_EVIL : ICN::BUTTON_QUIT_GOOD, 0, 1, { buttonOffsets.x, buttonOffsets.y },
11761176
fheroes2::StandardWindow::Padding::CENTER_RIGHT );
1177-
background.renderButtonSprite( buttonMainMenu, gettext_noop( "MAIN\nMENU" ), { buttonSave.area().width - 10, buttonSave.area().height }, { 0, buttonOffsets.y },
1178-
isEvilInterface, fheroes2::StandardWindow::Padding::CENTER_CENTER );
1179-
background.renderButtonSprite( buttonPlayMap, gettext_noop( "START\nMAP" ), { buttonSave.area().width - 10, buttonSave.area().height },
1180-
{ buttonOffsets.x, buttonOffsets.y }, isEvilInterface, fheroes2::StandardWindow::Padding::TOP_RIGHT );
1177+
1178+
const fheroes2::FontType releasedButtonFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE };
1179+
1180+
background.renderButtonSprite( buttonMainMenu, fheroes2::getSupportedText( gettext_noop( "MAIN\nMENU" ), releasedButtonFont ),
1181+
{ buttonSave.area().width - 10, buttonSave.area().height }, { 0, buttonOffsets.y }, isEvilInterface,
1182+
fheroes2::StandardWindow::Padding::CENTER_CENTER );
1183+
background.renderButtonSprite( buttonPlayMap, fheroes2::getSupportedText( gettext_noop( "START\nMAP" ), releasedButtonFont ),
1184+
{ buttonSave.area().width - 10, buttonSave.area().height }, { buttonOffsets.x, buttonOffsets.y }, isEvilInterface,
1185+
fheroes2::StandardWindow::Padding::TOP_RIGHT );
11811186
background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 },
11821187
fheroes2::StandardWindow::Padding::BOTTOM_CENTER );
11831188

src/fheroes2/gui/ui_button.cpp

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ namespace fheroes2
734734
void makeTransparentBackground( const Sprite & released, Sprite & pressed, const int backgroundIcnID )
735735
{
736736
// We need to copy the background image to pressed button only where it does not overlay the image of released button.
737-
const fheroes2::Sprite & background = fheroes2::AGG::GetICN( backgroundIcnID, 0 );
737+
const Sprite & background = AGG::GetICN( backgroundIcnID, 0 );
738738
// you are trying to apply transform on an image that is single-layered
739739
assert( !pressed.singleLayer() && !released.singleLayer() );
740740
const uint8_t * releasedTransform = released.transform();
@@ -778,7 +778,7 @@ namespace fheroes2
778778
ButtonSprite makeButtonWithShadow( int32_t offsetX, int32_t offsetY, const Sprite & released, const Sprite & pressed, const Image & background,
779779
const Point & shadowOffset )
780780
{
781-
const Sprite & shadow = fheroes2::makeShadow( released, shadowOffset, 3 );
781+
const Sprite & shadow = makeShadow( released, shadowOffset, 3 );
782782

783783
Sprite croppedBackground = Crop( background, offsetX + shadow.x(), offsetY + shadow.y(), shadow.width(), shadow.height() );
784784
Blit( shadow, croppedBackground );
@@ -837,28 +837,28 @@ namespace fheroes2
837837
}
838838
}
839839

840-
void getTextAdaptedSprite( Sprite & released, Sprite & pressed, const char * text, const int emptyButtonIcnID, const int buttonBackgroundIcnID )
840+
void getTextAdaptedSprite( Sprite & released, Sprite & pressed, const char * untranslatedText, const int emptyButtonIcnID, const int buttonBackgroundIcnID )
841841
{
842-
fheroes2::FontColor buttonFont = fheroes2::FontColor::WHITE;
843-
fheroes2::Point textAreaMargins = { 0, 3 };
842+
FontColor buttonFont = FontColor::WHITE;
843+
Point textAreaMargins = { 0, 3 };
844844

845-
fheroes2::Size minimumTextArea = { 0, 15 };
846-
fheroes2::Size maximumTextArea = { 200, 200 }; // Why is such a wide button needed?
845+
Size minimumTextArea = { 0, 15 };
846+
Size maximumTextArea = { 200, 200 }; // Why is such a wide button needed?
847847

848-
fheroes2::Size backgroundBorders = { 0, 7 };
848+
Size backgroundBorders = { 0, 7 };
849849

850-
fheroes2::Point releasedOffset;
851-
fheroes2::Point pressedOffset;
850+
Point releasedOffset;
851+
Point pressedOffset;
852852

853853
getButtonSpecificValues( emptyButtonIcnID, buttonFont, textAreaMargins, minimumTextArea, maximumTextArea, backgroundBorders, releasedOffset, pressedOffset );
854854

855-
const fheroes2::FontType releasedButtonFont{ fheroes2::FontSize::BUTTON_RELEASED, buttonFont };
855+
const FontType releasedButtonFont{ FontSize::BUTTON_RELEASED, buttonFont };
856856

857-
const char * translatedText = _( text );
858-
const char * supportedText = fheroes2::isFontAvailable( translatedText, releasedButtonFont ) ? translatedText : text;
857+
// TODO: do not do translations for button generation. We shouldn't assume that we receive a non-translated string.
858+
const char * supportedText = getSupportedText( untranslatedText, releasedButtonFont );
859859

860-
const fheroes2::Text releasedText( supportedText, releasedButtonFont );
861-
const fheroes2::Text pressedText( supportedText, { fheroes2::FontSize::BUTTON_PRESSED, buttonFont } );
860+
const Text releasedText( supportedText, releasedButtonFont );
861+
const Text pressedText( supportedText, { FontSize::BUTTON_PRESSED, buttonFont } );
862862

863863
// We need to pass an argument to width() so that it correctly accounts for multi-lined texts.
864864
const int32_t textWidth = releasedText.width( maximumTextArea.width );
@@ -879,10 +879,12 @@ namespace fheroes2
879879
const int32_t borderedTextHeight = textHeight + textAreaMargins.y;
880880
const int32_t textAreaHeight = std::clamp( borderedTextHeight, minimumTextArea.height, maximumTextArea.height );
881881

882-
assert( textAreaHeight + backgroundBorders.height > 0 );
882+
const Size buttonSize( textAreaWidth + backgroundBorders.width, textAreaHeight + backgroundBorders.height );
883883

884-
released = resizeButton( AGG::GetICN( emptyButtonIcnID, 0 ), { textAreaWidth + backgroundBorders.width, textAreaHeight + backgroundBorders.height } );
885-
pressed = resizeButton( AGG::GetICN( emptyButtonIcnID, 1 ), { textAreaWidth + backgroundBorders.width, textAreaHeight + backgroundBorders.height } );
884+
assert( buttonSize.height > 0 );
885+
886+
released = resizeButton( AGG::GetICN( emptyButtonIcnID, 0 ), buttonSize );
887+
pressed = resizeButton( AGG::GetICN( emptyButtonIcnID, 1 ), buttonSize );
886888

887889
if ( buttonBackgroundIcnID != ICN::UNKNOWN ) {
888890
makeTransparentBackground( released, pressed, buttonBackgroundIcnID );
@@ -891,27 +893,38 @@ namespace fheroes2
891893
addButtonShine( released, emptyButtonIcnID );
892894
}
893895

894-
const fheroes2::Size releasedTextSize( releasedText.width( textAreaWidth ), releasedText.height( textAreaWidth ) );
895-
const fheroes2::Size pressedTextSize( pressedText.width( textAreaWidth ), pressedText.height( textAreaWidth ) );
896-
897896
// The button font letters are all shifted 1 pixel to the left due to shadows, so we have to add 1 to the x position when drawing
898897
// to properly center-align.
899-
releasedText.draw( releasedOffset.x + 1, releasedOffset.y + ( textAreaHeight - releasedTextSize.height ) / 2, textAreaWidth, released );
900-
pressedText.draw( pressedOffset.x + 1, pressedOffset.y + ( textAreaHeight - pressedTextSize.height ) / 2, textAreaWidth, pressed );
898+
releasedText.draw( releasedOffset.x + 1, releasedOffset.y + ( textAreaHeight - textHeight ) / 2, textAreaWidth, released );
899+
pressedText.draw( pressedOffset.x + 1, pressedOffset.y + ( textAreaHeight - textHeight ) / 2, textAreaWidth, pressed );
901900
}
902901

903902
void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const Size buttonSize, const bool isEvilInterface, const int backgroundIcnId )
904903
{
905-
fheroes2::Point releasedOffset;
906-
fheroes2::Point pressedOffset;
907-
fheroes2::getCustomNormalButton( released, pressed, isEvilInterface, buttonSize, releasedOffset, pressedOffset, backgroundIcnId );
904+
Point releasedOffset;
905+
Point pressedOffset;
906+
getCustomNormalButton( released, pressed, isEvilInterface, buttonSize, releasedOffset, pressedOffset, backgroundIcnId );
907+
908+
const fheroes2::FontColor buttonFontColor = isEvilInterface ? fheroes2::FontColor::GRAY : fheroes2::FontColor::WHITE;
909+
renderTextOnButton( released, pressed, text, releasedOffset, pressedOffset, buttonSize, buttonFontColor );
910+
}
911+
912+
const char * getSupportedText( const char * untranslatedText, const FontType font )
913+
{
914+
const char * translatedText = _( untranslatedText );
915+
return isFontAvailable( translatedText, font ) ? translatedText : untranslatedText;
916+
}
908917

909-
const fheroes2::FontColor fontColor = isEvilInterface ? fheroes2::FontColor::GRAY : fheroes2::FontColor::WHITE;
918+
void renderTextOnButton( Image & releasedState, Image & pressedState, const std::string & text, const Point & releasedTextOffset, const Point & pressedTextOffset,
919+
const Size & buttonSize, const FontColor fontColor )
920+
{
921+
const FontType releasedFont{ FontSize::BUTTON_RELEASED, fontColor };
922+
const FontType pressedFont{ FontSize::BUTTON_PRESSED, fontColor };
910923

911-
const fheroes2::Text releasedText( text, { fheroes2::FontSize::BUTTON_RELEASED, fontColor } );
912-
const fheroes2::Text pressedText( text, { fheroes2::FontSize::BUTTON_PRESSED, fontColor } );
924+
const Text releasedText( text, releasedFont );
925+
const Text pressedText( text, pressedFont );
913926

914-
releasedText.draw( releasedOffset.x, ( buttonSize.height - releasedText.height( buttonSize.width ) ) / 2, buttonSize.width, released );
915-
pressedText.draw( pressedOffset.x, ( buttonSize.height - pressedText.height( buttonSize.width ) ) / 2 + 1, buttonSize.width, pressed );
927+
releasedText.draw( releasedTextOffset.x, ( buttonSize.height - releasedText.height( buttonSize.width ) ) / 2, buttonSize.width, releasedState );
928+
pressedText.draw( pressedTextOffset.x, ( buttonSize.height - pressedText.height( buttonSize.width ) ) / 2 + 1, buttonSize.width, pressedState );
916929
}
917930
}

src/fheroes2/gui/ui_button.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535

3636
namespace fheroes2
3737
{
38+
enum class FontColor : uint8_t;
39+
struct FontType;
40+
3841
// An abstract class for button usage
3942
class ButtonBase : public ActionObject
4043
{
@@ -352,8 +355,14 @@ namespace fheroes2
352355

353356
// Generates released and pressed button sprites with the width and height necessary to fit a provided text using an empty button template ICN and a chosen background
354357
// ICN.
355-
void getTextAdaptedSprite( Sprite & released, Sprite & pressed, const char * text, const int icnId, const int buttonBackgroundIcnID );
358+
void getTextAdaptedSprite( Sprite & released, Sprite & pressed, const char * untranslatedText, const int icnId, const int buttonBackgroundIcnID );
356359

357360
// Generate custom-size released and pressed button sprites with text on them over a chosen background ICN.
358361
void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const Size buttonSize, const bool isEvilInterface, const int backgroundIcnId );
362+
363+
// TODO: find a better place where to put this function.
364+
const char * getSupportedText( const char * untranslatedText, const FontType font );
365+
366+
void renderTextOnButton( Image & releasedState, Image & pressedState, const std::string & text, const Point & releasedTextOffset, const Point & pressedTextOffset,
367+
const Size & buttonSize, const FontColor fontColor );
359368
}

0 commit comments

Comments
 (0)