Get menu background image from selected game
authorPerttu Ahola <celeron55@gmail.com>
Fri, 15 Feb 2013 19:13:53 +0000 (21:13 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Thu, 2 May 2013 16:43:47 +0000 (19:43 +0300)
src/guiMainMenu.cpp
src/guiMainMenu.h
src/main.cpp
src/subgame.cpp
src/subgame.h
src/tile.cpp
src/tile.h

index d3e3c007a796c23f75e72912ce298d215dc22e04..07efbb62f853334673bb37a8602fc1c968d099c9 100644 (file)
@@ -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<s32> 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; i<m_data->games.size(); i++){
+               const SubgameSpec *spec = &m_data->games[i];
+               v2s32 p(8 + i*(48+8), screensize.Y - (48+8));
+               core::rect<s32> 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<SubgameSpec> games = getAvailableGames();
+                               const std::vector<SubgameSpec> &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)
                {
index a594ccd418bac8c2b9a052b5740ab6ccc1245440..b0c9ff24b9583f846d256434230988367fc05acb 100644 (file)
@@ -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),
index eef65cdb2ab77eee7b75630b01a3ff68d7576d13..67aa82bc4d299eada1c49609f0fa7d412dacb050 100644 (file)
@@ -612,122 +612,65 @@ private:
        bool rightreleased;
 };
 
-//Draw the tiled menu background
-void drawMenuBackground(video::IVideoDriver* driver) {
-       core::dimension2d<u32> screensize = driver->getScreenSize();
-
-       std::string path = getTexturePath("menubg.png");
-       if (path[0]) {
-               static const video::ITexture *bgtexture =
-                       driver->getTexture(path.c_str());
+void drawMenuBackground(video::IVideoDriver* driver, const SubgameSpec *spec)
+{
+       v2u32 screensize = driver->getScreenSize();
 
-               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<s32>(0, 0, destsize.X, destsize.Y),
-                               core::rect<s32>(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());
        }
-}
 
-//Draw the footer at the bottom of the window
-void drawMenuFooter(video::IVideoDriver* driver, bool clouds) {
-       core::dimension2d<u32> 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());
-
-               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<s32> 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<s32>(core::position2d<s32>(0,0),
-                                       core::dimension2di(footertexture->getSize())),
-                                       NULL, NULL, true);
-                       }
-               }
+       /* If no texture, draw background of solid color */
+       if(!texture){
+               video::SColor color(255,80,58,37);
+               core::rect<s32> rect(0, 0, screensize.X, screensize.Y);
+               driver->draw2DRectangle(color, rect, NULL);
+               return;
        }
-}
-
-// Draw the Header over the main menu
-void drawMenuHeader(video::IVideoDriver* driver) {
-       core::dimension2d<u32> 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<s32> splashrect(0, 0, splashsize.X, splashsize.Y);
-                               splashrect += v2s32((screensize.Width/2)-(splashsize.X/2),
-                                       ((free_space/2)-splashsize.Y/2)+10);
+       /* Draw background texture */
+       v2u32 sourcesize = texture->getSize();
+       driver->draw2DImage(texture,
+               core::rect<s32>(0, 0, screensize.X, screensize.Y),
+               core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
+               NULL, NULL, true);
+}
 
-                               video::SColor bgcolor(255,50,50,50);
+void drawMenuOverlay(video::IVideoDriver* driver, const SubgameSpec *spec)
+{
+       v2u32 screensize = driver->getScreenSize();
 
-                               driver->draw2DImage(splashtexture, splashrect,
-                                       core::rect<s32>(core::position2d<s32>(0,0),
-                                       core::dimension2di(splashtexture->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());
        }
-}
 
-// Draw the Splash over the clouds and under the main menu
-void drawMenuSplash(video::IVideoDriver* driver) {
-       core::dimension2d<u32> screensize = driver->getScreenSize();
-       std::string path = getTexturePath("menusplash.png");
-       if (path[0]) {
-               static const video::ITexture *splashtexture =
-                       driver->getTexture(path.c_str());
+       /* If no texture, draw nothing */
+       if(!texture)
+               return;
 
-               if(splashtexture) {
-                       core::rect<s32> splashrect(0, 0, screensize.Width, screensize.Height);
-
-                       video::SColor bgcolor(255,50,50,50);
+       /* Draw overlay texture */
+       v2u32 sourcesize = texture->getSize();
+       driver->draw2DImage(texture,
+               core::rect<s32>(0, 0, screensize.X, screensize.Y),
+               core::rect<s32>(0, 0, sourcesize.X, sourcesize.Y),
+               NULL, NULL, true);
+}
 
-                       driver->draw2DImage(splashtexture, splashrect,
-                               core::rect<s32>(core::position2d<s32>(0,0),
-                               core::dimension2di(splashtexture->getSize())),
-                               NULL, NULL, true);
+static const SubgameSpec* getMenuGame(const MainMenuData &menudata)
+{
+       for(size_t i=0; i<menudata.games.size(); i++){
+               if(menudata.games[i].id == menudata.selected_game){
+                       return &menudata.games[i];
                }
        }
+       return NULL;
 }
 
-#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));
-
-                                               // A camera to see the clouds
-                                               scene::ICameraSceneNode* camera;
-                                               camera = smgr->addCameraSceneNode(0,
-                                                                       v3f(0,0,0), v3f(0, 60, 100));
-                                               camera->setFarValue(10000);
-                                       }
+                                       // 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);
 
                                        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"<<std::endl;
 
                                        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));
index 19ad4e636be379fdd38171d175f72f42b49b455e..a17b1623466c301d509a0aadb2be6f6268f7e940 100644 (file)
@@ -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)
index b120b75425482d8d5ee1e43dd54611734a63942b..2e16c2fec7f8357980cebdc74cfc78086d0a5328 100644 (file)
@@ -35,17 +35,26 @@ struct SubgameSpec
        std::string gamemods_path; //path to mods of the game
        std::set<std::string> 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<std::string> &addon_mods_paths_=std::set<std::string>(),
-                       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
index 39f47962e9da676f07fd09c5216b08ff0499f984..5f25e123bdd21556029e407cd81304a7e3cbee91 100644 (file)
@@ -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[] = {
index ea5c4be54b4598d1aeadede016ed27a114448205..531a93172894a3639f33fdcf95a9874b677b8d1e 100644 (file)
@@ -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.