From c914cbb0a081b30b28271618bbaa8e987a108ae7 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 23 Jan 2011 17:29:15 +0200 Subject: OMG! Main Menu! --- src/main.cpp | 544 ++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 356 insertions(+), 188 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 3006e3fd5..447224645 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,6 +104,16 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into different directions and then only those drawn that need to be - Also an 1-dimensional tile map would be nice probably +Gaming ideas: +------------- + +- How would some GTA-style ideas work? + - Cars? Stealing? Unlawful stuff and cops? Lots of guns? + +- RPG style? + +- Space racer style? + Documentation: -------------- @@ -289,7 +299,7 @@ Doing now: #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") -#pragma comment(lib, "jthread.lib") +//#pragma comment(lib, "jthread.lib") #pragma comment(lib, "zlibwapi.lib") // This would get rid of the console window //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") @@ -322,6 +332,7 @@ Doing now: #include "guiMessageMenu.h" #include "filesys.h" #include "config.h" +#include "guiMainMenu.h" IrrlichtWrapper *g_irrlicht; @@ -346,15 +357,87 @@ Client *g_client = NULL; /* GUI Stuff */ + gui::IGUIEnvironment* guienv = NULL; gui::IGUIStaticText *guiroot = NULL; -int g_active_menu_count = 0; + +class MainMenuManager : public IMenuManager +{ +public: + virtual void createdMenu(GUIModalMenu *menu) + { + for(core::list::Iterator + i = m_stack.begin(); + i != m_stack.end(); i++) + { + assert(*i != menu); + } + + if(m_stack.size() != 0) + (*m_stack.getLast())->setVisible(false); + m_stack.push_back(menu); + } + + virtual void deletingMenu(GUIModalMenu *menu) + { + // Remove all entries if there are duplicates + bool removed_entry; + do{ + removed_entry = false; + for(core::list::Iterator + i = m_stack.begin(); + i != m_stack.end(); i++) + { + if(*i == menu) + { + m_stack.erase(i); + removed_entry = true; + break; + } + } + }while(removed_entry); + + /*core::list::Iterator i = m_stack.getLast(); + assert(*i == menu); + m_stack.erase(i);*/ + + if(m_stack.size() != 0) + (*m_stack.getLast())->setVisible(true); + } + + u32 menuCount() + { + return m_stack.size(); + } + + core::list m_stack; +}; + +MainMenuManager g_menumgr; bool noMenuActive() { - return (g_active_menu_count == 0); + return (g_menumgr.menuCount() == 0); } +bool g_disconnect_requested = false; + +class MainGameCallback : public IGameCallback +{ +public: + virtual void exitToOS() + { + g_device->closeDevice(); + } + + virtual void disconnect() + { + g_disconnect_requested = true; + } +}; + +MainGameCallback g_gamecallback; + // Inventory actions from the menu are buffered here before sending Queue inventory_action_queue; // This is a copy of the inventory that the client's environment has @@ -472,8 +555,8 @@ public: dstream<drop(); + (new GUIPauseMenu(guienv, guiroot, -1, &g_gamecallback, + &g_menumgr))->drop(); return true; } if(event.KeyInput.Key == irr::KEY_KEY_I) @@ -482,7 +565,7 @@ public: <<"Launching inventory"<drop(); + &g_menumgr))->drop(); return true; } if(event.KeyInput.Key == irr::KEY_KEY_T) @@ -490,7 +573,7 @@ public: TextDest *dest = new TextDestChat(g_client); (new GUITextInputMenu(guienv, guiroot, -1, - &g_active_menu_count, dest, + &g_menumgr, dest, L""))->drop(); } } @@ -1067,6 +1150,18 @@ public: } } + ~GUIQuickInventory() + { + for(u32 i=0; iremove(); + } + for(u32 i=0; iremove(); + } + } + virtual bool OnEvent(const SEvent& event) { return false; @@ -1179,9 +1274,6 @@ int main(int argc, char *argv[]) <<", "<__| \\___ >____ > |__| "< "< list = server.getPlayerInfo(); - core::list::Iterator i; - static u32 sum_old = 0; - u32 sum = PIChecksum(list); - if(sum != sum_old) - { - std::cout<PrintLine(&std::cout); - } - } - sum_old = sum; - } - } + + // Run server + dedicated_server_loop(server); return 0; } - bool hosting = false; - char connect_name[100] = ""; - - if(cmd_args.exists("address")) - { - snprintf(connect_name, 100, "%s", cmd_args.get("address").c_str()); - } - else if(is_yes(g_settings.get("host_game")) == false) - { - if(g_settings.get("address") != "") - { - std::cout< Hosting game"< Connecting to "< \""<setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); + /* + Preload some textures + */ + + init_content_inventory_texture_paths(); + init_tile_texture_paths(); + tile_materials_preload(g_irrlicht); + + /* + GUI stuff + */ + + /* + We need some kind of a root node to be able to add + custom gui elements directly on the screen. + Otherwise they won't be automatically drawn. + */ + guiroot = guienv->addStaticText(L"", + core::rect(0, 0, 10000, 10000)); + + // First line of debug text + gui::IGUIStaticText *guitext = guienv->addStaticText( + L"", + core::rect(5, 5, 795, 5+text_height), + false, false); + // Second line of debug text + gui::IGUIStaticText *guitext2 = guienv->addStaticText( + L"", + core::rect(5, 5+(text_height+5)*1, 795, (5+text_height)*2), + false, false); + + // At the middle of the screen + // Object infos are shown in this + gui::IGUIStaticText *guitext_info = guienv->addStaticText( + L"", + core::rect(100, 70, 100+400, 70+(text_height+5)), + false, false); + + // Chat text + gui::IGUIStaticText *guitext_chat = guienv->addStaticText( + L"", + core::rect(0,0,0,0), + false, true); + guitext_chat->setBackgroundColor(video::SColor(96,0,0,0)); + core::list chat_lines; + + /* + If an error occurs, this is set to something and the + menu-game loop is restarted. It is then displayed before + the menu. + */ + std::wstring error_message = L""; + + /* + Menu-game loop + */ + while(g_device->run()) + { + + // This is used for catching disconnects + try + { + + /* + Out-of-game menu loop + */ + + // Wait for proper parameters + for(;;) + { + // Cursor can be non-visible when coming from the game + device->getCursorControl()->setVisible(true); + // Some stuff are left to scene manager when coming from the game + // (map at least?) + smgr->clear(); + // Reset or hide the debug gui texts + guitext->setText(L"Minetest-c55"); + guitext2->setVisible(false); + guitext_info->setVisible(false); + guitext_chat->setVisible(false); + + // Initialize menu data + MainMenuData menudata; + menudata.address = narrow_to_wide(address); + menudata.name = narrow_to_wide(playername); + menudata.port = narrow_to_wide(itos(port)); + menudata.creative_mode = g_settings.getBool("creative_mode"); + + GUIMainMenu *menu = + new GUIMainMenu(guienv, guiroot, -1, + &g_menumgr, &menudata, &g_gamecallback); + menu->allowFocusRemoval(true); + + if(error_message != L"") + { + GUIMessageMenu *menu2 = + new GUIMessageMenu(guienv, guiroot, -1, + &g_menumgr, error_message.c_str()); + menu2->drop(); + error_message = L""; + } + + video::IVideoDriver* driver = g_device->getVideoDriver(); + + dstream<<"Created main menu"<run()) + { + // Run global IrrlichtWrapper's main thread processing stuff + g_irrlicht->Run(); + + if(menu->getStatus() == true) + break; + + //driver->beginScene(true, true, video::SColor(255,0,0,0)); + driver->beginScene(true, true, video::SColor(255,128,128,128)); + guienv->drawAll(); + driver->endScene(); + } + + // Break out of menu-game loop to shut down cleanly + if(g_device->run() == false) + break; + + dstream<<"Dropping main menu"<drop(); + + playername = wide_to_narrow(menudata.name); + address = wide_to_narrow(menudata.address); + port = stoi(wide_to_narrow(menudata.port)); + g_settings.set("creative_mode", itos(menudata.creative_mode)); + + // Check for valid parameters, restart menu if invalid. + if(playername == "") + { + error_message = L"Name required."; + continue; + } + + // Save settings + g_settings.set("name", playername); + g_settings.set("address", address); + g_settings.set("port", itos(port)); + // Update configuration file + if(configpath != "") + g_settings.updateConfigFile(configpath.c_str()); + + // Continue to game + break; + } + + // Break out of menu-game loop to shut down cleanly + if(g_device->run() == false) + break; + + /* + Make a scope here so that the client and the server and other + stuff gets removed when disconnected or the irrlicht device + is removed. + */ + { + + /* + Draw "Loading" screen + */ const wchar_t *text = L"Loading and connecting..."; core::vector2d center(screenW/2, screenH/2); core::vector2d textsize(300, text_height); @@ -1533,27 +1717,14 @@ int main(int argc, char *argv[]) guienv->drawAll(); driver->endScene(); - /* - Preload some textures - */ - - init_content_inventory_texture_paths(); - init_tile_texture_paths(); - tile_materials_preload(g_irrlicht); - - /* - Make a scope here for the client so that it gets removed - before the irrlicht device - */ - { - std::cout< server; - if(hosting){ + if(address == ""){ server = new Server(map_dir, hm_params, map_params); server->start(port); } @@ -1562,18 +1733,24 @@ int main(int argc, char *argv[]) Create client */ - Client client(device, playername, draw_control); + Client client(device, playername.c_str(), draw_control); g_client = &client; Address connect_address(0,0,0,0, port); try{ - connect_address.Resolve(connect_name); + if(address == "") + connect_address.Resolve("localhost"); + else + connect_address.Resolve(address.c_str()); } catch(ResolveError &e) { std::cout<remove(); + continue; } std::cout<beginScene(true, true, video::SColor(255,0,0,0)); + guienv->drawAll(); + driver->endScene(); + + // Update client and server + client.step(0.1); - if(server != NULL){ + + if(server != NULL) server->step(0.1); - } + + // Delay a bit sleep_ms(100); } } catch(con::PeerNotFoundException &e) { std::cout<remove(); + continue; } /* @@ -1644,52 +1833,23 @@ int main(int argc, char *argv[]) GUIQuickInventory *quick_inventory = new GUIQuickInventory (guienv, NULL, v2s32(10, 70), 5, &local_inventory); - /* - We need some kind of a root node to be able to add - custom elements directly on the screen. - Otherwise they won't be automatically drawn. - */ - guiroot = guienv->addStaticText(L"", - core::rect(0, 0, 10000, 10000)); - // Test the text input system - /*(new GUITextInputMenu(guienv, guiroot, -1, &g_active_menu_count, + /*(new GUITextInputMenu(guienv, guiroot, -1, &g_menumgr, NULL))->drop();*/ /*GUIMessageMenu *menu = new GUIMessageMenu(guienv, guiroot, -1, - &g_active_menu_count, + &g_menumgr, L"Asd"); menu->drop();*/ // Launch pause menu - (new GUIPauseMenu(guienv, guiroot, -1, g_device, - &g_active_menu_count))->drop(); - - // First line of debug text - gui::IGUIStaticText *guitext = guienv->addStaticText( - L"Minetest-c55", - core::rect(5, 5, 795, 5+textsize.Y), - false, false); - // Second line of debug text - gui::IGUIStaticText *guitext2 = guienv->addStaticText( - L"", - core::rect(5, 5+(textsize.Y+5)*1, 795, (5+textsize.Y)*2), - false, false); + (new GUIPauseMenu(guienv, guiroot, -1, &g_gamecallback, + &g_menumgr))->drop(); - // At the middle of the screen - // Object infos are shown in this - gui::IGUIStaticText *guitext_info = guienv->addStaticText( - L"test", - core::rect(100, 70, 100+400, 70+(textsize.Y+5)), - false, false); - - // Chat text - gui::IGUIStaticText *chat_guitext = guienv->addStaticText( - L"Chat here\nOther line\nOther line\nOther line\nOther line", - core::rect(70, 60, 795, 150), - false, true); - chat_guitext->setBackgroundColor(video::SColor(96,0,0,0)); - core::list chat_lines; + // Enable texts + guitext2->setVisible(true); + guitext_info->setVisible(true); + guitext_chat->setVisible(true); /* Some statistics are collected in these @@ -1715,6 +1875,12 @@ int main(int argc, char *argv[]) while(device->run()) { + if(g_disconnect_requested) + { + g_disconnect_requested = false; + break; + } + /* Run global IrrlichtWrapper's main thread processing stuff */ @@ -2042,7 +2208,7 @@ int main(int argc, char *argv[]) narrow_to_wide(sign_object->getText()); (new GUITextInputMenu(guienv, guiroot, -1, - &g_active_menu_count, dest, + &g_menumgr, dest, wtext))->drop(); } } @@ -2519,7 +2685,7 @@ int main(int argc, char *argv[]) it = chat_lines.begin(); chat_lines.erase(it); } - chat_guitext->setText(whole.c_str()); + guitext_chat->setText(whole.c_str()); // Update gui element size and position core::rect rect( 10, @@ -2527,12 +2693,12 @@ int main(int argc, char *argv[]) screensize.X - 10, screensize.Y - 10 ); - chat_guitext->setRelativePosition(rect); + guitext_chat->setRelativePosition(rect); if(chat_lines.size() == 0) - chat_guitext->setVisible(false); + guitext_chat->setVisible(false); else - chat_guitext->setVisible(true); + guitext_chat->setVisible(true); } /* @@ -2667,22 +2833,7 @@ int main(int argc, char *argv[]) delete quick_inventory; - } // client is deleted at this point - - delete g_input; - - /* - In the end, delete the Irrlicht device. - */ - device->drop(); - - /* - Update configuration file - */ - /*if(configpath != "") - { - g_settings.updateConfigFile(configpath.c_str()); - }*/ + } // client and server are deleted at this point } //try catch(con::PeerNotFoundException &e) @@ -2693,7 +2844,7 @@ int main(int argc, char *argv[]) { GUIMessageMenu *menu = new GUIMessageMenu(guienv, guiroot, -1, - &g_active_menu_count, + &g_menumgr, L"Connection timed out"); video::IVideoDriver* driver = g_device->getVideoDriver(); @@ -2713,6 +2864,23 @@ int main(int argc, char *argv[]) }*/ } + } // Menu-game loop + + delete g_input; + + /* + In the end, delete the Irrlicht device. + */ + device->drop(); + + /* + Update configuration file + */ + /*if(configpath != "") + { + g_settings.updateConfigFile(configpath.c_str()); + }*/ + END_DEBUG_EXCEPTION_HANDLER debugstreams_deinit(); -- cgit v1.2.3