You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
11 KiB
C++
328 lines
11 KiB
C++
#include "mainmenu.hpp"
|
|
|
|
#include <MyGUI_TextBox.h>
|
|
#include <MyGUI_Gui.h>
|
|
#include <MyGUI_RenderManager.h>
|
|
|
|
#include <components/widgets/imagebutton.hpp>
|
|
#include <components/settings/settings.hpp>
|
|
#include <components/vfs/manager.hpp>
|
|
|
|
#include "../mwbase/environment.hpp"
|
|
#include "../mwbase/windowmanager.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
#include "../mwbase/statemanager.hpp"
|
|
|
|
#include "savegamedialog.hpp"
|
|
#include "confirmationdialog.hpp"
|
|
#include "backgroundimage.hpp"
|
|
#include "videowidget.hpp"
|
|
|
|
namespace MWGui
|
|
{
|
|
|
|
MainMenu::MainMenu(int w, int h, const VFS::Manager* vfs, const std::string& versionDescription)
|
|
: WindowBase("openmw_mainmenu.layout")
|
|
, mWidth (w), mHeight (h)
|
|
, mVFS(vfs), mButtonBox(0)
|
|
, mBackground(NULL)
|
|
, mVideoBackground(NULL)
|
|
, mVideo(NULL)
|
|
, mSaveGameDialog(NULL)
|
|
{
|
|
getWidget(mVersionText, "VersionText");
|
|
mVersionText->setCaption(versionDescription);
|
|
|
|
mHasAnimatedMenu = mVFS->exists("video/menu_background.bik");
|
|
|
|
updateMenu();
|
|
}
|
|
|
|
MainMenu::~MainMenu()
|
|
{
|
|
delete mSaveGameDialog;
|
|
}
|
|
|
|
void MainMenu::onResChange(int w, int h)
|
|
{
|
|
mWidth = w;
|
|
mHeight = h;
|
|
|
|
updateMenu();
|
|
}
|
|
|
|
void MainMenu::setVisible (bool visible)
|
|
{
|
|
if (visible)
|
|
updateMenu();
|
|
|
|
bool isMainMenu =
|
|
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
|
|
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame;
|
|
|
|
showBackground(isMainMenu);
|
|
|
|
if (visible)
|
|
{
|
|
if (isMainMenu)
|
|
{
|
|
if (mButtons["loadgame"]->getVisible())
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["loadgame"]);
|
|
else
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["newgame"]);
|
|
}
|
|
else
|
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["return"]);
|
|
}
|
|
|
|
Layout::setVisible (visible);
|
|
}
|
|
|
|
void MainMenu::onNewGameConfirmed()
|
|
{
|
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu);
|
|
MWBase::Environment::get().getStateManager()->newGame();
|
|
}
|
|
|
|
void MainMenu::onExitConfirmed()
|
|
{
|
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
|
}
|
|
|
|
void MainMenu::onButtonClicked(MyGUI::Widget *sender)
|
|
{
|
|
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
|
|
|
|
std::string name = *sender->getUserData<std::string>();
|
|
winMgr->playSound("Menu Click");
|
|
if (name == "return")
|
|
{
|
|
winMgr->removeGuiMode (GM_MainMenu);
|
|
}
|
|
else if (name == "options")
|
|
winMgr->pushGuiMode (GM_Settings);
|
|
else if (name == "credits")
|
|
winMgr->playVideo("mw_credits.bik", true);
|
|
else if (name == "exitgame")
|
|
{
|
|
if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame)
|
|
onExitConfirmed();
|
|
else
|
|
{
|
|
ConfirmationDialog* dialog = winMgr->getConfirmationDialog();
|
|
dialog->askForConfirmation("#{sMessage2}");
|
|
dialog->eventOkClicked.clear();
|
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onExitConfirmed);
|
|
dialog->eventCancelClicked.clear();
|
|
}
|
|
}
|
|
else if (name == "newgame")
|
|
{
|
|
if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame)
|
|
onNewGameConfirmed();
|
|
else
|
|
{
|
|
ConfirmationDialog* dialog = winMgr->getConfirmationDialog();
|
|
dialog->askForConfirmation("#{sNotifyMessage54}");
|
|
dialog->eventOkClicked.clear();
|
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onNewGameConfirmed);
|
|
dialog->eventCancelClicked.clear();
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (!mSaveGameDialog)
|
|
mSaveGameDialog = new SaveGameDialog();
|
|
if (name == "loadgame")
|
|
mSaveGameDialog->setLoadOrSave(true);
|
|
else if (name == "savegame")
|
|
mSaveGameDialog->setLoadOrSave(false);
|
|
mSaveGameDialog->setVisible(true);
|
|
}
|
|
}
|
|
|
|
void MainMenu::showBackground(bool show)
|
|
{
|
|
if (mVideo && !show)
|
|
{
|
|
MyGUI::Gui::getInstance().destroyWidget(mVideoBackground);
|
|
mVideoBackground = NULL;
|
|
mVideo = NULL;
|
|
}
|
|
if (mBackground && !show)
|
|
{
|
|
MyGUI::Gui::getInstance().destroyWidget(mBackground);
|
|
mBackground = NULL;
|
|
}
|
|
|
|
if (!show)
|
|
return;
|
|
|
|
bool stretch = Settings::Manager::getBool("stretch menu background", "GUI");
|
|
|
|
if (mHasAnimatedMenu)
|
|
{
|
|
if (!mVideo)
|
|
{
|
|
// Use black background to correct aspect ratio
|
|
mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1,
|
|
MyGUI::Align::Default, "Menu");
|
|
mVideoBackground->setImageTexture("black");
|
|
|
|
mVideo = mVideoBackground->createWidget<VideoWidget>("ImageBox", 0,0,1,1,
|
|
MyGUI::Align::Stretch, "Menu");
|
|
mVideo->setVFS(mVFS);
|
|
|
|
mVideo->playVideo("video\\menu_background.bik");
|
|
}
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
int screenWidth = viewSize.width;
|
|
int screenHeight = viewSize.height;
|
|
mVideoBackground->setSize(screenWidth, screenHeight);
|
|
|
|
mVideo->autoResize(stretch);
|
|
|
|
mVideo->setVisible(true);
|
|
}
|
|
else
|
|
{
|
|
if (!mBackground)
|
|
{
|
|
mBackground = MyGUI::Gui::getInstance().createWidgetReal<BackgroundImage>("ImageBox", 0,0,1,1,
|
|
MyGUI::Align::Stretch, "Menu");
|
|
mBackground->setBackgroundImage("textures\\menu_morrowind.dds", true, stretch);
|
|
}
|
|
mBackground->setVisible(true);
|
|
}
|
|
}
|
|
|
|
void MainMenu::onFrame(float dt)
|
|
{
|
|
if (mVideo)
|
|
{
|
|
if (!mVideo->update())
|
|
{
|
|
// If finished playing, start again
|
|
mVideo->playVideo("video\\menu_background.bik");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool MainMenu::exit()
|
|
{
|
|
return MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_Running;
|
|
}
|
|
|
|
void MainMenu::updateMenu()
|
|
{
|
|
setCoord(0,0, mWidth, mHeight);
|
|
|
|
if (!mButtonBox)
|
|
mButtonBox = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
|
|
|
|
int curH = 0;
|
|
|
|
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
|
|
|
|
mVersionText->setVisible(state == MWBase::StateManager::State_NoGame);
|
|
|
|
std::vector<std::string> buttons;
|
|
|
|
if (state==MWBase::StateManager::State_Running)
|
|
buttons.push_back("return");
|
|
|
|
/*
|
|
Start of tes3mp change (major)
|
|
|
|
In multiplayer, the main menu should not have options for starting or loading the game,
|
|
so they have been removed
|
|
|
|
Saving the game should still be possible, as long as it's clear that the resulting
|
|
save is singleplayer-only; this will prevent players from completely losing their
|
|
characters and houses on servers if those servers ever go down
|
|
*/
|
|
|
|
//buttons.push_back("newgame");
|
|
|
|
if (state==MWBase::StateManager::State_Running &&
|
|
MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 &&
|
|
MWBase::Environment::get().getWindowManager()->isSavingAllowed())
|
|
buttons.push_back("savegame");
|
|
|
|
/*
|
|
if (MWBase::Environment::get().getStateManager()->characterBegin()!=
|
|
MWBase::Environment::get().getStateManager()->characterEnd())
|
|
buttons.push_back("loadgame");
|
|
*/
|
|
|
|
/*
|
|
End of tes3mp change (major)
|
|
*/
|
|
|
|
buttons.push_back("options");
|
|
|
|
if (state==MWBase::StateManager::State_NoGame)
|
|
buttons.push_back("credits");
|
|
|
|
buttons.push_back("exitgame");
|
|
|
|
// Create new buttons if needed
|
|
std::vector<std::string> allButtons { "return", "newgame", "savegame", "loadgame", "options", "credits", "exitgame"};
|
|
for (std::vector<std::string>::iterator it = allButtons.begin(); it != allButtons.end(); ++it)
|
|
{
|
|
if (mButtons.find(*it) == mButtons.end())
|
|
{
|
|
Gui::ImageButton* button = mButtonBox->createWidget<Gui::ImageButton>
|
|
("ImageBox", MyGUI::IntCoord(0, curH, 0, 0), MyGUI::Align::Default);
|
|
button->setProperty("ImageHighlighted", "textures\\menu_" + *it + "_over.dds");
|
|
button->setProperty("ImageNormal", "textures\\menu_" + *it + ".dds");
|
|
button->setProperty("ImagePushed", "textures\\menu_" + *it + "_pressed.dds");
|
|
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MainMenu::onButtonClicked);
|
|
button->setUserData(std::string(*it));
|
|
mButtons[*it] = button;
|
|
}
|
|
}
|
|
|
|
// Start by hiding all buttons
|
|
int maxwidth = 0;
|
|
for (std::map<std::string, Gui::ImageButton*>::iterator it = mButtons.begin(); it != mButtons.end(); ++it)
|
|
{
|
|
it->second->setVisible(false);
|
|
MyGUI::IntSize requested = it->second->getRequestedSize();
|
|
if (requested.width > maxwidth)
|
|
maxwidth = requested.width;
|
|
}
|
|
|
|
// Now show and position the ones we want
|
|
for (std::vector<std::string>::iterator it = buttons.begin(); it != buttons.end(); ++it)
|
|
{
|
|
assert(mButtons.find(*it) != mButtons.end());
|
|
Gui::ImageButton* button = mButtons[*it];
|
|
button->setVisible(true);
|
|
|
|
MyGUI::IntSize requested = button->getRequestedSize();
|
|
|
|
// Trim off some of the excessive padding
|
|
// TODO: perhaps do this within ImageButton?
|
|
int trim = 8;
|
|
button->setImageCoord(MyGUI::IntCoord(0, trim, requested.width, requested.height-trim));
|
|
int height = requested.height-trim*2;
|
|
button->setImageTile(MyGUI::IntSize(requested.width, height));
|
|
button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, height);
|
|
curH += height;
|
|
}
|
|
|
|
if (state == MWBase::StateManager::State_NoGame)
|
|
{
|
|
// Align with the background image
|
|
int bottomPadding=24;
|
|
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight - curH - bottomPadding, maxwidth, curH);
|
|
}
|
|
else
|
|
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH);
|
|
|
|
}
|
|
}
|