Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add return to main menu and play map buttons to the editor #9512

Merged
merged 48 commits into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3859f65
Add Main Menu button to editor's file options dialog
zenseii Jan 29, 2025
d2d8b26
Code style and right click info
zenseii Jan 29, 2025
69ba7c2
Fix equal conditional branches
zenseii Jan 29, 2025
ed5d686
IWYU, change confirm dialog header
zenseii Jan 29, 2025
c93771d
Make the buttons aligned horizontally
zenseii Jan 30, 2025
07970f6
Add play map button
zenseii Jan 30, 2025
b403bf1
early returns and tidying
zenseii Jan 30, 2025
e81d8ff
Add Play Map button, restorer for save dialog
zenseii Jan 30, 2025
0e9e4a7
clang tidy
zenseii Jan 30, 2025
8c86d1e
Fix fade-in when PLAY MAP is pressed
Districh-ru Jan 31, 2025
1bc62ce
Update copyright
Districh-ru Jan 31, 2025
74276b0
Add background restorer to StandardWindow
zenseii Feb 3, 2025
5e1f9c8
Tidy dialog, fix dimensions of the new buttons
zenseii Feb 3, 2025
2d4ba8f
restore background when saving
zenseii Feb 6, 2025
d3273a2
Fix Main menu button placement
zenseii Feb 6, 2025
0b91121
Add right click info for play map
zenseii Feb 6, 2025
8e7d7b5
Add save dialog tree
zenseii Feb 6, 2025
d920c6f
make equal distance between buttons
zenseii Feb 6, 2025
251e15f
text consistency
zenseii Feb 7, 2025
bab2e4b
Add necessary changes from button reworking. NOTE!
zenseii Feb 8, 2025
89cf8a6
remove unused roi
zenseii Feb 8, 2025
b04cc1b
fix wrong semicolon
zenseii Feb 8, 2025
de6d07c
Merge remote-tracking branch 'upstream/master' into return-to-main-me…
zenseii Feb 8, 2025
d484218
copyright year
zenseii Feb 8, 2025
9c99a19
Change to start map
zenseii Feb 8, 2025
3c7d519
IWYU
zenseii Feb 8, 2025
457b347
parity with changes from button rework pr
zenseii Feb 8, 2025
ace95f2
Paraphrase right-click info
zenseii Feb 8, 2025
2286ef7
Merge branch 'master' into return-to-main-menu-from-editor
zenseii Feb 9, 2025
8e2d8ea
code style
zenseii Feb 9, 2025
5ed098c
Code style and update method descriptions
zenseii Feb 9, 2025
17cbfa5
add new restore method to file dialog
zenseii Feb 9, 2025
e88c7a4
copyright year
zenseii Feb 9, 2025
7c3ac9a
remove unused variables
zenseii Feb 9, 2025
d06859d
move conf calls to right before use
zenseii Feb 9, 2025
b62b055
move button initiations and calls for consistency
zenseii Feb 9, 2025
53859c9
remove unnecessary render call
zenseii Feb 9, 2025
08e9536
IWYU
zenseii Feb 9, 2025
0d696bf
grammar fix for comment
zenseii Feb 9, 2025
4226cd6
address comments, rename hideWindow
zenseii Feb 9, 2025
892520e
clang tidy and copyright year
zenseii Feb 9, 2025
0622cd6
revert wrong identifier changes
zenseii Feb 9, 2025
9c6d82e
fix copyright years
zenseii Feb 9, 2025
b4aed6f
fix dialog showing
zenseii Feb 9, 2025
e358d8c
make const
zenseii Feb 9, 2025
7c06d96
Fix
zenseii Feb 9, 2025
5c4db15
simplify
zenseii Feb 9, 2025
2f6ad97
add a display render
zenseii Feb 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 2 additions & 11 deletions src/fheroes2/dialog/dialog_file.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2019 - 2024 *
* Copyright (C) 2019 - 2025 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <[email protected]> *
Expand Down Expand Up @@ -29,13 +29,11 @@
#include "game_interface.h"
#include "game_mode.h"
#include "icn.h"
#include "image.h"
#include "localevent.h"
#include "screen.h"
#include "settings.h"
#include "translations.h"
#include "ui_button.h"
#include "ui_constants.h"
#include "ui_dialog.h"
#include "ui_window.h"

Expand All @@ -48,13 +46,6 @@ namespace

fheroes2::Display & display = fheroes2::Display::instance();

const int32_t totalDialogWidth = 337;
const int32_t totalDialogHeight = 252;

// Prepare restorer of the adventure map when save feedback dialog is shown.
fheroes2::ImageRestorer back( display, ( display.width() - totalDialogWidth - fheroes2::borderWidthPx ) / 2,
( display.height() - totalDialogHeight + fheroes2::borderWidthPx ) / 2, totalDialogWidth, totalDialogHeight );

fheroes2::StandardWindow background( 289, 204, true, display );

fheroes2::Button buttonNew;
Expand Down Expand Up @@ -107,7 +98,7 @@ namespace
}
else if ( le.MouseClickLeft( buttonSave.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) {
// Special case: since we show a window about file saving we don't want to display the current dialog anymore.
back.restore();
background.hideWindow();

return Interface::AdventureMap::Get().EventSaveGame();
}
Expand Down
136 changes: 90 additions & 46 deletions src/fheroes2/editor/editor_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include <string>
#include <vector>

#include "agg_image.h"
#include "artifact.h"
#include "audio_manager.h"
#include "color.h"
Expand All @@ -55,7 +54,6 @@
#include "heroes.h"
#include "history_manager.h"
#include "icn.h"
#include "image.h"
#include "interface_base.h"
#include "interface_border.h"
#include "interface_gamearea.h"
Expand Down Expand Up @@ -86,6 +84,7 @@
#include "ui_map_object.h"
#include "ui_text.h"
#include "ui_tool.h"
#include "ui_window.h"
#include "view_world.h"
#include "world.h"
#include "world_object_uid.h"
Expand Down Expand Up @@ -1149,35 +1148,40 @@ namespace Interface

fheroes2::GameMode EditorInterface::eventFileDialog()
{
const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled();
const int cpanbkg = isEvilInterface ? ICN::CPANBKGE : ICN::CPANBKG;
const fheroes2::Sprite & background = fheroes2::AGG::GetICN( cpanbkg, 0 );

const CursorRestorer cursorRestorer( true, Cursor::POINTER );

fheroes2::Display & display = fheroes2::Display::instance();

// Since the original image contains shadow it is important to remove it from calculation of window's position.
const fheroes2::Point rb( ( display.width() - background.width() - fheroes2::borderWidthPx ) / 2,
( display.height() - background.height() + fheroes2::borderWidthPx ) / 2 );
fheroes2::ImageRestorer back( display, rb.x, rb.y, background.width(), background.height() );
fheroes2::Blit( background, display, rb.x, rb.y );

fheroes2::Button buttonNew( rb.x + 62, rb.y + 31, isEvilInterface ? ICN::BUTTON_NEW_MAP_EVIL : ICN::BUTTON_NEW_MAP_GOOD, 0, 1 );
fheroes2::Button buttonLoad( rb.x + 195, rb.y + 31, isEvilInterface ? ICN::BUTTON_LOAD_MAP_EVIL : ICN::BUTTON_LOAD_MAP_GOOD, 0, 1 );
fheroes2::Button buttonSave( rb.x + 62, rb.y + 107, isEvilInterface ? ICN::BUTTON_SAVE_MAP_EVIL : ICN::BUTTON_SAVE_MAP_GOOD, 0, 1 );
fheroes2::Button buttonQuit( rb.x + 195, rb.y + 107, isEvilInterface ? ICN::BUTTON_QUIT_EVIL : ICN::BUTTON_QUIT_GOOD, 0, 1 );
fheroes2::Button buttonCancel( rb.x + 128, rb.y + 184, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1 );

buttonNew.draw();
buttonLoad.draw();
buttonSave.draw();
buttonQuit.draw();
buttonCancel.draw();

display.render( back.rect() );

fheroes2::GameMode result = fheroes2::GameMode::CANCEL;
fheroes2::StandardWindow background( 418 - fheroes2::borderWidthPx * 2, 236 - fheroes2::borderWidthPx * 2, true, display );

fheroes2::Button buttonNew;
fheroes2::Button buttonLoad;
fheroes2::Button buttonSave;
fheroes2::Button buttonQuit;
fheroes2::ButtonSprite buttonMainMenu;
fheroes2::ButtonSprite buttonPlayMap;
fheroes2::Button buttonCancel;

const Settings & conf = Settings::Get();
const bool isEvilInterface = conf.isEvilInterfaceEnabled();

const fheroes2::Point buttonOffsets = { 30, 15 };
background.renderButton( buttonNew, isEvilInterface ? ICN::BUTTON_NEW_MAP_EVIL : ICN::BUTTON_NEW_MAP_GOOD, 0, 1, buttonOffsets,
fheroes2::StandardWindow::Padding::TOP_LEFT );
background.renderButton( buttonLoad, isEvilInterface ? ICN::BUTTON_LOAD_MAP_EVIL : ICN::BUTTON_LOAD_MAP_GOOD, 0, 1, { 0, buttonOffsets.y },
fheroes2::StandardWindow::Padding::TOP_CENTER );
background.renderButton( buttonSave, isEvilInterface ? ICN::BUTTON_SAVE_MAP_EVIL : ICN::BUTTON_SAVE_MAP_GOOD, 0, 1, { buttonOffsets.x, buttonOffsets.y },
fheroes2::StandardWindow::Padding::CENTER_LEFT );
background.renderButton( buttonQuit, isEvilInterface ? ICN::BUTTON_QUIT_EVIL : ICN::BUTTON_QUIT_GOOD, 0, 1, { buttonOffsets.x, buttonOffsets.y },
fheroes2::StandardWindow::Padding::CENTER_RIGHT );
background.renderButtonSprite( buttonMainMenu, gettext_noop( "MAIN\nMENU" ), { buttonSave.area().width - 10, buttonSave.area().height }, { 0, buttonOffsets.y },
isEvilInterface, fheroes2::StandardWindow::Padding::CENTER_CENTER );
background.renderButtonSprite( buttonPlayMap, gettext_noop( "START\nMAP" ), { buttonSave.area().width - 10, buttonSave.area().height },
{ buttonOffsets.x, buttonOffsets.y }, isEvilInterface, fheroes2::StandardWindow::Padding::TOP_RIGHT );
background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 },
fheroes2::StandardWindow::Padding::BOTTOM_CENTER );

display.render( background.totalArea() );

LocalEvent & le = LocalEvent::Get();

Expand All @@ -1186,36 +1190,75 @@ namespace Interface
buttonLoad.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLoad.area() ) );
buttonSave.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSave.area() ) );
buttonQuit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonQuit.area() ) );
buttonMainMenu.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMainMenu.area() ) );
buttonPlayMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPlayMap.area() ) );
buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) );

if ( le.MouseClickLeft( buttonNew.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU ) ) {
if ( eventNewMap() == fheroes2::GameMode::EDITOR_NEW_MAP ) {
result = fheroes2::GameMode::EDITOR_NEW_MAP;
break;
return fheroes2::GameMode::EDITOR_NEW_MAP;
}
}
else if ( le.MouseClickLeft( buttonLoad.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) {
if ( le.MouseClickLeft( buttonLoad.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) {
if ( eventLoadMap() == fheroes2::GameMode::EDITOR_LOAD_MAP ) {
result = fheroes2::GameMode::EDITOR_LOAD_MAP;
break;
return fheroes2::GameMode::EDITOR_LOAD_MAP;
}
}
else if ( le.MouseClickLeft( buttonSave.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) {
back.restore();

if ( le.MouseClickLeft( buttonSave.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) {
// Special case: since we show a window about file saving we don't want to display the current dialog anymore.
background.hideWindow();
Get().saveMapToFile();

break;
return fheroes2::GameMode::CANCEL;
}

if ( le.MouseClickLeft( buttonQuit.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_QUIT ) ) {
if ( EventExit() == fheroes2::GameMode::QUIT_GAME ) {
result = fheroes2::GameMode::QUIT_GAME;
break;
return fheroes2::GameMode::QUIT_GAME;
}
}
if ( le.MouseClickLeft( buttonMainMenu.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_TO_GAME_MAIN_MENU ) ) {
if ( fheroes2::showStandardTextMessage( _( "Main Menu" ),
_( "Do you wish to return to the game's Main Menu? (Any unsaved changes to the current map will be lost.)" ),
Dialog::YES | Dialog::NO )
== Dialog::YES ) {
return fheroes2::GameMode::MAIN_MENU;
}
}
else if ( le.MouseClickLeft( buttonPlayMap.area() ) ) {
bool isNameEmpty = conf.getCurrentMapInfo().name.empty();
if ( isNameEmpty
&& fheroes2::showStandardTextMessage(
_( "Unsaved Changes" ),
_( "This map has either terrain changes, undo history or has not yet been saved to a file.\n\nDo you wish to save the current map?" ),
Dialog::YES | Dialog::NO )
== Dialog::NO ) {
continue;
}
if ( isNameEmpty ) {
Get().saveMapToFile();
isNameEmpty = conf.getCurrentMapInfo().name.empty();
if ( isNameEmpty ) {
// Saving was aborted.
display.render( background.totalArea() );
continue;
}
}
if ( conf.getCurrentMapInfo().colorsAvailableForHumans == 0 ) {
fheroes2::showStandardTextMessage( _( "Unplayable Map" ),
_( "This map is not playable. You need at least one human player for the map to be playable." ), Dialog::OK );
}
else {
if ( fheroes2::
showStandardTextMessage( _( "Start Map" ),
_( "Do you wish to leave the Editor and start the map? (Any unsaved changes to the current map will be lost.)" ),
Dialog::YES | Dialog::NO )
== Dialog::YES ) {
return fheroes2::GameMode::NEW_STANDARD;
}
}
}
else if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyCloseWindow() ) {
break;
return fheroes2::GameMode::CANCEL;
}

if ( le.isMouseRightButtonPressedInArea( buttonNew.area() ) ) {
Expand All @@ -1232,16 +1275,17 @@ namespace Interface
else if ( le.isMouseRightButtonPressedInArea( buttonQuit.area() ) ) {
fheroes2::showStandardTextMessage( _( "Quit" ), _( "Quit out of the map editor." ), Dialog::ZERO );
}
else if ( le.isMouseRightButtonPressedInArea( buttonMainMenu.area() ) ) {
fheroes2::showStandardTextMessage( _( "Main Menu" ), _( "Return to the game's Main Menu." ), Dialog::ZERO );
}
zenseii marked this conversation as resolved.
Show resolved Hide resolved
else if ( le.isMouseRightButtonPressedInArea( buttonPlayMap.area() ) ) {
fheroes2::showStandardTextMessage( _( "Start Map" ), _( "Leave the Editor and play the map in the Standard Game mode." ), Dialog::ZERO );
}
else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) {
fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO );
}
}

// restore background
back.restore();
display.render( back.rect() );

return result;
return fheroes2::GameMode::CANCEL;
}

void EditorInterface::eventViewWorld()
Expand Down
2 changes: 1 addition & 1 deletion src/fheroes2/game/game_scenarioinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ namespace
}
levelCursor.redraw();

display.render();
fheroes2::validateFadeInAndRender();

fheroes2::GameMode result = fheroes2::GameMode::QUIT_GAME;

Expand Down
3 changes: 1 addition & 2 deletions src/fheroes2/gui/ui_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -900,8 +900,7 @@ namespace fheroes2
pressedText.draw( pressedOffset.x + 1, pressedOffset.y + ( textAreaHeight - pressedTextSize.height ) / 2, textAreaWidth, pressed );
}

void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const fheroes2::Size buttonSize, const bool isEvilInterface,
const int backgroundIcnId )
void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const Size buttonSize, const bool isEvilInterface, const int backgroundIcnId )
{
fheroes2::Point releasedOffset;
fheroes2::Point pressedOffset;
Expand Down
11 changes: 5 additions & 6 deletions src/fheroes2/gui/ui_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,15 +346,14 @@ namespace fheroes2
ButtonSprite makeButtonWithShadow( int32_t offsetX, int32_t offsetY, const Sprite & released, const Sprite & pressed, const Image & background,
const Point & shadowOffset = Point( -4, 6 ) );

// The height of text area is only 16 pixels. If 'isTransparentBackground' is set to false the button sprite will have a default background pattern from
// STONEBAK or STONEBAK_EVIL (for Evil interface). The pattern is the same for all buttons.
// Generate released and pressed button sprites with custom sizes (width and height) for a chosen background ICN.
void getCustomNormalButton( Sprite & released, Sprite & pressed, const bool isEvilInterface, Size buttonSize, Point & releasedOffset, Point & pressedOffset,
const int backgroundIcnId );

// Makes a button that has the width necessary to fit a provided text using an empty button template
// 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
// ICN.
void getTextAdaptedSprite( Sprite & released, Sprite & pressed, const char * text, const int icnId, const int buttonBackgroundIcnID );

// Generate released and pressed button sprites with the text on it over a transparent or a default (STONEBAK/STONEBAK_EVIL) background.
void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const fheroes2::Size buttonSize, const bool isEvilInterface,
const int backgroundIcnId );
// Generate custom-size released and pressed button sprites with text on them over a chosen background ICN.
void makeButtonSprites( Sprite & released, Sprite & pressed, const std::string & text, const Size buttonSize, const bool isEvilInterface, const int backgroundIcnId );
}
5 changes: 5 additions & 0 deletions src/fheroes2/gui/ui_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ namespace fheroes2

static void renderBackgroundImage( fheroes2::Image & output, const Rect & roi, const int32_t borderOffset, const bool isEvilInterface );

void hideWindow()
{
_restorer.restore();
}

private:
Image & _output;
const Rect _activeArea;
Expand Down
Loading