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 Editor Main Menu #7241

Merged
merged 16 commits into from
May 30, 2023
Merged
1 change: 1 addition & 0 deletions VisualStudio/fheroes2/sources.props
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<ClCompile Include="src\fheroes2\game\game_campaign.cpp" />
<ClCompile Include="src\fheroes2\game\game_credits.cpp" />
<ClCompile Include="src\fheroes2\game\game_delays.cpp" />
<ClCompile Include="src\fheroes2\game\game_editor_mainmenu.cpp" />
<ClCompile Include="src\fheroes2\game\game_highscores.cpp" />
<ClCompile Include="src\fheroes2\game\game_hotkeys.cpp" />
<ClCompile Include="src\fheroes2\game\game_interface.cpp" />
Expand Down
11 changes: 10 additions & 1 deletion src/fheroes2/agg/agg_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2635,6 +2635,15 @@ namespace fheroes2

return true;
}
case ICN::EDITOR:
LoadOriginalICN( id );
if ( !_icnVsSprite[id].empty() ) {
// This is the Editor main menu background which shouldn't have any transform layer.
_icnVsSprite[id][0]._disableTransformLayer();
// Fix the cycling colors in original editor main menu background.
fheroes2::ApplyPalette( _icnVsSprite[id][0], PAL::GetPalette( PAL::PaletteType::NO_CYCLE ) );
}
return true;
case ICN::HEROES:
LoadOriginalICN( id );
if ( !_icnVsSprite[id].empty() ) {
Expand Down Expand Up @@ -3672,7 +3681,7 @@ namespace fheroes2
// We have few ICNs which we need to scale like some related to main screen
bool IsScalableICN( const int id )
{
return id == ICN::HEROES || id == ICN::BTNSHNGL || id == ICN::SHNGANIM;
return id == ICN::EDITOR || id == ICN::HEROES || id == ICN::BTNSHNGL || id == ICN::SHNGANIM;
}

const Sprite & GetScaledICN( const int icnId, const uint32_t index )
Expand Down
4 changes: 4 additions & 0 deletions src/fheroes2/game/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ namespace Game
fheroes2::GameMode CompleteCampaignScenario( const bool isLoadingSaveFile );
fheroes2::GameMode DisplayHighScores( const bool isCampaign );

fheroes2::GameMode editorMainMenu();
fheroes2::GameMode editorNewMap();
fheroes2::GameMode editorLoadMap();

bool isSuccessionWarsCampaignPresent();
bool isPriceOfLoyaltyCampaignPresent();

Expand Down
263 changes: 263 additions & 0 deletions src/fheroes2/game/game_editor_mainmenu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2023 *
* *
* Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 *
* Copyright (C) 2009 by Andrey Afletdinov <fheroes2@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#include <array>
#include <cstddef>
#include <cstdint>
#include <string>

#include "audio.h"
#include "audio_manager.h"
#include "cursor.h"
#include "dialog.h"
#include "dialog_selectscenario.h"
#include "game.h"
#include "game_hotkeys.h"
#include "game_mainmenu_ui.h"
#include "game_mode.h"
#include "icn.h"
#include "localevent.h"
#include "maps.h"
#include "maps_fileinfo.h"
#include "math_base.h"
#include "mus.h"
#include "settings.h"
#include "text.h"
#include "tools.h"
#include "translations.h"
#include "ui_button.h"
#include "ui_dialog.h"
#include "ui_text.h"

namespace
{
const int32_t buttonYStep = 66;

void showWIPInfo()
{
fheroes2::showMessage( fheroes2::Text{ _( "Warning!" ), fheroes2::FontType::normalYellow() },
fheroes2::Text{ "The Map Editor is still in development. This function is not available yet.", fheroes2::FontType::normalWhite() },
Dialog::OK );
}

Maps::mapsize_t selectMapSize()
{
const CursorRestorer cursorRestorer( true, Cursor::POINTER );

fheroes2::drawEditorMainMenuScreen();

const fheroes2::Point buttonPos = fheroes2::drawButtonPanel();

std::array<fheroes2::Button, 4> buttons;
std::array<Game::HotKeyEvent, 4> buttonHotkey = { Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_SMALL, Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_MEDIUM,
Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_LARGE, Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE };
std::array<Maps::mapsize_t, 4> buttonMapSize = { Maps::SMALL, Maps::MEDIUM, Maps::LARGE, Maps::XLARGE };
const size_t buttonCount = buttons.size();

for ( uint32_t i = 0; i < buttonCount; ++i ) {
buttons[i].setICNInfo( ICN::BTNESIZE, 0 + i * 2, 1 + i * 2 );
buttons[i].setPosition( buttonPos.x, buttonPos.y + buttonYStep * static_cast<int32_t>( i ) );
buttons[i].draw();
}

fheroes2::Button cancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 );
cancel.draw();

fheroes2::validateFadeInAndRender();

LocalEvent & le = LocalEvent::Get();

while ( le.HandleEvents() ) {
for ( size_t i = 0; i < buttonCount; ++i ) {
le.MousePressLeft( buttons[i].area() ) ? buttons[i].drawOnPress() : buttons[i].drawOnRelease();

if ( le.MouseClickLeft( buttons[i].area() ) || Game::HotKeyPressEvent( buttonHotkey[i] ) ) {
return buttonMapSize[i];
}

if ( le.MousePressRight( buttons[i].area() ) ) {
std::string mapSize = std::to_string( buttonMapSize[i] );
std::string message = _( "Create a map that is %{size} squares wide and %{size} squares high." );
StringReplace( message, "%{size}", mapSize );
mapSize += " x " + mapSize;
Dialog::Message( mapSize, message, Font::BIG );
}
}

le.MousePressLeft( cancel.area() ) ? cancel.drawOnPress() : cancel.drawOnRelease();

if ( le.MouseClickLeft( cancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) {
return Maps::ZERO;
}

if ( le.MousePressRight( cancel.area() ) ) {
Dialog::Message( _( "Cancel" ), _( "Cancel back to the New Map menu." ), Font::BIG );
}
}

return Maps::ZERO;
}

}

fheroes2::GameMode Game::editorMainMenu()
{
// Stop all sounds, but not the music
AudioManager::stopSounds();

AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE );

// setup cursor
const CursorRestorer cursorRestorer( true, Cursor::POINTER );

fheroes2::drawEditorMainMenuScreen();

const fheroes2::Point buttonPos = fheroes2::drawButtonPanel();

fheroes2::Button newMap( buttonPos.x, buttonPos.y, ICN::BTNEMAIN, 0, 1 );
fheroes2::Button loadMap( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNEMAIN, 2, 3 );
fheroes2::Button cancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 );

newMap.draw();
loadMap.draw();
cancel.draw();

fheroes2::validateFadeInAndRender();

LocalEvent & le = LocalEvent::Get();

while ( le.HandleEvents() ) {
le.MousePressLeft( newMap.area() ) ? newMap.drawOnPress() : newMap.drawOnRelease();
le.MousePressLeft( loadMap.area() ) ? loadMap.drawOnPress() : loadMap.drawOnRelease();
le.MousePressLeft( cancel.area() ) ? cancel.drawOnPress() : cancel.drawOnRelease();

if ( le.MouseClickLeft( newMap.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_NEW_GAME ) ) {
return fheroes2::GameMode::EDITOR_NEW_MAP;
}
if ( le.MouseClickLeft( loadMap.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) {
return fheroes2::GameMode::EDITOR_LOAD_MAP;
}
if ( le.MouseClickLeft( cancel.area() ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) ) {
return fheroes2::GameMode::MAIN_MENU;
}

if ( le.MousePressRight( newMap.area() ) ) {
Dialog::Message( _( "New Map" ), _( "Create a new map either from scratch or using the random map generator." ), Font::BIG );
}
else if ( le.MousePressRight( loadMap.area() ) ) {
Dialog::Message( _( "Load Map" ), _( "Load an existing map." ), Font::BIG );
}
else if ( le.MousePressRight( cancel.area() ) ) {
Dialog::Message( _( "Cancel" ), _( "Cancel back to the main menu." ), Font::BIG );
}
}

return fheroes2::GameMode::MAIN_MENU;
}

fheroes2::GameMode Game::editorNewMap()
{
const CursorRestorer cursorRestorer( true, Cursor::POINTER );

fheroes2::drawEditorMainMenuScreen();

const fheroes2::Point buttonPos = fheroes2::drawButtonPanel();

fheroes2::Button scratchMap( buttonPos.x, buttonPos.y, ICN::BTNENEW, 0, 1 );
fheroes2::Button randomMap( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNENEW, 2, 3 );
fheroes2::Button cancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 );

scratchMap.draw();
randomMap.draw();
cancel.draw();

fheroes2::validateFadeInAndRender();

LocalEvent & le = LocalEvent::Get();

while ( le.HandleEvents() ) {
le.MousePressLeft( scratchMap.area() ) ? scratchMap.drawOnPress() : scratchMap.drawOnRelease();
le.MousePressLeft( randomMap.area() ) ? randomMap.drawOnPress() : randomMap.drawOnRelease();
le.MousePressLeft( cancel.area() ) ? cancel.drawOnPress() : cancel.drawOnRelease();

if ( le.MouseClickLeft( scratchMap.area() ) ) {
if ( selectMapSize() != Maps::ZERO ) {
showWIPInfo();
}
return fheroes2::GameMode::EDITOR_NEW_MAP;
}

if ( le.MouseClickLeft( randomMap.area() ) ) {
if ( selectMapSize() != Maps::ZERO ) {
showWIPInfo();
}
return fheroes2::GameMode::EDITOR_NEW_MAP;
}

if ( le.MouseClickLeft( cancel.area() ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) ) {
return fheroes2::GameMode::EDITOR_MAIN_MENU;
}

if ( le.MousePressRight( scratchMap.area() ) ) {
Dialog::Message( _( "From Scratch" ), _( "Start from scratch with a blank map." ), Font::BIG );
}
else if ( le.MousePressRight( randomMap.area() ) ) {
Dialog::Message( _( "Random" ), _( "Create a randomly generated map." ), Font::BIG );
}
else if ( le.MousePressRight( cancel.area() ) ) {
Dialog::Message( _( "Cancel" ), _( "Cancel back to the Map Editor main menu." ), Font::BIG );
}
}

return fheroes2::GameMode::EDITOR_MAIN_MENU;
}

fheroes2::GameMode Game::editorLoadMap()
{
const CursorRestorer cursorRestorer( true, Cursor::POINTER );

fheroes2::drawEditorMainMenuScreen();

fheroes2::validateFadeInAndRender();

const MapsFileInfoList lists = Maps::PrepareMapsFileInfoList( false );
if ( lists.empty() ) {
Dialog::Message( _( "Warning" ), _( "No maps available!" ), Font::BIG, Dialog::OK );
return fheroes2::GameMode::EDITOR_MAIN_MENU;
}

const Maps::FileInfo * fileInfo = Dialog::SelectScenario( lists );

if ( fileInfo
&& fheroes2::showMessage( fheroes2::Text{ _( "Warning!" ), fheroes2::FontType::normalYellow() },
fheroes2::Text{ "You have selected:\n" + fileInfo->name
+ "\n But the Map Editor is still in development.\nDo you want to play a single player game?",
fheroes2::FontType::normalWhite() },
Dialog::YES | Dialog::NO )
== Dialog::YES ) {
Settings::Get().SetCurrentFileInfo( *fileInfo );
return fheroes2::GameMode::NEW_STANDARD;
}

return fheroes2::GameMode::EDITOR_MAIN_MENU;
}
5 changes: 5 additions & 0 deletions src/fheroes2/game/game_hotkeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ namespace
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_NEW_EXPANSION_CAMPAIGN )]
= { HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|choose the expansion campaign" ), fheroes2::Key::KEY_E };

#if defined( WITH_DEBUG )
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_MAIN_MENU )]
= { HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|map editor main menu" ), fheroes2::Key::KEY_E };
#endif

hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_ROLAND )]
= { HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|roland campaign" ), fheroes2::Key::KEY_1 };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_ARCHIBALD )]
Expand Down
5 changes: 5 additions & 0 deletions src/fheroes2/game/game_hotkeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ namespace Game
MAIN_MENU_NEW_ORIGINAL_CAMPAIGN,
MAIN_MENU_NEW_EXPANSION_CAMPAIGN,

#if defined( WITH_DEBUG )
// Editor is still in development.
EDITOR_MAIN_MENU,
#endif

CAMPAIGN_ROLAND,
CAMPAIGN_ARCHIBALD,
CAMPAIGN_PRICE_OF_LOYALTY,
Expand Down
15 changes: 15 additions & 0 deletions src/fheroes2/game/game_mainmenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ void Game::mainGameLoop( bool isFirstGameRun )
result = Game::SelectCampaignScenario( fheroes2::GameMode::LOAD_CAMPAIGN, false );
}
break;
case fheroes2::GameMode::EDITOR_MAIN_MENU:
result = Game::editorMainMenu();
break;
case fheroes2::GameMode::EDITOR_NEW_MAP:
result = Game::editorNewMap();
break;
case fheroes2::GameMode::EDITOR_LOAD_MAP:
result = Game::editorLoadMap();
break;

default:
break;
Expand Down Expand Up @@ -349,6 +358,12 @@ fheroes2::GameMode Game::MainMenu( bool isFirstGameRun )

return fheroes2::GameMode::MAIN_MENU;
}
#if defined( WITH_DEBUG )
// Editor is still in development.
else if ( HotKeyPressEvent( HotKeyEvent::EDITOR_MAIN_MENU ) ) {
return fheroes2::GameMode::EDITOR_MAIN_MENU;
}
#endif

// right info
if ( le.MousePressRight( buttonQuit.area() ) )
Expand Down
Loading