Skip to content

Commit

Permalink
Use drawOnState() for buttons precessing and cache buttons' position …
Browse files Browse the repository at this point in the history
…for event handler loop (#9223)
  • Loading branch information
Districh-ru authored Dec 5, 2024
1 parent 0a28c04 commit db8136f
Show file tree
Hide file tree
Showing 53 changed files with 703 additions and 578 deletions.
5 changes: 5 additions & 0 deletions src/engine/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,11 @@ namespace fheroes2
Blit( in, 0, 0, out, 0, 0, in.width(), in.height(), flip );
}

void Blit( const Image & in, Image & out, const Rect & outRoi, const bool flip /* = false */ )
{
Blit( in, 0, 0, out, outRoi.x, outRoi.y, outRoi.width, outRoi.height, flip );
}

void Blit( const Image & in, Image & out, int32_t outX, int32_t outY, const bool flip /* = false */ )
{
Blit( in, 0, 0, out, outX, outY, in.width(), in.height(), flip );
Expand Down
1 change: 1 addition & 0 deletions src/engine/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ namespace fheroes2

// draw one image onto another
void Blit( const Image & in, Image & out, const bool flip = false );
void Blit( const Image & in, Image & out, const Rect & outRoi, const bool flip = false );
void Blit( const Image & in, Image & out, int32_t outX, int32_t outY, const bool flip = false );
void Blit( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool flip = false );

Expand Down
104 changes: 68 additions & 36 deletions src/fheroes2/battle/battle_dialogs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,15 @@ namespace

const fheroes2::Point buttonOffset( 112 + pos_rt.x, 362 + pos_rt.y );
fheroes2::Button buttonOkay( buttonOffset.x, buttonOffset.y, isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD, 0, 1 );

buttonOkay.draw();

RedrawBattleSettings( optionAreas );

display.render();

while ( le.HandleEvents() ) {
le.isMouseLeftButtonPressedInArea( buttonOkay.area() ) ? buttonOkay.drawOnPress() : buttonOkay.drawOnRelease();
buttonOkay.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOkay.area() ) );

bool redrawScreen = false;

Expand Down Expand Up @@ -336,15 +337,16 @@ namespace
else if ( le.MouseClickLeft( optionAreas[6] ) ) {
return DialogAction::AudioSettings;
}

if ( le.MouseClickLeft( optionAreas[7] ) ) {
return DialogAction::HotKeys;
}

if ( le.MouseClickLeft( optionAreas[8] ) ) {
conf.setBattleDamageInfo( !conf.isBattleShowDamageInfoEnabled() );
redrawScreen = true;
}

if ( le.isMouseRightButtonPressedInArea( optionAreas[0] ) ) {
else if ( le.isMouseRightButtonPressedInArea( optionAreas[0] ) ) {
fheroes2::showStandardTextMessage( _( "Speed" ), _( "Set the speed of combat actions and animations." ), 0 );
}
else if ( le.isMouseRightButtonPressedInArea( optionAreas[1] ) ) {
Expand Down Expand Up @@ -661,14 +663,16 @@ bool Battle::Arena::DialogBattleSummary( const Result & res, const std::vector<A
int sequenceId = sequence.id();

while ( le.HandleEvents() ) {
le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ? buttonOk.drawOnPress() : buttonOk.drawOnRelease();
buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) );

if ( allowToRestart ) {
le.isMouseLeftButtonPressedInArea( buttonRestart->area() ) ? buttonRestart->drawOnPress() : buttonRestart->drawOnRelease();
buttonRestart->drawOnState( le.isMouseLeftButtonPressedInArea( buttonRestart->area() ) );
}

if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( buttonOk.area() ) ) {
break;
}

if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) {
fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to leave the battle results." ), Dialog::ZERO );
}
Expand Down Expand Up @@ -697,6 +701,11 @@ bool Battle::Arena::DialogBattleSummary( const Result & res, const std::vector<A
}
}

// Free memory because RESTART button is not used more.
if ( allowToRestart ) {
buttonRestart.reset();
}

if ( !artifacts.empty() ) {
const HeroBase * winner = ( res.army1 & RESULT_WINS ? _army1->GetCommander() : ( res.army2 & RESULT_WINS ? _army2->GetCommander() : nullptr ) );
const HeroBase * loser = ( res.army1 & RESULT_LOSS ? _army1->GetCommander() : ( res.army2 & RESULT_LOSS ? _army2->GetCommander() : nullptr ) );
Expand Down Expand Up @@ -790,7 +799,7 @@ bool Battle::Arena::DialogBattleSummary( const Result & res, const std::vector<A
}

while ( le.HandleEvents() ) {
le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ? buttonOk.drawOnPress() : buttonOk.drawOnRelease();
buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) );

// Display captured artifact info on right click
if ( le.isMouseRightButtonPressedInArea( artifactArea ) ) {
Expand All @@ -799,9 +808,11 @@ bool Battle::Arena::DialogBattleSummary( const Result & res, const std::vector<A
else if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) {
break;
}
else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) {

if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) {
fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), Dialog::ZERO );
}

// Animation
if ( Game::validateAnimationDelay( Game::BATTLE_DIALOG_DELAY ) && !sequence.nextFrame() ) {
if ( sequenceId != sequence.id() ) {
Expand Down Expand Up @@ -886,13 +897,14 @@ void Battle::Arena::DialogBattleNecromancy( const uint32_t raiseCount )
const int buttonOffset = 121;
const int buttonICN = isEvilInterface ? ICN::BUTTON_SMALLER_OKAY_EVIL : ICN::BUTTON_SMALLER_OKAY_GOOD;
fheroes2::Button buttonOk( renderArea.x + buttonOffset, renderArea.y + 410, buttonICN, 0, 1 );

buttonOk.draw();

display.render();

LocalEvent & le = LocalEvent::Get();
while ( le.HandleEvents() ) {
le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ? buttonOk.drawOnPress() : buttonOk.drawOnRelease();
buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) );

// exit
if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( buttonOk.area() ) )
Expand Down Expand Up @@ -1011,38 +1023,52 @@ int Battle::Arena::DialogBattleHero( HeroBase & hero, const bool buttons, Status
btnSurrender.disable();
}

if ( !buttons ) {
btnClose.disable();
}

btnCast.draw();
btnRetreat.draw();
btnSurrender.draw();
btnClose.draw();

int result = 0;

display.render( pos_rt );
LocalEvent & le = LocalEvent::Get();

// The Hero Screen is available for a Hero only (not Captain) and only when the corresponding player has a turn.
Heroes * heroForHeroScreen = ( currentColor == hero.GetColor() ) ? dynamic_cast<Heroes *>( &hero ) : nullptr;
if ( !buttons ) {
// This is a case when this dialog was called by the right mouse button press.

std::string statusMessage = _( "Hero's Options" );
btnClose.disable();
btnClose.draw();

LocalEvent & le = LocalEvent::Get();
while ( le.HandleEvents() && !result ) {
btnCast.isEnabled() && le.isMouseLeftButtonPressedInArea( btnCast.area() ) ? btnCast.drawOnPress() : btnCast.drawOnRelease();
btnRetreat.isEnabled() && le.isMouseLeftButtonPressedInArea( btnRetreat.area() ) ? btnRetreat.drawOnPress() : btnRetreat.drawOnRelease();
btnSurrender.isEnabled() && le.isMouseLeftButtonPressedInArea( btnSurrender.area() ) ? btnSurrender.drawOnPress() : btnSurrender.drawOnRelease();
le.isMouseLeftButtonPressedInArea( btnClose.area() ) ? btnClose.drawOnPress() : btnClose.drawOnRelease();
display.render( pos_rt );

if ( !buttons ) {
while ( le.HandleEvents() ) {
if ( !le.isMouseRightButtonPressed() ) {
break;
}
}

return result;
}

btnClose.draw();

display.render( pos_rt );

// The Hero Screen is available for a Hero only (not Captain) and only when the corresponding player has a turn.
Heroes * heroForHeroScreen = ( currentColor == hero.GetColor() ) ? dynamic_cast<Heroes *>( &hero ) : nullptr;

continue;
std::string statusMessage = _( "Hero's Options" );

while ( le.HandleEvents() && !result ) {
if ( btnCast.isEnabled() ) {
btnCast.drawOnState( le.isMouseLeftButtonPressedInArea( btnCast.area() ) );
}
if ( btnRetreat.isEnabled() ) {
btnRetreat.drawOnState( le.isMouseLeftButtonPressedInArea( btnRetreat.area() ) );
}
if ( btnSurrender.isEnabled() ) {
btnSurrender.drawOnState( le.isMouseLeftButtonPressedInArea( btnSurrender.area() ) );
}

btnClose.drawOnState( le.isMouseLeftButtonPressedInArea( btnClose.area() ) );

// The Cast Spell is available for a hero and a captain.
if ( le.isMouseCursorPosInArea( btnCast.area() ) && currentColor == hero.GetColor() ) {
Expand Down Expand Up @@ -1131,8 +1157,12 @@ int Battle::Arena::DialogBattleHero( HeroBase & hero, const bool buttons, Status

bool Battle::DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdom & kingdom )
{
if ( kingdom.GetColor() == hero.GetColor() ) // this is weird. You're surrending to yourself!
if ( kingdom.GetColor() == hero.GetColor() ) {
// This is weird. You're surrendering to yourself!
assert( 0 );

return false;
}

fheroes2::Display & display = fheroes2::Display::instance();
LocalEvent & le = LocalEvent::Get();
Expand Down Expand Up @@ -1181,16 +1211,15 @@ bool Battle::DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdo
btnAccept.draw();
btnDecline.draw();

const auto drawGoldMsg = [cost, &kingdom, &btnAccept]() {
const auto drawGoldMsg = [cost, &kingdom, &display]( const fheroes2::Rect & btnAcceptArea ) {
std::string str = _( "Not enough gold (%{gold})" );

StringReplace( str, "%{gold}", cost - kingdom.GetFunds().gold );

const fheroes2::Text text( str, fheroes2::FontType::smallWhite() );
const fheroes2::Rect rect = btnAccept.area();

// Since button area includes 3D effect on the left side we need to shift the text by X axis to center it in relation to the button.
text.draw( rect.x + ( rect.width - text.width() ) / 2 + 2, rect.y - 13, fheroes2::Display::instance() );
text.draw( btnAcceptArea.x + ( btnAcceptArea.width - text.width() ) / 2 + 2, btnAcceptArea.y - 13, display );
};

const int icn = isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR;
Expand All @@ -1213,20 +1242,23 @@ bool Battle::DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdo
fheroes2::ImageRestorer back( display, pos_rt.x, pos_rt.y, pos_rt.width, pos_rt.height );

if ( !kingdom.AllowPayment( Funds( Resource::GOLD, cost ) ) ) {
drawGoldMsg();
drawGoldMsg( btnAccept.area() );
}

display.render();

bool result = false;

while ( le.HandleEvents() && !result ) {
if ( btnAccept.isEnabled() )
le.isMouseLeftButtonPressedInArea( btnAccept.area() ) ? btnAccept.drawOnPress() : btnAccept.drawOnRelease();
le.isMouseLeftButtonPressedInArea( btnDecline.area() ) ? btnDecline.drawOnPress() : btnDecline.drawOnRelease();
if ( btnAccept.isEnabled() ) {
btnAccept.drawOnState( le.isMouseLeftButtonPressedInArea( btnAccept.area() ) );
}

btnDecline.drawOnState( le.isMouseLeftButtonPressedInArea( btnDecline.area() ) );

if ( btnMarket.isEnabled() )
le.isMouseLeftButtonPressedInArea( btnMarket.area() ) ? btnMarket.drawOnPress() : btnMarket.drawOnRelease();
if ( btnMarket.isEnabled() ) {
btnMarket.drawOnState( le.isMouseLeftButtonPressedInArea( btnMarket.area() ) );
}

if ( btnAccept.isEnabled() && ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( btnAccept.area() ) ) ) {
result = true;
Expand All @@ -1243,7 +1275,7 @@ bool Battle::DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdo
else {
btnAccept.disable();

drawGoldMsg();
drawGoldMsg( btnAccept.area() );
}

btnAccept.draw();
Expand Down
Loading

0 comments on commit db8136f

Please sign in to comment.