From 084be3599a5ef0acba7c341bfd14a4e9801423a2 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 15 Feb 2013 21:13:53 +0200 Subject: [PATCH] Get menu background image from selected game --- src/guiMainMenu.cpp | 47 +++++++++- src/guiMainMenu.h | 2 + src/main.cpp | 219 ++++++++++++++++++-------------------------- src/subgame.cpp | 14 ++- src/subgame.h | 13 ++- src/tile.cpp | 2 +- src/tile.h | 11 +++ 7 files changed, 172 insertions(+), 136 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index d3e3c007a..07efbb62f 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -162,6 +162,8 @@ enum GUI_ID_SERVERLIST_TOGGLE, GUI_ID_SERVERLIST_DELETE, GUI_ID_SERVERLIST_TITLE, + GUI_ID_GAME_BUTTON_FIRST = 130, + GUI_ID_GAME_BUTTON_MAX = 150, }; enum @@ -255,8 +257,12 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, size.X, 40); rect += v2s32(4, 0); - Environment->addStaticText(narrow_to_wide( - "Minetest " VERSION_STRING).c_str(), + std::string t = "Minetest " VERSION_STRING; + if(m_data->selected_game != ""){ + t += "/"; + t += m_data->selected_game; + } + Environment->addStaticText(narrow_to_wide(t).c_str(), rect, false, true, this, -1); } @@ -900,6 +906,27 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) } } + /* Add game selection buttons */ + + video::IVideoDriver* driver = Environment->getVideoDriver(); + for(size_t i=0; igames.size(); i++){ + const SubgameSpec *spec = &m_data->games[i]; + v2s32 p(8 + i*(48+8), screensize.Y - (48+8)); + core::rect rect(0, 0, 48, 48); + rect += p; + video::ITexture *bgtexture = NULL; + if(spec->menuicon_path != "") + bgtexture = driver->getTexture(spec->menuicon_path.c_str()); + gui::IGUIButton *b = Environment->addButton(rect, this, + GUI_ID_GAME_BUTTON_FIRST+i, narrow_to_wide(wrap_rows(spec->id, 4)).c_str()); + if(bgtexture){ + b->setImage(bgtexture); + b->setText(L""); + b->setDrawBorder(false); + b->setUseAlphaChannel(true); + } + } + m_is_regenerating = false; } @@ -909,7 +936,9 @@ void GUIMainMenu::drawMenu() if (!skin) return; video::IVideoDriver* driver = Environment->getVideoDriver(); - + + /* Draw menu background */ + /*video::SColor bgcolor(140,0,0,0); driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/ @@ -976,6 +1005,8 @@ void GUIMainMenu::drawMenu() } } + /* Draw UI elements */ + gui::IGUIElement::draw(); } @@ -1221,7 +1252,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event) return true; } case GUI_ID_CREATE_WORLD_BUTTON: { - std::vector games = getAvailableGames(); + const std::vector &games = m_data->games; if(games.size() == 0){ wchar_t* text = wgettext("Cannot create world: No games found"); GUIMessageMenu *menu = new GUIMessageMenu(env, parent, @@ -1308,6 +1339,14 @@ bool GUIMainMenu::OnEvent(const SEvent& event) } #endif } + /* Game buttons */ + int eid = event.GUIEvent.Caller->getID(); + if(eid >= GUI_ID_GAME_BUTTON_FIRST && + eid <= GUI_ID_GAME_BUTTON_MAX){ + m_data->selected_game = + m_data->games[eid - GUI_ID_GAME_BUTTON_FIRST].id; + regenerateGui(m_screensize_old); + } } if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) { diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index a594ccd41..b0c9ff24b 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -39,6 +39,7 @@ struct MainMenuData // These are in the native format of the gui elements // Generic int selected_tab; + std::string selected_game; // Client options std::string servername; std::string serverdescription; @@ -78,6 +79,7 @@ struct MainMenuData MainMenuData(): // Generic selected_tab(0), + selected_game("minetest"), // Client opts fancy_trees(false), smooth_lighting(false), diff --git a/src/main.cpp b/src/main.cpp index eef65cdb2..67aa82bc4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -612,122 +612,65 @@ private: bool rightreleased; }; -//Draw the tiled menu background -void drawMenuBackground(video::IVideoDriver* driver) { - core::dimension2d screensize = driver->getScreenSize(); +void drawMenuBackground(video::IVideoDriver* driver, const SubgameSpec *spec) +{ + v2u32 screensize = driver->getScreenSize(); - std::string path = getTexturePath("menubg.png"); - if (path[0]) { - static const video::ITexture *bgtexture = - driver->getTexture(path.c_str()); - - if (bgtexture) { - s32 scaledsize = 128; - - // The important difference between destsize and screensize is - // that destsize is rounded to whole scaled pixels. - // These formulas use component-wise multiplication and division of v2u32. - v2u32 texturesize = bgtexture->getSize(); - v2u32 sourcesize = texturesize * screensize / scaledsize + v2u32(1,1); - v2u32 destsize = scaledsize * sourcesize / texturesize; - - // Default texture wrapping mode in Irrlicht is ETC_REPEAT. - driver->draw2DImage(bgtexture, - core::rect(0, 0, destsize.X, destsize.Y), - core::rect(0, 0, sourcesize.X, sourcesize.Y), - NULL, NULL, true); - } + /* Figure out background texture */ + video::ITexture *texture = NULL; + if(spec && spec->menubackground_path != ""){ + texture = driver->getTexture(spec->menubackground_path.c_str()); } + + /* If no texture, draw background of solid color */ + if(!texture){ + video::SColor color(255,80,58,37); + core::rect rect(0, 0, screensize.X, screensize.Y); + driver->draw2DRectangle(color, rect, NULL); + return; + } + + /* Draw background texture */ + v2u32 sourcesize = texture->getSize(); + driver->draw2DImage(texture, + core::rect(0, 0, screensize.X, screensize.Y), + core::rect(0, 0, sourcesize.X, sourcesize.Y), + NULL, NULL, true); } -//Draw the footer at the bottom of the window -void drawMenuFooter(video::IVideoDriver* driver, bool clouds) { - core::dimension2d screensize = driver->getScreenSize(); - std::string path = getTexturePath(clouds ? - "menufooter_clouds.png" : "menufooter.png"); - if (path[0]) { - static const video::ITexture *footertexture = - driver->getTexture(path.c_str()); +void drawMenuOverlay(video::IVideoDriver* driver, const SubgameSpec *spec) +{ + v2u32 screensize = driver->getScreenSize(); - if (footertexture) { - f32 mult = (((f32)screensize.Width)) / - ((f32)footertexture->getOriginalSize().Width); - - v2s32 footersize(((f32)footertexture->getOriginalSize().Width) * mult, - ((f32)footertexture->getOriginalSize().Height) * mult); - - // Don't draw the footer if there isn't enough room - s32 free_space = (((s32)screensize.Height)-320)/2; - if (free_space > footersize.Y) { - core::rect rect(0,0,footersize.X,footersize.Y); - rect += v2s32(screensize.Width/2,screensize.Height-footersize.Y); - rect -= v2s32(footersize.X/2, 0); - - driver->draw2DImage(footertexture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(footertexture->getSize())), - NULL, NULL, true); - } - } + /* Figure out overlay texture */ + video::ITexture *texture = NULL; + if(spec && spec->menuoverlay_path != ""){ + texture = driver->getTexture(spec->menuoverlay_path.c_str()); } + + /* If no texture, draw nothing */ + if(!texture) + return; + + /* Draw overlay texture */ + v2u32 sourcesize = texture->getSize(); + driver->draw2DImage(texture, + core::rect(0, 0, screensize.X, screensize.Y), + core::rect(0, 0, sourcesize.X, sourcesize.Y), + NULL, NULL, true); } -// Draw the Header over the main menu -void drawMenuHeader(video::IVideoDriver* driver) { - core::dimension2d screensize = driver->getScreenSize(); - - std::string path = getTexturePath("menuheader.png"); - if (path[0]) { - static const video::ITexture *splashtexture = - driver->getTexture(path.c_str()); - - if(splashtexture) { - f32 mult = (((f32)screensize.Width / 2)) / - ((f32)splashtexture->getOriginalSize().Width); - - v2s32 splashsize(((f32)splashtexture->getOriginalSize().Width) * mult, - ((f32)splashtexture->getOriginalSize().Height) * mult); - - // Don't draw the header is there isn't enough room - s32 free_space = (((s32)screensize.Height)-320)/2; - if (free_space > splashsize.Y) { - core::rect splashrect(0, 0, splashsize.X, splashsize.Y); - splashrect += v2s32((screensize.Width/2)-(splashsize.X/2), - ((free_space/2)-splashsize.Y/2)+10); - - video::SColor bgcolor(255,50,50,50); - - driver->draw2DImage(splashtexture, splashrect, - core::rect(core::position2d(0,0), - core::dimension2di(splashtexture->getSize())), - NULL, NULL, true); - } +static const SubgameSpec* getMenuGame(const MainMenuData &menudata) +{ + for(size_t i=0; i screensize = driver->getScreenSize(); - std::string path = getTexturePath("menusplash.png"); - if (path[0]) { - static const video::ITexture *splashtexture = - driver->getTexture(path.c_str()); - - if(splashtexture) { - core::rect splashrect(0, 0, screensize.Width, screensize.Height); - - video::SColor bgcolor(255,50,50,50); - - driver->draw2DImage(splashtexture, splashrect, - core::rect(core::position2d(0,0), - core::dimension2di(splashtexture->getSize())), - NULL, NULL, true); - } - } -} - -#endif +#endif // !SERVER // These are defined global so that they're not optimized too much. // Can't change them to volatile. @@ -1558,6 +1501,8 @@ int main(int argc, char *argv[]) menudata.selected_tab = g_settings->getS32("selected_mainmenu_tab"); if(g_settings->exists("selected_serverlist")) menudata.selected_serverlist = g_settings->getS32("selected_serverlist"); + if(g_settings->exists("selected_mainmenu_game")) + menudata.selected_game = g_settings->get("selected_mainmenu_game"); menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); @@ -1611,6 +1556,14 @@ int main(int argc, char *argv[]) } // Copy worldspecs to menu menudata.worlds = worldspecs; + // Get game listing + menudata.games = getAvailableGames(); + // If selected game doesn't exist, take first from list + if(findSubgame(menudata.selected_game).id == "" && + !menudata.games.empty()){ + menudata.selected_game = menudata.games[0].id; + } + const SubgameSpec *menugame = getMenuGame(menudata); if(skip_main_menu == false) { @@ -1623,7 +1576,7 @@ int main(int argc, char *argv[]) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); - drawMenuBackground(driver); + drawMenuBackground(driver, menugame); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be @@ -1637,21 +1590,17 @@ int main(int argc, char *argv[]) &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); - // Clouds for the main menu - bool cloud_menu_background = false; - Clouds *clouds = NULL; - if (g_settings->getBool("menu_clouds")) { - cloud_menu_background = true; - clouds = new Clouds(smgr->getRootSceneNode(), - smgr, -1, rand(), 100); - clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); + // Always create clouds because they may or may not be + // needed based on the game selected + Clouds *clouds = new Clouds(smgr->getRootSceneNode(), + smgr, -1, rand(), 100); + clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); - // A camera to see the clouds - scene::ICameraSceneNode* camera; - camera = smgr->addCameraSceneNode(0, - v3f(0,0,0), v3f(0, 60, 100)); - camera->setFarValue(10000); - } + // A camera to see the clouds + scene::ICameraSceneNode* camera; + camera = smgr->addCameraSceneNode(0, + v3f(0,0,0), v3f(0, 60, 100)); + camera->setFarValue(10000); if(error_message != L"") { @@ -1675,6 +1624,24 @@ int main(int argc, char *argv[]) if(menu->getStatus() == true) break; + // Game can be selected in the menu + menugame = getMenuGame(menudata); + // Clouds for the main menu + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + if(menugame){ + // If game has regular background and no overlay, don't use clouds + if(cloud_menu_background && + menugame->menuoverlay_path.empty() && + !menugame->menubackground_path.empty()){ + cloud_menu_background = false; + } + // If game game has overlay and no regular background, always draw clouds + else if(menugame->menubackground_path.empty() && + !menugame->menuoverlay_path.empty()){ + cloud_menu_background = true; + } + } + // Time calc for the clouds f32 dtime; // in seconds if (cloud_menu_background) { @@ -1694,12 +1661,9 @@ int main(int argc, char *argv[]) clouds->step(dtime*3); clouds->render(); smgr->drawAll(); - drawMenuSplash(driver); - drawMenuFooter(driver, true); - drawMenuHeader(driver); + drawMenuOverlay(driver, menugame); } else { - drawMenuBackground(driver); - drawMenuFooter(driver, false); + drawMenuBackground(driver, menugame); } guienv->drawAll(); @@ -1735,10 +1699,8 @@ int main(int argc, char *argv[]) infostream<<"Dropping main menu"<drop(); - if (cloud_menu_background) { - clouds->drop(); - smgr->clear(); - } + clouds->drop(); + smgr->clear(); } playername = wide_to_narrow(menudata.name); @@ -1755,6 +1717,7 @@ int main(int argc, char *argv[]) // Save settings g_settings->setS32("selected_mainmenu_tab", menudata.selected_tab); g_settings->setS32("selected_serverlist", menudata.selected_serverlist); + g_settings->set("selected_mainmenu_game", menudata.selected_game); g_settings->set("new_style_leaves", itos(menudata.fancy_trees)); g_settings->set("smooth_lighting", itos(menudata.smooth_lighting)); g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d)); diff --git a/src/subgame.cpp b/src/subgame.cpp index 19ad4e636..a17b16234 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -22,6 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "settings.h" #include "log.h" +#ifndef SERVER +#include "tile.h" // getImagePath +#endif #include "util/string.h" bool getGameMinetestConfig(const std::string &game_path, Settings &conf) @@ -94,7 +97,16 @@ SubgameSpec findSubgame(const std::string &id) std::string game_name = getGameName(game_path); if(game_name == "") game_name = id; - return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name); + std::string menubackground_path; + std::string menuoverlay_path; + std::string menuicon_path; +#ifndef SERVER + menubackground_path = getImagePath(game_path + DIR_DELIM + "menu/background.png"); + menuoverlay_path = getImagePath(game_path + DIR_DELIM + "menu/overlay.png"); + menuicon_path = getImagePath(game_path + DIR_DELIM + "menu/icon.png"); +#endif + return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name, + menubackground_path, menuoverlay_path, menuicon_path); } SubgameSpec findWorldSubgame(const std::string &world_path) diff --git a/src/subgame.h b/src/subgame.h index b120b7542..2e16c2fec 100644 --- a/src/subgame.h +++ b/src/subgame.h @@ -35,17 +35,26 @@ struct SubgameSpec std::string gamemods_path; //path to mods of the game std::set addon_mods_paths; //paths to addon mods for this game std::string name; + std::string menubackground_path; + std::string menuoverlay_path; + std::string menuicon_path; SubgameSpec(const std::string &id_="", const std::string &path_="", const std::string &gamemods_path_="", const std::set &addon_mods_paths_=std::set(), - const std::string &name_=""): + const std::string &name_="", + const std::string &menubackground_path_="", + const std::string &menuoverlay_path_="", + const std::string &menuicon_path_=""): id(id_), path(path_), gamemods_path(gamemods_path_), addon_mods_paths(addon_mods_paths_), - name(name_) + name(name_), + menubackground_path(menubackground_path_), + menuoverlay_path(menuoverlay_path_), + menuicon_path(menuicon_path_) {} bool isValid() const diff --git a/src/tile.cpp b/src/tile.cpp index 39f47962e..5f25e123b 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -77,7 +77,7 @@ static bool replace_ext(std::string &path, const char *ext) If failed, return "". */ -static std::string getImagePath(std::string path) +std::string getImagePath(std::string path) { // A NULL-ended list of possible image extensions const char *extensions[] = { diff --git a/src/tile.h b/src/tile.h index ea5c4be54..531a93172 100644 --- a/src/tile.h +++ b/src/tile.h @@ -34,6 +34,17 @@ class IGameDef; tile.{h,cpp}: Texture handling stuff. */ +/* + Find out the full path of an image by trying different filename + extensions. + + If failed, return "". + + TODO: Should probably be moved out from here, because things needing + this function do not need anything else from this header +*/ +std::string getImagePath(std::string path); + /* Gets the path to a texture by first checking if the texture exists in texture_path and if not, using the data path.