int main(int argc, char *argv[]) { int retval = 0; /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); // This enables internatonal characters input if( setlocale(LC_ALL, "") == NULL ) { fprintf( stderr, "%s: warning: could not set default locale\n", argv[0] ); } // Set locale. This is for forcing '.' as the decimal point. try { std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric)); setlocale(LC_NUMERIC, "C"); } catch (const std::exception& ex) { errorstream<<"Could not set numeric locale to C"<<std::endl; } /* Parse command line */ // List all allowed options core::map<std::string, ValueSpec> allowed_options; allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG, _("Show allowed options"))); allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, _("Load configuration from specified file"))); allowed_options.insert("port", ValueSpec(VALUETYPE_STRING, _("Set network port (UDP)"))); allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG, _("Disable unit tests"))); allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG, _("Enable unit tests"))); allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING, _("Same as --world (deprecated)"))); allowed_options.insert("world", ValueSpec(VALUETYPE_STRING, _("Set world path (implies local game) ('list' lists all)"))); allowed_options.insert("worldname", ValueSpec(VALUETYPE_STRING, _("Set world by name (implies local game)"))); allowed_options.insert("info", ValueSpec(VALUETYPE_FLAG, _("Print more information to console"))); allowed_options.insert("verbose", ValueSpec(VALUETYPE_FLAG, _("Print even more information to console"))); allowed_options.insert("trace", ValueSpec(VALUETYPE_FLAG, _("Print enormous amounts of information to log and console"))); allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING, _("Set logfile path ('' = no logging)"))); allowed_options.insert("gameid", ValueSpec(VALUETYPE_STRING, _("Set gameid (\"--gameid list\" prints available ones)"))); #ifndef SERVER allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG, _("Run speed tests"))); allowed_options.insert("address", ValueSpec(VALUETYPE_STRING, _("Address to connect to. ('' = local game)"))); allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG, _("Enable random user input, for testing"))); allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, _("Run dedicated server"))); allowed_options.insert("name", ValueSpec(VALUETYPE_STRING, _("Set player name"))); allowed_options.insert("password", ValueSpec(VALUETYPE_STRING, _("Set password"))); allowed_options.insert("go", ValueSpec(VALUETYPE_FLAG, _("Disable main menu"))); #endif Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help") || cmd_args.exists("nonopt1")) { dstream<<_("Allowed options:")<<std::endl; for(core::map<std::string, ValueSpec>::Iterator i = allowed_options.getIterator(); i.atEnd() == false; i++) { std::ostringstream os1(std::ios::binary); os1<<" --"<<i.getNode()->getKey(); if(i.getNode()->getValue().type == VALUETYPE_FLAG) {} else os1<<_(" <value>"); dstream<<padStringRight(os1.str(), 24); if(i.getNode()->getValue().help != NULL) dstream<<i.getNode()->getValue().help; dstream<<std::endl; } return cmd_args.getFlag("help") ? 0 : 1; } /* Low-level initialization */ // If trace is enabled, enable logging of certain things if(cmd_args.getFlag("trace")){ dstream<<_("Enabling trace level debug output")<<std::endl; log_trace_level_enabled = true; dout_con_ptr = &verbosestream; // this is somewhat old crap socket_enable_debug_output = true; // socket doesn't use log.h } // In certain cases, output info level on stderr if(cmd_args.getFlag("info") || cmd_args.getFlag("verbose") || cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests")) log_add_output(&main_stderr_log_out, LMT_INFO); // In certain cases, output verbose level on stderr if(cmd_args.getFlag("verbose") || cmd_args.getFlag("trace")) log_add_output(&main_stderr_log_out, LMT_VERBOSE); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_user); init_gettext((porting::path_share + DIR_DELIM + "locale").c_str()); infostream<<"path_share = "<<porting::path_share<<std::endl; infostream<<"path_user = "******"gameid") && cmd_args.get("gameid") == "list") { std::set<std::string> gameids = getAvailableGameIds(); for(std::set<std::string>::const_iterator i = gameids.begin(); i != gameids.end(); i++) dstream<<(*i)<<std::endl; return 0; } // List worlds if requested if(cmd_args.exists("world") && cmd_args.get("world") == "list"){ dstream<<_("Available worlds:")<<std::endl; std::vector<WorldSpec> worldspecs = getAvailableWorlds(); print_worldspecs(worldspecs, dstream); return 0; } // Print startup message infostream<<PROJECT_NAME<< " "<<_("with")<<" SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use std::string configpath = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } configpath = cmd_args.get("config"); } else { core::array<std::string> filenames; filenames.push_back(porting::path_user + DIR_DELIM + "minetest.conf"); // Legacy configuration file location filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #if RUN_IN_PLACE // Try also from a lower level (to aid having the same configuration // for many RUN_IN_PLACE installs) filenames.push_back(porting::path_user + DIR_DELIM + ".." + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { configpath = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(configpath == "") configpath = filenames[0]; } // Initialize debug streams #define DEBUGFILE "debug.txt" #if RUN_IN_PLACE std::string logfile = DEBUGFILE; #else std::string logfile = porting::path_user+DIR_DELIM+DEBUGFILE; #endif if(cmd_args.exists("logfile")) logfile = cmd_args.get("logfile"); log_remove_output(&main_dstream_no_stderr_log_out); int loglevel = g_settings->getS32("debug_log_level"); if (loglevel == 0) //no logging logfile = ""; else if (loglevel > 0 && loglevel <= LMT_NUM_VALUES) log_add_output_maxlev(&main_dstream_no_stderr_log_out, (LogMessageLevel)(loglevel - 1)); if(logfile != "") debugstreams_init(false, logfile.c_str()); else debugstreams_init(false, NULL); infostream<<"logfile = "<<logfile<<std::endl; // Initialize random seed srand(time(0)); mysrand(time(0)); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) commanded_world = cmd_args.get("world"); else if(cmd_args.exists("map-dir")) commanded_world = cmd_args.get("map-dir"); else if(cmd_args.exists("nonopt0")) // First nameless argument commanded_world = cmd_args.get("nonopt0"); else if(g_settings->exists("map-dir")) commanded_world = g_settings->get("map-dir"); // World name std::string commanded_worldname = ""; if(cmd_args.exists("worldname")) commanded_worldname = cmd_args.get("worldname"); // Strip world.mt from commanded_world { std::string worldmt = "world.mt"; if(commanded_world.size() > worldmt.size() && commanded_world.substr(commanded_world.size()-worldmt.size()) == worldmt){ dstream<<_("Supplied world.mt file - stripping it off.")<<std::endl; commanded_world = commanded_world.substr( 0, commanded_world.size()-worldmt.size()); } } // If a world name was specified, convert it to a path if(commanded_worldname != ""){ // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); bool found = false; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ if(commanded_world != ""){ dstream<<_("--worldname takes precedence over previously " "selected world.")<<std::endl; } commanded_world = worldspecs[i].path; found = true; break; } } if(!found){ dstream<<_("World")<<" '"<<commanded_worldname<<_("' not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // Gamespec SubgameSpec commanded_gamespec; if(cmd_args.exists("gameid")){ std::string gameid = cmd_args.get("gameid"); commanded_gamespec = findSubgame(gameid); if(!commanded_gamespec.isValid()){ errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl; return 1; } } /* Run dedicated server if asked to or no other option */ #ifdef SERVER bool run_dedicated_server = true; #else bool run_dedicated_server = cmd_args.getFlag("server"); #endif g_settings->set("server_dedicated", run_dedicated_server ? "true" : "false"); if(run_dedicated_server) { DSTACK("Dedicated server branch"); // Create time getter if built with Irrlicht #ifndef SERVER g_timegetter = new SimpleTimeGetter(); #endif // World directory std::string world_path; verbosestream<<_("Determining world path")<<std::endl; bool is_legacy_world = false; // If a world was commanded, use it if(commanded_world != ""){ world_path = commanded_world; infostream<<"Using commanded world path ["<<world_path<<"]" <<std::endl; } // No world was specified; try to select it automatically else { // Get information about available worlds std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If a world name was specified, select it if(commanded_worldname != ""){ world_path = ""; for(u32 i=0; i<worldspecs.size(); i++){ std::string name = worldspecs[i].name; if(name == commanded_worldname){ world_path = worldspecs[i].path; break; } } if(world_path == ""){ dstream<<_("World")<<" '"<<commanded_worldname<<"' "<<_("not " "available. Available worlds:")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; } } // If there is only a single world, use it if(worldspecs.size() == 1){ world_path = worldspecs[0].path; dstream<<_("Automatically selecting world at")<<" [" <<world_path<<"]"<<std::endl; // If there are multiple worlds, list them } else if(worldspecs.size() > 1){ dstream<<_("Multiple worlds are available.")<<std::endl; dstream<<_("Please select one using --worldname <name>" " or --world <path>")<<std::endl; print_worldspecs(worldspecs, dstream); return 1; // If there are no worlds, automatically create a new one } else { // This is the ultimate default world path world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "world"; infostream<<"Creating default world at [" <<world_path<<"]"<<std::endl; } } if(world_path == ""){ errorstream<<"No world path specified or found."<<std::endl; return 1; } verbosestream<<_("Using world path")<<" ["<<world_path<<"]"<<std::endl; // We need a gamespec. SubgameSpec gamespec; verbosestream<<_("Determining gameid/gamespec")<<std::endl; // If world doesn't exist if(!getWorldExists(world_path)) { // Try to take gamespec from command line if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; infostream<<"Using commanded gameid ["<<gamespec.id<<"]"<<std::endl; } // Otherwise we will be using "minetest" else{ gamespec = findSubgame(g_settings->get("default_game")); infostream<<"Using default gameid ["<<gamespec.id<<"]"<<std::endl; } } // World exists else { std::string world_gameid = getWorldGameId(world_path, is_legacy_world); // If commanded to use a gameid, do so if(commanded_gamespec.isValid()){ gamespec = commanded_gamespec; if(commanded_gamespec.id != world_gameid){ errorstream<<"WARNING: Using commanded gameid [" <<gamespec.id<<"]"<<" instead of world gameid [" <<world_gameid<<"]"<<std::endl; } } else{ // If world contains an embedded game, use it; // Otherwise find world from local system. gamespec = findWorldSubgame(world_path); infostream<<"Using world gameid ["<<gamespec.id<<"]"<<std::endl; } } if(!gamespec.isValid()){ errorstream<<"Subgame ["<<gamespec.id<<"] could not be found." <<std::endl; return 1; } verbosestream<<_("Using gameid")<<" ["<<gamespec.id<<"]"<<std::endl; // Create server Server server(world_path, configpath, gamespec, false); server.start(port); // Run server dedicated_server_loop(server, kill); return 0; } #ifndef SERVER // Exclude from dedicated server build /* More parameters */ std::string address = g_settings->get("address"); if(commanded_world != "") address = ""; else if(cmd_args.exists("address")) address = cmd_args.get("address"); std::string playername = g_settings->get("name"); if(cmd_args.exists("name")) playername = cmd_args.get("name"); bool skip_main_menu = cmd_args.getFlag("go"); /* Device initialization */ // Resolution selection bool fullscreen = g_settings->getBool("fullscreen"); u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // bpp, fsaa, vsync bool vsync = g_settings->getBool("vsync"); u16 bits = g_settings->getU16("fullscreen_bpp"); u16 fsaa = g_settings->getU16("fsaa"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* Create device and exit if creation failed */ MyEventReceiver receiver; IrrlichtDevice *device; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(screenW, screenH); params.Bits = bits; params.AntiAlias = fsaa; params.Fullscreen = fullscreen; params.Stencilbuffer = false; params.Vsync = vsync; params.EventReceiver = &receiver; device = createDeviceEx(params); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) input = new RandomInputHandler(); else input = new RealInputHandler(device, &receiver); scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); #if USE_FREETYPE std::string font_path = g_settings->get("font_path"); u16 font_size = g_settings->getU16("font_size"); gui::IGUIFont *font = gui::CGUITTFont::createTTFont(guienv, font_path.c_str(), font_size); #else gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); #endif if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255,70,100,50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255,255,255,255)); #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 // Irrlicht 1.8 input colours skin->setColor(gui::EGDC_EDITABLE, video::SColor(255,128,128,128)); skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49)); #endif /* GUI stuff */ ChatBackend chat_backend; /* 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""; // The password entered during the menu screen, std::string password; bool first_loop = true; /* Menu-game loop */ while(device->run() && kill == false) { // Set the window caption device->setWindowCaption((std::wstring(L"Minetest [")+wgettext("Main Menu")+L"]").c_str()); // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* 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<s32>(0, 0, 10000, 10000)); SubgameSpec gamespec; WorldSpec worldspec; bool simple_singleplayer_mode = false; // These are set up based on the menu and other things std::string current_playername = "inv£lid"; std::string current_password = ""; std::string current_address = "does-not-exist"; int current_port = 0; /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // If skip_main_menu, only go through here once if(skip_main_menu && !first_loop){ kill = true; break; } first_loop = false; // 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(); // Initialize menu data MainMenuData menudata; if(g_settings->exists("selected_mainmenu_tab")) menudata.selected_tab = g_settings->getS32("selected_mainmenu_tab"); menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); if(cmd_args.exists("password")) menudata.password = narrow_to_wide(cmd_args.get("password")); menudata.fancy_trees = g_settings->getBool("new_style_leaves"); menudata.smooth_lighting = g_settings->getBool("smooth_lighting"); menudata.clouds_3d = g_settings->getBool("enable_3d_clouds"); menudata.opaque_water = g_settings->getBool("opaque_water"); menudata.mip_map = g_settings->getBool("mip_map"); menudata.anisotropic_filter = g_settings->getBool("anisotropic_filter"); menudata.bilinear_filter = g_settings->getBool("bilinear_filter"); menudata.trilinear_filter = g_settings->getBool("trilinear_filter"); menudata.enable_shaders = g_settings->getS32("enable_shaders"); menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals"); menudata.enable_particles = g_settings->getBool("enable_particles"); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map); menudata.creative_mode = g_settings->getBool("creative_mode"); menudata.enable_damage = g_settings->getBool("enable_damage"); menudata.enable_public = g_settings->getBool("server_announce"); // Default to selecting nothing menudata.selected_world = -1; // Get world listing for the menu std::vector<WorldSpec> worldspecs = getAvailableWorlds(); // If there is only one world, select it if(worldspecs.size() == 1){ menudata.selected_world = 0; } // Otherwise try to select according to selected_world_path else if(g_settings->exists("selected_world_path")){ std::string trypath = g_settings->get("selected_world_path"); for(u32 i=0; i<worldspecs.size(); i++){ if(worldspecs[i].path == trypath){ menudata.selected_world = i; break; } } } // If a world was commanded, append and select it if(commanded_world != ""){ std::string gameid = getWorldGameId(commanded_world, true); std::string name = _("[--world parameter]"); if(gameid == ""){ gameid = g_settings->get("default_game"); name += " [new]"; } WorldSpec spec(commanded_world, name, gameid); worldspecs.push_back(spec); menudata.selected_world = worldspecs.size()-1; } // Copy worldspecs to menu menudata.worlds = worldspecs; if(skip_main_menu == false) { video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Waiting for other menus"<<std::endl; while(device->run() && kill == false) { if(noMenuActive()) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Waited for other menus"<<std::endl; GUIMainMenu *menu = new GUIMainMenu(guienv, guiroot, -1, &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); if(error_message != L"") { verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; GUIMessageMenu *menu2 = new GUIMessageMenu(guienv, guiroot, -1, &g_menumgr, error_message.c_str()); menu2->drop(); error_message = L""; } infostream<<"Created main menu"<<std::endl; while(device->run() && kill == false) { 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)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } infostream<<"Dropping main menu"<<std::endl; menu->drop(); } playername = wide_to_narrow(menudata.name); password = translatePassword(playername, menudata.password); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = wide_to_narrow(menudata.address); int newport = stoi(wide_to_narrow(menudata.port)); if(newport != 0) port = newport; simple_singleplayer_mode = menudata.simple_singleplayer_mode; // Save settings g_settings->setS32("selected_mainmenu_tab", menudata.selected_tab); 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)); g_settings->set("opaque_water", itos(menudata.opaque_water)); g_settings->set("mip_map", itos(menudata.mip_map)); g_settings->set("anisotropic_filter", itos(menudata.anisotropic_filter)); g_settings->set("bilinear_filter", itos(menudata.bilinear_filter)); g_settings->set("trilinear_filter", itos(menudata.trilinear_filter)); g_settings->setS32("enable_shaders", menudata.enable_shaders); g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals)); g_settings->set("enable_particles", itos(menudata.enable_particles)); g_settings->set("creative_mode", itos(menudata.creative_mode)); g_settings->set("enable_damage", itos(menudata.enable_damage)); g_settings->set("server_announce", itos(menudata.enable_public)); g_settings->set("name", playername); g_settings->set("address", address); g_settings->set("port", itos(port)); if(menudata.selected_world != -1) g_settings->set("selected_world_path", worldspecs[menudata.selected_world].path); // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; current_playername = playername; current_password = password; current_address = address; current_port = port; // If using simple singleplayer mode, override if(simple_singleplayer_mode){ current_playername = "singleplayer"; current_password = ""; current_address = ""; current_port = 30011; } else if (address != "") { ServerListSpec server; server["name"] = menudata.servername; server["address"] = wide_to_narrow(menudata.address); server["port"] = wide_to_narrow(menudata.port); server["description"] = menudata.serverdescription; ServerList::insert(server); } // Set world path to selected one if(menudata.selected_world != -1){ worldspec = worldspecs[menudata.selected_world]; infostream<<"Selected world: "<<worldspec.name <<" ["<<worldspec.path<<"]"<<std::endl; } // Only refresh if so requested if(menudata.only_refresh){ infostream<<"Refreshing menu"<<std::endl; continue; } // Create new world if requested if(menudata.create_world_name != L"") { std::string path = porting::path_user + DIR_DELIM "worlds" + DIR_DELIM + wide_to_narrow(menudata.create_world_name); // Create world if it doesn't exist if(!initializeWorld(path, menudata.create_world_gameid)){ error_message = wgettext("Failed to initialize world"); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } g_settings->set("selected_world_path", path); continue; } // If local game if(current_address == "") { if(menudata.selected_world == -1){ error_message = wgettext("No world selected and no address " "provided. Nothing to do."); errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } // Load gamespec for required game gamespec = findWorldSubgame(worldspec.path); if(!gamespec.isValid() && !commanded_gamespec.isValid()){ error_message = wgettext("Could not find or load game \"") + narrow_to_wide(worldspec.gameid) + L"\""; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } if(commanded_gamespec.isValid() && commanded_gamespec.id != worldspec.gameid){ errorstream<<"WARNING: Overriding gamespec from \"" <<worldspec.gameid<<"\" to \"" <<commanded_gamespec.id<<"\""<<std::endl; gamespec = commanded_gamespec; } if(!gamespec.isValid()){ error_message = wgettext("Invalid gamespec."); error_message += L" (world_gameid=" +narrow_to_wide(worldspec.gameid)+L")"; errorstream<<wide_to_narrow(error_message)<<std::endl; continue; } } // Continue to game break; } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; /* Run game */ the_game( kill, random_input, input, device, font, worldspec.path, current_playername, current_password, current_address, current_port, error_message, configpath, chat_backend, gamespec, simple_singleplayer_mode ); } //try catch(con::PeerNotFoundException &e) { error_message = wgettext("Connection error (timed out?)"); errorstream<<wide_to_narrow(error_message)<<std::endl; } catch(ServerError &e) { error_message = narrow_to_wide(e.what()); errorstream<<wide_to_narrow(error_message)<<std::endl; } catch(ModError &e) { errorstream<<e.what()<<std::endl; error_message = narrow_to_wide(e.what()) + wgettext("\nCheck debug.txt for details."); } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception: \""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif // If no main menu, show error and exit if(skip_main_menu) { if(error_message != L""){ verbosestream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; retval = 1; } break; } } // Menu-game loop delete input; /* In the end, delete the Irrlicht device. */ device->drop(); #endif // !SERVER // Update configuration file if(configpath != "") g_settings->updateConfigFile(configpath.c_str()); // Print modified quicktune values { bool header_printed = false; std::vector<std::string> names = getQuicktuneNames(); for(u32 i=0; i<names.size(); i++){ QuicktuneValue val = getQuicktuneValue(names[i]); if(!val.modified) continue; if(!header_printed){ dstream<<"Modified quicktune values:"<<std::endl; header_printed = true; } dstream<<names[i]<<" = "<<val.getString()<<std::endl; } } END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return retval; }
void drawItemStack(video::IVideoDriver *driver, gui::IGUIFont *font, const ItemStack &item, const core::rect<s32> &rect, const core::rect<s32> *clip, IGameDef *gamedef) { if(item.empty()) return; const ItemDefinition &def = item.getDefinition(gamedef->idef()); video::ITexture *texture = def.inventory_texture; // Draw the inventory texture if(texture != NULL) { const video::SColor color(255,255,255,255); const video::SColor colors[] = {color,color,color,color}; driver->draw2DImage(texture, rect, core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(texture->getOriginalSize())), clip, colors, true); } if(def.type == ITEM_TOOL && item.wear != 0) { // Draw a progressbar float barheight = rect.getHeight()/16; float barpad_x = rect.getWidth()/16; float barpad_y = rect.getHeight()/16; core::rect<s32> progressrect( rect.UpperLeftCorner.X + barpad_x, rect.LowerRightCorner.Y - barpad_y - barheight, rect.LowerRightCorner.X - barpad_x, rect.LowerRightCorner.Y - barpad_y); // Shrink progressrect by amount of tool damage float wear = item.wear / 65535.0; int progressmid = wear * progressrect.UpperLeftCorner.X + (1-wear) * progressrect.LowerRightCorner.X; // Compute progressbar color // wear = 0.0: green // wear = 0.5: yellow // wear = 1.0: red video::SColor color(255,255,255,255); int wear_i = MYMIN(floor(wear * 600), 511); wear_i = MYMIN(wear_i + 10, 511); if(wear_i <= 255) color.set(255, wear_i, 255, 0); else color.set(255, 255, 511-wear_i, 0); core::rect<s32> progressrect2 = progressrect; progressrect2.LowerRightCorner.X = progressmid; driver->draw2DRectangle(color, progressrect2, clip); color = video::SColor(255,0,0,0); progressrect2 = progressrect; progressrect2.UpperLeftCorner.X = progressmid; driver->draw2DRectangle(color, progressrect2, clip); } if(font != NULL && item.count >= 2) { // Get the item count as a string std::string text = itos(item.count); v2u32 dim = font->getDimension(narrow_to_wide(text).c_str()); v2s32 sdim(dim.X,dim.Y); core::rect<s32> rect2( /*rect.UpperLeftCorner, core::dimension2d<u32>(rect.getWidth(), 15)*/ rect.LowerRightCorner - sdim, sdim ); video::SColor bgcolor(128,0,0,0); driver->draw2DRectangle(bgcolor, rect2, clip); video::SColor color(255,255,255,255); font->draw(text.c_str(), rect2, color, false, false, clip); } }
void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) { video::IVideoDriver* driver = Environment->getVideoDriver(); // Get font gui::IGUIFont *font = NULL; gui::IGUISkin* skin = Environment->getSkin(); if (skin) font = skin->getFont(); Inventory *inv = m_invmgr->getInventory(s.inventoryloc); if(!inv){ infostream<<"GUIFormSpecMenu::drawList(): WARNING: " <<"The inventory location " <<"\""<<s.inventoryloc.dump()<<"\" doesn't exist" <<std::endl; return; } InventoryList *ilist = inv->getList(s.listname); if(!ilist){ infostream<<"GUIFormSpecMenu::drawList(): WARNING: " <<"The inventory list \""<<s.listname<<"\" @ \"" <<s.inventoryloc.dump()<<"\" doesn't exist" <<std::endl; return; } core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y); for(s32 i=0; i<s.geom.X*s.geom.Y; i++) { u32 item_i = i + s.start_item_i; if(item_i >= ilist->getSize()) break; s32 x = (i%s.geom.X) * spacing.X; s32 y = (i/s.geom.X) * spacing.Y; v2s32 p(x,y); core::rect<s32> rect = imgrect + s.pos + p; ItemStack item; if(ilist) item = ilist->getItem(item_i); bool selected = m_selected_item && m_invmgr->getInventory(m_selected_item->inventoryloc) == inv && m_selected_item->listname == s.listname && m_selected_item->i == i; bool hovering = rect.isPointInside(m_pointer); if(phase == 0) { if(hovering && m_selected_item) { video::SColor bgcolor(255,192,192,192); driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect); } else { video::SColor bgcolor(255,128,128,128); driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect); } } if(phase == 1) { // Draw item stack if(selected) { item.takeItem(m_selected_amount); } if(!item.empty()) { drawItemStack(driver, font, item, rect, &AbsoluteClippingRect, m_gamedef); } // Draw tooltip std::string tooltip_text = ""; if(hovering && !m_selected_item) tooltip_text = item.getDefinition(m_gamedef->idef()).description; if(tooltip_text != "") { m_tooltip_element->setVisible(true); this->bringToFront(m_tooltip_element); m_tooltip_element->setText(narrow_to_wide(tooltip_text).c_str()); s32 tooltip_x = m_pointer.X + 15; s32 tooltip_y = m_pointer.Y + 15; s32 tooltip_width = m_tooltip_element->getTextWidth() + 15; s32 tooltip_height = m_tooltip_element->getTextHeight() + 5; m_tooltip_element->setRelativePosition(core::rect<s32>( core::position2d<s32>(tooltip_x, tooltip_y), core::dimension2d<s32>(tooltip_width, tooltip_height))); } } } }
void ChatPrompt::nickCompletion(const std::list<std::string>& names, bool backwards) { // Two cases: // (a) m_nick_completion_start == m_nick_completion_end == 0 // Then no previous nick completion is active. // Get the word around the cursor and replace with any nick // that has that word as a prefix. // (b) else, continue a previous nick completion. // m_nick_completion_start..m_nick_completion_end are the // interval where the originally used prefix was. Cycle // through the list of completions of that prefix. u32 prefix_start = m_nick_completion_start; u32 prefix_end = m_nick_completion_end; bool initial = (prefix_end == 0); if (initial) { // no previous nick completion is active prefix_start = prefix_end = m_cursor; while (prefix_start > 0 && !std::isspace(m_line[prefix_start-1])) --prefix_start; while (prefix_end < m_line.size() && !std::isspace(m_line[prefix_end])) ++prefix_end; if (prefix_start == prefix_end) return; } std::wstring prefix = m_line.substr(prefix_start, prefix_end - prefix_start); // find all names that start with the selected prefix std::vector<std::wstring> completions; for (std::list<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) { if (str_starts_with(narrow_to_wide(*i), prefix, true)) { std::wstring completion = narrow_to_wide(*i); if (prefix_start == 0) completion += L": "; completions.push_back(completion); } } if (completions.empty()) return; // find a replacement string and the word that will be replaced u32 word_end = prefix_end; u32 replacement_index = 0; if (!initial) { while (word_end < m_line.size() && !std::isspace(m_line[word_end])) ++word_end; std::wstring word = m_line.substr(prefix_start, word_end - prefix_start); // cycle through completions for (u32 i = 0; i < completions.size(); ++i) { if (str_equal(word, completions[i], true)) { if (backwards) replacement_index = i + completions.size() - 1; else replacement_index = i + 1; replacement_index %= completions.size(); break; } } } std::wstring replacement = completions[replacement_index]; if (word_end < m_line.size() && std::isspace(word_end)) ++word_end; // replace existing word with replacement word, // place the cursor at the end and record the completion prefix m_line.replace(prefix_start, word_end - prefix_start, replacement); m_cursor = prefix_start + replacement.size(); clampView(); m_nick_completion_start = prefix_start; m_nick_completion_end = prefix_end; }
void GUIFormSpecMenu::regenerateGui(v2u32 screensize) { // Remove children removeChildren(); v2s32 size(100,100); s32 helptext_h = 15; core::rect<s32> rect; // Base position of contents of form v2s32 basepos = getBasePos(); // State of basepos, 0 = not set, 1= set by formspec, 2 = set by size[] element // Used to adjust form size automatically if needed // A proceed button is added if there is no size[] element int bp_set = 0; /* Convert m_init_draw_spec to m_inventorylists */ m_inventorylists.clear(); m_images.clear(); m_fields.clear(); Strfnd f(m_formspec_string); while(f.atend() == false) { std::string type = trim(f.next("[")); if(type == "invsize" || type == "size") { v2f invsize; invsize.X = stof(f.next(",")); if(type == "size") { invsize.Y = stof(f.next("]")); } else{ invsize.Y = stof(f.next(";")); f.next("]"); } infostream<<"Form size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl; padding = v2s32(screensize.Y/40, screensize.Y/40); spacing = v2s32(screensize.Y/12, screensize.Y/13); imgsize = v2s32(screensize.Y/15, screensize.Y/15); size = v2s32( padding.X*2+spacing.X*(invsize.X-1.0)+imgsize.X, padding.Y*2+spacing.Y*(invsize.Y-1.0)+imgsize.Y + (helptext_h-5) ); rect = core::rect<s32>( screensize.X/2 - size.X/2, screensize.Y/2 - size.Y/2, screensize.X/2 + size.X/2, screensize.Y/2 + size.Y/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); basepos = getBasePos(); bp_set = 2; } else if(type == "list") { std::string name = f.next(";"); InventoryLocation loc; if(name == "context" || name == "current_name") loc = m_current_inventory_location; else loc.deSerialize(name); std::string listname = f.next(";"); v2s32 pos = basepos; pos.X += stof(f.next(",")) * (float)spacing.X; pos.Y += stof(f.next(";")) * (float)spacing.Y; v2s32 geom; geom.X = stoi(f.next(",")); geom.Y = stoi(f.next(";")); infostream<<"list inv="<<name<<", listname="<<listname <<", pos=("<<pos.X<<","<<pos.Y<<")" <<", geom=("<<geom.X<<","<<geom.Y<<")" <<std::endl; std::string start_i_s = f.next("]"); s32 start_i = 0; if(start_i_s != "") start_i = stoi(start_i_s); if(bp_set != 2) errorstream<<"WARNING: invalid use of list without a size[] element"<<std::endl; m_inventorylists.push_back(ListDrawSpec(loc, listname, pos, geom, start_i)); } else if(type == "image") { v2s32 pos = basepos; pos.X += stof(f.next(",")) * (float)spacing.X; pos.Y += stof(f.next(";")) * (float)spacing.Y; v2s32 geom; geom.X = stof(f.next(",")) * (float)imgsize.X; geom.Y = stof(f.next(";")) * (float)imgsize.Y; std::string name = f.next("]"); infostream<<"image name="<<name <<", pos=("<<pos.X<<","<<pos.Y<<")" <<", geom=("<<geom.X<<","<<geom.Y<<")" <<std::endl; if(bp_set != 2) errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; m_images.push_back(ImageDrawSpec(name, pos, geom)); } else if(type == "field") { std::string fname = f.next(";"); std::string flabel = f.next(";"); if(fname.find(",") == std::string::npos && flabel.find(",") == std::string::npos) { if(!bp_set) { rect = core::rect<s32>( screensize.X/2 - 580/2, screensize.Y/2 - 300/2, screensize.X/2 + 580/2, screensize.Y/2 + 300/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); basepos = getBasePos(); bp_set = 1; } else if(bp_set == 2) errorstream<<"WARNING: invalid use of unpositioned field in inventory"<<std::endl; v2s32 pos = basepos; pos.Y = ((m_fields.size()+2)*60); v2s32 size = DesiredRect.getSize(); rect = core::rect<s32>(size.X/2-150, pos.Y, (size.X/2-150)+300, pos.Y+30); } else { v2s32 pos; pos.X = stof(fname.substr(0,fname.find(","))) * (float)spacing.X; pos.Y = stof(fname.substr(fname.find(",")+1)) * (float)spacing.Y; v2s32 geom; geom.X = (stof(flabel.substr(0,flabel.find(","))) * (float)spacing.X)-(spacing.X-imgsize.X); pos.Y += (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y)/2; rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); fname = f.next(";"); flabel = f.next(";"); if(bp_set != 2) errorstream<<"WARNING: invalid use of positioned field without a size[] element"<<std::endl; } std::string odefault = f.next("]"); std::string fdefault; // fdefault may contain a variable reference, which // needs to be resolved from the node metadata if(m_form_src) fdefault = m_form_src->resolveText(odefault); else fdefault = odefault; FieldSpec spec = FieldSpec( narrow_to_wide(fname.c_str()), narrow_to_wide(flabel.c_str()), narrow_to_wide(fdefault.c_str()), 258+m_fields.size() ); // three cases: field and no label, label and no field, label and field if (flabel == "") { spec.send = true; gui::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); Environment->setFocus(e); irr::SEvent evt; evt.EventType = EET_KEY_INPUT_EVENT; evt.KeyInput.Key = KEY_END; evt.KeyInput.PressedDown = true; e->OnEvent(evt); } else if (fname == "") { // set spec field id to 0, this stops submit searching for a value that isn't there Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); } else { spec.send = true; gui::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); Environment->setFocus(e); rect.UpperLeftCorner.Y -= 15; rect.LowerRightCorner.Y -= 15; Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0); irr::SEvent evt; evt.EventType = EET_KEY_INPUT_EVENT; evt.KeyInput.Key = KEY_END; evt.KeyInput.PressedDown = true; e->OnEvent(evt); } m_fields.push_back(spec); } else if(type == "label") { v2s32 pos = padding; pos.X += stof(f.next(",")) * (float)spacing.X; pos.Y += stof(f.next(";")) * (float)spacing.Y; rect = core::rect<s32>(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15)); std::string flabel = f.next("]"); if(bp_set != 2) errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl; FieldSpec spec = FieldSpec( narrow_to_wide(""), narrow_to_wide(flabel.c_str()), narrow_to_wide(""), 258+m_fields.size() ); Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); m_fields.push_back(spec); } else if(type == "button" || type == "button_exit") { v2s32 pos = padding; pos.X += stof(f.next(",")) * (float)spacing.X; pos.Y += stof(f.next(";")) * (float)spacing.Y; v2s32 geom; geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X); pos.Y += (stof(f.next(";")) * (float)imgsize.Y)/2; rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); std::string fname = f.next(";"); std::string flabel = f.next("]"); if(bp_set != 2) errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; FieldSpec spec = FieldSpec( narrow_to_wide(fname.c_str()), narrow_to_wide(flabel.c_str()), narrow_to_wide(""), 258+m_fields.size() ); spec.is_button = true; if(type == "button_exit") spec.is_exit = true; Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); m_fields.push_back(spec); } else if(type == "image_button" || type == "image_button_exit") { v2s32 pos = padding; pos.X += stof(f.next(",")) * (float)spacing.X; pos.Y += stof(f.next(";")) * (float)spacing.Y; v2s32 geom; geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X); geom.Y = (stof(f.next(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y); rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); std::string fimage = f.next(";"); std::string fname = f.next(";"); std::string flabel = f.next("]"); if(bp_set != 2) errorstream<<"WARNING: invalid use of image_button without a size[] element"<<std::endl; FieldSpec spec = FieldSpec( narrow_to_wide(fname.c_str()), narrow_to_wide(flabel.c_str()), narrow_to_wide(fimage.c_str()), 258+m_fields.size() ); spec.is_button = true; if(type == "image_button_exit") spec.is_exit = true; video::ITexture *texture = m_gamedef->tsrc()->getTextureRaw(fimage); gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); e->setImage(texture); e->setPressedImage(texture); e->setScaleImage(true); m_fields.push_back(spec); } else { // Ignore others std::string ts = f.next("]"); infostream<<"Unknown DrawSpec: type="<<type<<", data=\""<<ts<<"\"" <<std::endl; } } // If there's inventory, put the usage string at the bottom if (m_inventorylists.size()) { changeCtype(""); core::rect<s32> rect(0, 0, size.X-padding.X*2, helptext_h); rect = rect + v2s32(size.X/2 - rect.getWidth()/2, size.Y-rect.getHeight()-5); const wchar_t *text = wgettext("Left click: Move all items, Right click: Move single item"); Environment->addStaticText(text, rect, false, true, this, 256); changeCtype("C"); } // If there's fields, add a Proceed button if (m_fields.size() && bp_set != 2) { // if the size wasn't set by an invsize[] or size[] adjust it now to fit all the fields rect = core::rect<s32>( screensize.X/2 - 580/2, screensize.Y/2 - 300/2, screensize.X/2 + 580/2, screensize.Y/2 + 240/2+(m_fields.size()*60) ); DesiredRect = rect; recalculateAbsolutePosition(false); basepos = getBasePos(); changeCtype(""); { v2s32 pos = basepos; pos.Y = ((m_fields.size()+2)*60); v2s32 size = DesiredRect.getSize(); rect = core::rect<s32>(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+30); Environment->addButton(rect, this, 257, wgettext("Proceed")); } changeCtype("C"); } // Add tooltip { // Note: parent != this so that the tooltip isn't clipped by the menu rectangle m_tooltip_element = Environment->addStaticText(L"",core::rect<s32>(0,0,110,18)); m_tooltip_element->enableOverrideColor(true); m_tooltip_element->setBackgroundColor(video::SColor(255,110,130,60)); m_tooltip_element->setDrawBackground(true); m_tooltip_element->setDrawBorder(true); m_tooltip_element->setOverrideColor(video::SColor(255,255,255,255)); m_tooltip_element->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); m_tooltip_element->setWordWrap(false); } }
bool GUIKeyChangeMenu::resetMenu() { if (activeKey >= 0) { switch (activeKey) { case GUI_ID_KEY_FORWARD_BUTTON: this->forward->setText( narrow_to_wide(KeyNames[key_forward]).c_str()); break; case GUI_ID_KEY_BACKWARD_BUTTON: this->backward->setText( narrow_to_wide(KeyNames[key_backward]).c_str()); break; case GUI_ID_KEY_LEFT_BUTTON: this->left->setText(narrow_to_wide(KeyNames[key_left]).c_str()); break; case GUI_ID_KEY_RIGHT_BUTTON: this->right->setText(narrow_to_wide(KeyNames[key_right]).c_str()); break; case GUI_ID_KEY_JUMP_BUTTON: this->jump->setText(narrow_to_wide(KeyNames[key_jump]).c_str()); break; case GUI_ID_KEY_SNEAK_BUTTON: this->sneak->setText(narrow_to_wide(KeyNames[key_sneak]).c_str()); break; case GUI_ID_KEY_INVENTORY_BUTTON: this->inventory->setText( narrow_to_wide(KeyNames[key_inventory]).c_str()); break; case GUI_ID_KEY_CHAT_BUTTON: this->chat->setText(narrow_to_wide(KeyNames[key_chat]).c_str()); break; case GUI_ID_KEY_RANGE_BUTTON: this->range->setText(narrow_to_wide(KeyNames[key_range]).c_str()); break; case GUI_ID_KEY_FLY_BUTTON: this->fly->setText(narrow_to_wide(KeyNames[key_fly]).c_str()); break; case GUI_ID_KEY_FAST_BUTTON: this->fast->setText(narrow_to_wide(KeyNames[key_fast]).c_str()); break; case GUI_ID_KEY_USE_BUTTON: this->use->setText(narrow_to_wide(KeyNames[key_use]).c_str()); break; case GUI_ID_KEY_DUMP_BUTTON: this->dump->setText(narrow_to_wide(KeyNames[key_dump]).c_str()); break; } activeKey = -1; return false; } return true; }
void GUIMainMenu::regenerateGui(v2u32 screensize) { m_is_regenerating = true; /* Read stuff from elements into m_data */ readInput(m_data); /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ v2s32 size(screensize.X, screensize.Y); core::rect<s32> rect( screensize.X/2 - size.X/2, screensize.Y/2 - size.Y/2, screensize.X/2 + size.X/2, screensize.Y/2 + size.Y/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); //v2s32 size = rect.getSize(); /* Add stuff */ changeCtype(""); // Version { core::rect<s32> rect(0, 0, size.X, 40); rect += v2s32(4, 0); std::string t = "Minetest " VERSION_STRING; if(m_data->selected_game_name != "" && m_data->selected_tab == TAB_SINGLEPLAYER){ t += "/"; t += m_data->selected_game_name; } Environment->addStaticText(narrow_to_wide(t).c_str(), rect, false, true, this, -1); } //v2s32 center(size.X/2, size.Y/2); v2s32 c800(size.X/2-400, size.Y/2-270); m_topleft_client = c800 + v2s32(90, 70+50+30); m_size_client = v2s32(620, 270); m_size_server = v2s32(620, 140); if(m_data->selected_tab == TAB_ADVANCED) { m_topleft_client = c800 + v2s32(90, 70+50+30); m_size_client = v2s32(620, 200); m_size_server = v2s32(620, 140); } m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20); // Tabs { core::rect<s32> rect(0, 0, m_size_client.X, 30); rect += m_topleft_client + v2s32(0, -30); gui::IGUITabControl *e = Environment->addTabControl( rect, this, true, true, GUI_ID_TAB_CONTROL); wchar_t* text = wgettext("Singleplayer"); e->addTab(text); delete[] text; text = wgettext("Multiplayer"); e->addTab(text); delete[] text; text = wgettext("Advanced"); e->addTab(text); delete[] text; text = wgettext("Settings"); e->addTab(text); delete[] text; text = wgettext("Credits"); e->addTab(text); delete[] text; e->setActiveTab(m_data->selected_tab); } if(m_data->selected_tab == TAB_SINGLEPLAYER) { // HYBRID { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); //const wchar_t *text = L"H\nY\nB\nR\nI\nD"; const wchar_t *text = L"S\nI\nN\nG\nL\nE\n \nP\nL\nA\nY\nE\nR\n"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } u32 bs = 5; // World selection listbox u32 world_sel_h = 160; u32 world_sel_w = 365; //s32 world_sel_x = 50; s32 world_sel_x = m_size_client.X-world_sel_w-30; s32 world_sel_y = 30; u32 world_button_count = 3; u32 world_button_w = (world_sel_w)/world_button_count - bs + bs/(world_button_count-1); { core::rect<s32> rect(0, 0, world_sel_w-4, 20); rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20); wchar_t* text = wgettext("Select World:"); /*gui::IGUIStaticText *e =*/ Environment->addStaticText( text, rect, false, true, this, -1); delete[] text; /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/ } { core::rect<s32> rect(0, 0, world_sel_w, world_sel_h); rect += m_topleft_client + v2s32(world_sel_x, world_sel_y); gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); m_world_indices.clear(); for(size_t wi = 0; wi < m_data->worlds.size(); wi++){ const WorldSpec &spec = m_data->worlds[wi]; if(spec.gameid == m_data->selected_game){ //e->addItem(narrow_to_wide(spec.name+" ["+spec.gameid+"]").c_str()); e->addItem(narrow_to_wide(spec.name).c_str()); m_world_indices.push_back(wi); if(m_data->selected_world == (int)wi) e->setSelected(m_world_indices.size()-1); } } Environment->setFocus(e); } // Delete world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0); wchar_t* text = wgettext("Delete"); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, text); delete[] text; } // Create world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0); wchar_t* text = wgettext("New"); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, text); delete[] text; } // Configure world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2, world_sel_y+world_sel_h+0); wchar_t* text = wgettext("Configure"); Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON, text); delete[] text; } // Start game button { /*core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3, world_sel_y+world_sel_h+0);*/ u32 bw = 160; /*core::rect<s32> rect(0, 0, bw, 30); rect += m_topleft_client + v2s32(m_size_client.X-bw-30, m_size_client.Y-30-15);*/ core::rect<s32> rect(0, 0, bw, 30); rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw, world_sel_y+world_sel_h+30+bs); wchar_t* text = wgettext("Play"); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, text); delete[] text; } // Options s32 option_x = 50; //s32 option_x = 50+world_sel_w+20; s32 option_y = 30; u32 option_w = 150; { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*0); wchar_t* text = wgettext("Creative Mode"); Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*1); wchar_t* text = wgettext("Enable Damage"); Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB, text); delete[] text; } changeCtype("C"); /* 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); } } } else if(m_data->selected_tab == TAB_MULTIPLAYER) { changeCtype(""); // CLIENT { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password { core::rect<s32> rect(0, 0, 110, 20); wchar_t* text = wgettext("Name/Password"); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6); Environment->addStaticText(text, rect, false, true, this, -1); delete [] text; } changeCtype("C"); { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50); gui::IGUIElement *e = Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT); if(m_data->name == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90); gui::IGUIEditBox *e = Environment->addEditBox(L"", rect, true, this, 264); e->setPasswordBox(true); if(m_data->name != L"" && m_data->address != L"") Environment->setFocus(e); } changeCtype(""); // Server List { core::rect<s32> rect(0, 0, 390, 140); rect += m_topleft_client + v2s32(50, 30); gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_SERVERLIST); e->setDrawBackground(true); #if USE_CURL if(m_data->selected_serverlist == SERVERLIST_FAVORITES) { m_data->servers = ServerList::getLocal(); { core::rect<s32> rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); wchar_t* text = wgettext("Favorites:"); Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); delete[] text; } } else { m_data->servers = ServerList::getOnline(); { core::rect<s32> rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); wchar_t* text = wgettext("Public Server List:"); Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); delete[] text; } } #else m_data->servers = ServerList::getLocal(); { core::rect<s32> rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); wchar_t* text = wgettext("Favorites:"); Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); delete[] text; } #endif updateGuiServerList(); e->setSelected(0); } // Address + port { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6); wchar_t* text = wgettext("Address/Port"); Environment->addStaticText(text, rect, false, true, this, -1); delete [] text; } changeCtype("C"); { core::rect<s32> rect(0, 0, 260, 30); rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15); gui::IGUIElement *e = Environment->addEditBox(m_data->address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(m_data->name != L"" && m_data->address == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15); Environment->addEditBox(m_data->port.c_str(), rect, true, this, GUI_ID_PORT_INPUT); } changeCtype(""); #if USE_CURL // Toggle Serverlist (Favorites/Online) { core::rect<s32> rect(0, 0, 260, 30); rect += m_topleft_client + v2s32(50, 180); wchar_t* text = wgettext("Show Public"); gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE, text); delete[] text; e->setIsPushButton(true); if (m_data->selected_serverlist == SERVERLIST_PUBLIC) { wchar_t* text = wgettext("Show Favorites"); e->setText(text); e->setPressed(); delete[] text; } } #endif // Delete Local Favorite { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(50+260+10, 180); wchar_t* text = wgettext("Delete"); gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE, text); if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // Hidden when on public list e->setVisible(false); delete [] text; } // Start game button { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-130-30, m_size_client.Y-25-15); wchar_t* text = wgettext("Connect"); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, text); delete[] text; } changeCtype("C"); } else if(m_data->selected_tab == TAB_ADVANCED) { changeCtype(""); // CLIENT { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 35+6); wchar_t* text = wgettext("Name/Password"); Environment->addStaticText(text, rect, false, true, this, -1); delete [] text; } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 35); gui::IGUIElement *e = Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT); if(m_data->name == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35); gui::IGUIEditBox *e = Environment->addEditBox(L"", rect, true, this, 264); e->setPasswordBox(true); if(m_data->name != L"" && m_data->address != L"") Environment->setFocus(e); } changeCtype(""); // Address + port { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 75+6); wchar_t* text = wgettext("Address/Port"); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 75); gui::IGUIElement *e = Environment->addEditBox(m_data->address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(m_data->name != L"" && m_data->address == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75); Environment->addEditBox(m_data->port.c_str(), rect, true, this, GUI_ID_PORT_INPUT); } changeCtype(""); { core::rect<s32> rect(0, 0, 400, 20); rect += m_topleft_client + v2s32(160+30, 75+35); wchar_t* text = wgettext("Leave address blank to start a local server."); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; } // Start game button { core::rect<s32> rect(0, 0, 180, 30); rect += m_topleft_client + v2s32(m_size_client.X-180-30, m_size_client.Y-30-20); wchar_t* text = wgettext("Start Game / Connect"); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, text); delete[] text; } /* Server section */ // SERVER { core::rect<s32> rect(0, 0, 10, m_size_server.Y); rect += m_topleft_server + v2s32(15, 0); const wchar_t *text = L"S\nE\nR\nV\nE\nR"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Server parameters { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 20); wchar_t* text = wgettext("Creative Mode"); Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 40); wchar_t* text = wgettext("Enable Damage"); Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB, text); delete[] text; } #if USE_CURL { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 60); wchar_t* text = wgettext("Public"); Environment->addCheckBox(m_data->enable_public, rect, this, GUI_ID_PUBLIC_CB, text); delete[] text; } #endif // Delete world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20, 90); wchar_t* text = wgettext("Delete world"); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, text ); delete[] text; } // Create world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20+140, 90); wchar_t* text = wgettext("Create world"); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, text ); delete[] text; } // World selection listbox { core::rect<s32> rect(0, 0, 250, 120); rect += m_topleft_server + v2s32(30+20, 10); gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); m_world_indices.clear(); for(size_t wi = 0; wi < m_data->worlds.size(); wi++){ const WorldSpec &spec = m_data->worlds[wi]; e->addItem(narrow_to_wide(spec.name+" ["+spec.gameid+"]").c_str()); m_world_indices.push_back(wi); } e->setSelected(m_data->selected_world); } changeCtype("C"); } else if(m_data->selected_tab == TAB_SETTINGS) { { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } s32 option_x = 70; s32 option_y = 50; u32 option_w = 150; { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y); wchar_t* text = wgettext("Fancy trees"); Environment->addCheckBox(m_data->fancy_trees, rect, this, GUI_ID_FANCYTREE_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20); wchar_t* text = wgettext("Smooth Lighting"); Environment->addCheckBox(m_data->smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*2); wchar_t* text = wgettext("3D Clouds"); Environment->addCheckBox(m_data->clouds_3d, rect, this, GUI_ID_3D_CLOUDS_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*3); wchar_t* text = wgettext("Opaque water"); Environment->addCheckBox(m_data->opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB, text); delete[] text; } // Anisotropic/mipmap/bi-/trilinear settings { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y); wchar_t* text = wgettext("Mip-Mapping"); Environment->addCheckBox(m_data->mip_map, rect, this, GUI_ID_MIPMAP_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20); wchar_t* text = wgettext("Anisotropic Filtering"); Environment->addCheckBox(m_data->anisotropic_filter, rect, this, GUI_ID_ANISOTROPIC_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20*2); wchar_t* text = wgettext("Bi-Linear Filtering"); Environment->addCheckBox(m_data->bilinear_filter, rect, this, GUI_ID_BILINEAR_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175, option_y+20*3); wchar_t* text = wgettext("Tri-Linear Filtering"); Environment->addCheckBox(m_data->trilinear_filter, rect, this, GUI_ID_TRILINEAR_CB, text); delete[] text; } // shader/on demand image loading/particles settings { core::rect<s32> rect(0, 0, option_w+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y); wchar_t* text = wgettext("Shaders"); Environment->addCheckBox(m_data->enable_shaders, rect, this, GUI_ID_SHADERS_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20); wchar_t* text = wgettext("Preload item visuals"); Environment->addCheckBox(m_data->preload_item_visuals, rect, this, GUI_ID_PRELOAD_ITEM_VISUALS_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2); wchar_t* text = wgettext("Enable Particles"); Environment->addCheckBox(m_data->enable_particles, rect, this, GUI_ID_ENABLE_PARTICLES_CB, text); delete[] text; } { core::rect<s32> rect(0, 0, option_w+20+20, 30); rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*3); wchar_t* text = wgettext("Finite liquid"); Environment->addCheckBox(m_data->liquid_finite, rect, this, GUI_ID_LIQUID_FINITE_CB, text); delete[] text; } // Key change button { core::rect<s32> rect(0, 0, 120, 30); /*rect += m_topleft_client + v2s32(m_size_client.X-120-30, m_size_client.Y-30-20);*/ rect += m_topleft_client + v2s32(option_x, option_y+120); wchar_t* text = wgettext("Change keys"); Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON, text); delete[] text; } changeCtype("C"); } else if(m_data->selected_tab == TAB_CREDITS) { // CREDITS { core::rect<s32> rect(0, 0, 9, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } { core::rect<s32> rect(0, 0, 130, 70); rect += m_topleft_client + v2s32(35, 160); Environment->addStaticText( L"Minetest " LSTRING(VERSION_STRING) L"\nhttp://minetest.net/", rect, false, true, this, -1); } { video::SColor yellow(255, 255, 255, 0); core::rect<s32> rect(0, 0, 450, 260); rect += m_topleft_client + v2s32(168, 5); irr::gui::IGUIListBox *list = Environment->addListBox(rect, this); list->addItem(L"Core Developers"); list->setItemOverrideColor(list->getItemCount() - 1, yellow); for (int i = 0; i != ARRAYLEN(contrib_core_strs); i++) list->addItem(contrib_core_strs[i]); list->addItem(L""); list->addItem(L"Active Contributors"); list->setItemOverrideColor(list->getItemCount() - 1, yellow); for (int i = 0; i != ARRAYLEN(contrib_active_strs); i++) list->addItem(contrib_active_strs[i]); list->addItem(L""); list->addItem(L"Previous Contributors"); list->setItemOverrideColor(list->getItemCount() - 1, yellow); for (int i = 0; i != ARRAYLEN(contrib_previous_strs); i++) list->addItem(contrib_previous_strs[i]); list->addItem(L""); } } m_is_regenerating = false; }
void GUIMainMenu::regenerateGui(v2u32 screensize) { m_is_regenerating = true; /* Read stuff from elements into m_data */ readInput(m_data); /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ v2s32 size(screensize.X, screensize.Y); core::rect<s32> rect( screensize.X/2 - size.X/2, screensize.Y/2 - size.Y/2, screensize.X/2 + size.X/2, screensize.Y/2 + size.Y/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); //v2s32 size = rect.getSize(); /* Add stuff */ changeCtype(""); // Version //if(m_data->selected_tab != TAB_CREDITS) { core::rect<s32> rect(0, 0, size.X, 40); rect += v2s32(4, 0); Environment->addStaticText(narrow_to_wide( "BlockPlanet " VERSION_STRING).c_str(), rect, false, true, this, -1); } //v2s32 center(size.X/2, size.Y/2); v2s32 c800(size.X/2-400, size.Y/2-300); m_topleft_client = c800 + v2s32(90, 70+50+30); m_size_client = v2s32(620, 270); m_size_server = v2s32(620, 140); if(m_data->selected_tab == TAB_ADVANCED) { m_topleft_client = c800 + v2s32(90, 70+50+30); m_size_client = v2s32(620, 200); m_size_server = v2s32(620, 140); } m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20); // Tabs #if 1 { core::rect<s32> rect(0, 0, m_size_client.X, 30); rect += m_topleft_client + v2s32(0, -30); gui::IGUITabControl *e = Environment->addTabControl( rect, this, true, true, GUI_ID_TAB_CONTROL); e->addTab(L"Singleplayer"); e->addTab(L"Multiplayer"); e->addTab(L"Advanced"); e->addTab(L"Settings"); e->addTab(L"Credits"); e->setActiveTab(m_data->selected_tab); } #endif if(m_data->selected_tab == TAB_SINGLEPLAYER) { // HYBRID { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); //const wchar_t *text = L"H\nY\nB\nR\nI\nD"; const wchar_t *text = L"S\nI\nG\nL\nE\nP\nL\nA\nY\nE\nR"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } u32 bs = 5; // World selection listbox u32 world_sel_h = 160; u32 world_sel_w = 365; //s32 world_sel_x = 50; s32 world_sel_x = m_size_client.X-world_sel_w-30; s32 world_sel_y = 30; u32 world_button_count = 3; u32 world_button_w = (world_sel_w)/world_button_count - bs + bs/(world_button_count-1); { core::rect<s32> rect(0, 0, world_sel_w-4, 20); rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20); /*gui::IGUIStaticText *e =*/ Environment->addStaticText( wgettext("Select World:"), rect, false, true, this, -1); /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/ } { core::rect<s32> rect(0, 0, world_sel_w, world_sel_h); rect += m_topleft_client + v2s32(world_sel_x, world_sel_y); gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin(); i != m_data->worlds.end(); i++) { e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str()); } e->setSelected(m_data->selected_world); Environment->setFocus(e); } // Delete world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, wgettext("Delete")); } // Create world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, wgettext("New")); } // Configure world button { core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2, world_sel_y+world_sel_h+0); Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON, wgettext("Configure")); } // Start game button { /*core::rect<s32> rect(0, 0, world_button_w, 30); rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3, world_sel_y+world_sel_h+0);*/ u32 bw = 160; /*core::rect<s32> rect(0, 0, bw, 30); rect += m_topleft_client + v2s32(m_size_client.X-bw-30, m_size_client.Y-30-15);*/ core::rect<s32> rect(0, 0, bw, 30); rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw, world_sel_y+world_sel_h+30+bs); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Play")); } // Options s32 option_x = 50; //s32 option_x = 50+world_sel_w+20; s32 option_y = 30; u32 option_w = 150; { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*0); Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB, wgettext("Creative Mode")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*1); Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB, wgettext("Enable Damage")); } changeCtype("C"); } else if(m_data->selected_tab == TAB_MULTIPLAYER) { changeCtype(""); // CLIENT { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 50+6); Environment->addStaticText(wgettext("Name/Password"), rect, false, true, this, -1); } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 50); gui::IGUIElement *e = Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT); if(m_data->name == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50); gui::IGUIEditBox *e = Environment->addEditBox(L"", rect, true, this, 264); e->setPasswordBox(true); if(m_data->name != L"" && m_data->address != L"") Environment->setFocus(e); } changeCtype(""); // Address + port { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 100+6); Environment->addStaticText(wgettext("Address/Port"), rect, false, true, this, -1); } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 100); gui::IGUIElement *e = Environment->addEditBox(m_data->address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(m_data->name != L"" && m_data->address == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 100); Environment->addEditBox(m_data->port.c_str(), rect, true, this, GUI_ID_PORT_INPUT); } changeCtype(""); // Start game button { core::rect<s32> rect(0, 0, 180, 30); rect += m_topleft_client + v2s32(m_size_client.X-180-30, m_size_client.Y-30-15); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Start Game / Connect")); } changeCtype("C"); } else if(m_data->selected_tab == TAB_ADVANCED) { changeCtype(""); // CLIENT { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 35+6); Environment->addStaticText(wgettext("Name/Password"), rect, false, true, this, -1); } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 35); gui::IGUIElement *e = Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT); if(m_data->name == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35); gui::IGUIEditBox *e = Environment->addEditBox(L"", rect, true, this, 264); e->setPasswordBox(true); if(m_data->name != L"" && m_data->address != L"") Environment->setFocus(e); } changeCtype(""); // Address + port { core::rect<s32> rect(0, 0, 110, 20); rect += m_topleft_client + v2s32(35+30, 75+6); Environment->addStaticText(wgettext("Address/Port"), rect, false, true, this, -1); } changeCtype("C"); { core::rect<s32> rect(0, 0, 230, 30); rect += m_topleft_client + v2s32(160+30, 75); gui::IGUIElement *e = Environment->addEditBox(m_data->address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT); if(m_data->name != L"" && m_data->address == L"") Environment->setFocus(e); } { core::rect<s32> rect(0, 0, 120, 30); rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75); Environment->addEditBox(m_data->port.c_str(), rect, true, this, GUI_ID_PORT_INPUT); } changeCtype(""); { core::rect<s32> rect(0, 0, 400, 20); rect += m_topleft_client + v2s32(160+30, 75+35); Environment->addStaticText(wgettext("Leave address blank to start a local server."), rect, false, true, this, -1); } // Start game button { core::rect<s32> rect(0, 0, 180, 30); rect += m_topleft_client + v2s32(m_size_client.X-180-30, m_size_client.Y-30-20); Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, wgettext("Start Game / Connect")); } /* Server section */ // SERVER { core::rect<s32> rect(0, 0, 10, m_size_server.Y); rect += m_topleft_server + v2s32(15, 0); const wchar_t *text = L"S\nE\nR\nV\nE\nR"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Server parameters { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 20); Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB, wgettext("Creative Mode")); } { core::rect<s32> rect(0, 0, 250, 30); rect += m_topleft_server + v2s32(30+20+250+20, 40); Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB, wgettext("Enable Damage")); } // Delete world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20, 90); Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON, wgettext("Delete world")); } // Create world button { core::rect<s32> rect(0, 0, 130, 30); rect += m_topleft_server + v2s32(30+20+250+20+140, 90); Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON, wgettext("Create world")); } // World selection listbox { core::rect<s32> rect(0, 0, 250, 120); rect += m_topleft_server + v2s32(30+20, 10); gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin(); i != m_data->worlds.end(); i++) { e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str()); } e->setSelected(m_data->selected_world); } changeCtype("C"); } else if(m_data->selected_tab == TAB_SETTINGS) { { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } s32 option_x = 70; s32 option_y = 50; u32 option_w = 150; { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y); Environment->addCheckBox(m_data->fancy_trees, rect, this, GUI_ID_FANCYTREE_CB, wgettext("Fancy trees")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20); Environment->addCheckBox(m_data->smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*2); Environment->addCheckBox(m_data->clouds_3d, rect, this, GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*3); Environment->addCheckBox(m_data->opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*4); Environment->addCheckBox(m_data->enable_sound, rect, this, GUI_ID_ENABLE_SOUND_CB, wgettext("Enable Sound")); } { core::rect<s32> rect(0, 0, option_w, 30); rect += m_topleft_client + v2s32(option_x, option_y+20*5); Environment->addCheckBox(m_data->player_3d, rect, this, GUI_ID_3D_PLAYER_CB, wgettext("3D Player")); } // Key change button { core::rect<s32> rect(0, 0, 120, 30); /*rect += m_topleft_client + v2s32(m_size_client.X-120-30, m_size_client.Y-30-20);*/ rect += m_topleft_client + v2s32(option_x, option_y+140); Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys")); } changeCtype("C"); } else if(m_data->selected_tab == TAB_CREDITS) { // CREDITS { core::rect<s32> rect(0, 0, 10, m_size_client.Y); rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS"; gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, false, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } { core::rect<s32> rect(0, 0, 620, 250); rect += m_topleft_client + v2s32(130+14, 50+35); Environment->addStaticText(narrow_to_wide( "Minetest++ " VERSION_STRING "\n" "http://minetestpp.tk/\n" "\n" "By:\n" "Perttu Ahola <*****@*****.**>\n" "Joel Leclerc (MiJyn) <*****@*****.**>\n" "Jordan Craige <*****@*****.**>\n" "sfan5 <*****@*****.**>\n" "Jeija <*****@*****.**>\n" "\n" "For a full list of contributors go here:\n" "http://www.blockpla.net/contributors/" ).c_str(), rect, false, true, this, -1); } } m_is_regenerating = false; }
bool GUIMainMenu::OnEvent(const SEvent& event) { if(event.EventType==EET_KEY_INPUT_EVENT) { if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown) { m_gamecallback->exitToOS(); quitMenu(); return true; } if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown) { acceptInput(); quitMenu(); return true; } } if(event.EventType==EET_GUI_EVENT) { if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { if(!canTakeFocus(event.GUIEvent.Element)) { dstream<<"GUIMainMenu: Not allowing focus change." <<std::endl; // Returning true disables focus change return true; } } if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED) { if(!m_is_regenerating) regenerateGui(m_screensize_old); return true; } if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_JOIN_GAME_BUTTON: { MainMenuData cur; readInput(&cur); if(cur.address == L"" && getTab() == TAB_MULTIPLAYER) { (new GUIMessageMenu(env, parent, -1, menumgr, wgettext("Address required.")) )->drop(); return true; } acceptInput(); quitMenu(); return true; } case GUI_ID_CHANGE_KEYS_BUTTON: { GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr); kmenu->drop(); return true; } case GUI_ID_DELETE_WORLD_BUTTON: { MainMenuData cur; readInput(&cur); if(cur.selected_world == -1) { (new GUIMessageMenu(env, parent, -1, menumgr, wgettext("Cannot delete world: Nothing selected")) )->drop(); } else { WorldSpec spec = m_data->worlds[cur.selected_world]; // Get files and directories involved std::vector<std::string> paths; paths.push_back(spec.path); fs::GetRecursiveSubPaths(spec.path, paths); // Launch confirmation dialog ConfirmDestDeleteWorld *dest = new ConfirmDestDeleteWorld(spec, this, paths); std::wstring text = wgettext("Delete world"); text += L" \""; text += narrow_to_wide(spec.name); text += L"\"?\n\n"; text += wgettext("Files to be deleted"); text += L":\n"; for(u32 i=0; i<paths.size(); i++) { if(i == 3) { text += L"..."; break; } text += narrow_to_wide(paths[i]) + L"\n"; } (new GUIConfirmMenu(env, parent, -1, menumgr, dest, text.c_str()))->drop(); } return true; } case GUI_ID_CREATE_WORLD_BUTTON: { std::vector<SubgameSpec> games = getAvailableGames(); if(games.size() == 0) { GUIMessageMenu *menu = new GUIMessageMenu(env, parent, -1, menumgr, wgettext("Cannot create world: No games found")); menu->drop(); } else { CreateWorldDest *dest = new CreateWorldDestMainMenu(this); GUICreateWorld *menu = new GUICreateWorld(env, parent, -1, menumgr, dest, games); menu->drop(); } return true; } case GUI_ID_CONFIGURE_WORLD_BUTTON: { GUIMessageMenu *menu = new GUIMessageMenu(env, parent, -1, menumgr, wgettext("Nothing here")); menu->drop(); return true; } } } if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264: acceptInput(); quitMenu(); return true; } } if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_WORLD_LISTBOX: acceptInput(); if(getTab() != TAB_SINGLEPLAYER) m_data->address = L""; // Force local game quitMenu(); return true; } } } return Parent ? Parent->OnEvent(event) : false; }
GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, gui::IGUIElement* parent, IMenuManager *menumgr, scene::ISceneManager* smgr, MainMenuData* data, bool& kill) : m_device(dev), m_parent(parent), m_menumanager(menumgr), m_smgr(smgr), m_data(data), m_texture_source(NULL), m_sound_manager(NULL), m_formspecgui(0), m_buttonhandler(0), m_menu(0), m_kill(kill), m_startgame(false), m_script(0), m_scriptdir(""), m_irr_toplefttext(0), m_clouds_enabled(true), m_cloud() { //initialize texture pointers for (unsigned int i = 0; i < TEX_LAYER_MAX; i++) { m_textures[i].texture = NULL; } // is deleted by guiformspec! m_buttonhandler = new TextDestGuiEngine(this); //create texture source m_texture_source = new MenuTextureSource(m_device->getVideoDriver()); //create soundmanager MenuMusicFetcher soundfetcher; #if USE_SOUND m_sound_manager = createOpenALSoundManager(&soundfetcher); #endif if(!m_sound_manager) m_sound_manager = &dummySoundManager; //create topleft header std::wstring t = narrow_to_wide(std::string("")); // = narrow_to_wide(std::string("MultiCraft ") + g_version_hash); core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(t), g_fontengine->getTextHeight()); rect += v2s32(4, 0); m_irr_toplefttext = m_device->getGUIEnvironment()->addStaticText(t.c_str(), rect,false,true,0,-1); //create formspecsource m_formspecgui = new FormspecFormSource(""); /* Create menu */ m_menu = new GUIFormSpecMenu(m_device, m_parent, -1, m_menumanager, NULL /* &client */, NULL /* gamedef */, m_texture_source, m_formspecgui, m_buttonhandler, NULL, false); m_menu->allowClose(false); m_menu->lockSize(true,v2u32(800,600)); // Initialize scripting infostream << "GUIEngine: Initializing Lua" << std::endl; m_script = new MainMenuScripting(this); try { if (m_data->errormessage != "") { m_script->setMainMenuErrorMessage(m_data->errormessage); m_data->errormessage = ""; } if (!loadMainMenuScript()) { errorstream << "No future without mainmenu" << std::endl; abort(); } run(); } catch(LuaError &e) { errorstream << "MAINMENU ERROR: " << e.what() << std::endl; m_data->errormessage = e.what(); } m_menu->quitMenu(); m_menu->drop(); m_menu = NULL; }
void GUIPauseMenu::regenerateGui(v2u32 screensize) { /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ core::rect<s32> rect( screensize.X/2 - 580/2, screensize.Y/2 - 300/2, screensize.X/2 + 580/2, screensize.Y/2 + 300/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); v2s32 size = rect.getSize(); /* Add stuff */ const s32 btn_height = 30; const s32 btn_gap = 20; const s32 btn_num = m_simple_singleplayer_mode ? 4 : 5; s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); wchar_t* text = wgettext("Continue"); Environment->addButton(rect, this, 256, text); delete[] text; } btn_y += btn_height + btn_gap; if(!m_simple_singleplayer_mode) { { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); wchar_t* text = wgettext("Change Password"); Environment->addButton(rect, this, 261, text); delete[] text; } btn_y += btn_height + btn_gap; } { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); wchar_t* text = wgettext("Sound Volume"); Environment->addButton(rect, this, 262, text); delete[] text; } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); wchar_t* text = wgettext("Exit to Menu"); Environment->addButton(rect, this, 260, text); delete[] text; } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); wchar_t* text = wgettext("Exit to OS"); Environment->addButton(rect, this, 257, text); delete[] text; } { core::rect<s32> rect(0, 0, 180, 240); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); wchar_t* text = wgettext("Default Controls:\n" "- WASD: move\n" "- Space: jump/climb\n" "- Shift: sneak/go down\n" "- Q: drop item\n" "- I: inventory\n" "- Mouse: turn/look\n" "- Mouse left: dig/punch\n" "- Mouse right: place/use\n" "- Mouse wheel: select item\n" "- T: chat\n" ); Environment->addStaticText(text, rect, false, true, this, 258); delete[] text; } { core::rect<s32> rect(0, 0, 180, 220); rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2); v2u32 max_texture_size; { video::IVideoDriver* driver = Environment->getVideoDriver(); max_texture_size = driver->getMaxTextureSize(); } std::ostringstream os; os<<"Minetest\n"; os<<minetest_build_info<<"\n"; os<<"path_user = "******"\n"; Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259); } }
void GUIPauseMenu::regenerateGui(v2u32 screensize) { /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ core::rect<s32> rect( screensize.X/2 - 580/2, screensize.Y/2 - 300/2, screensize.X/2 + 580/2, screensize.Y/2 + 300/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); v2s32 size = rect.getSize(); /* Add stuff */ const s32 btn_height = 30; const s32 btn_gap = 20; const s32 btn_num = m_simple_singleplayer_mode ? 4 : 5; s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2; changeCtype(""); { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 256, wgettext("Continue")); } btn_y += btn_height + btn_gap; if(!m_simple_singleplayer_mode) { { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 261, wgettext("Change Password")); } btn_y += btn_height + btn_gap; } { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 262, wgettext("Sound Volume")); } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 260, wgettext("Exit to Menu")); } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 257, wgettext("Exit to OS")); } { core::rect<s32> rect(0, 0, 180, 240); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); Environment->addStaticText(chartowchar_t(gettext( "Default Controls:\n" "- WASD: Walk\n" "- Mouse left: dig/hit\n" "- Mouse right: place/use\n" "- Mouse wheel: select item\n" "- 0...9: select item\n" "- Shift: sneak\n" "- R: Toggle viewing all loaded chunks\n" "- I: Inventory menu\n" "- ESC: This menu\n" "- T: Chat\n" )), rect, false, true, this, 258); } { core::rect<s32> rect(0, 0, 180, 220); rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2); v2u32 max_texture_size; { video::IVideoDriver* driver = Environment->getVideoDriver(); max_texture_size = driver->getMaxTextureSize(); } std::ostringstream os; os<<"Minetest\n"; os<<BUILD_INFO<<"\n"; os<<"path_user = "******"\n"; Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259); } changeCtype("C"); }
void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ v2s32 size(620, 430); core::rect < s32 > rect(screensize.X / 2 - size.X / 2, screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2, screensize.Y / 2 + size.Y / 2); DesiredRect = rect; recalculateAbsolutePosition(false); v2s32 topleft(0, 0); { core::rect < s32 > rect(0, 0, 125, 20); rect += topleft + v2s32(25, 3); const wchar_t *text = L"KEYBINDINGS"; //gui::IGUIStaticText *t = Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } v2s32 offset(25, 40); // buttons { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Forward"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->forward = Environment->addButton(rect, this, GUI_ID_KEY_FORWARD_BUTTON, narrow_to_wide(KeyNames[key_forward]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Backward"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->backward = Environment->addButton(rect, this, GUI_ID_KEY_BACKWARD_BUTTON, narrow_to_wide(KeyNames[key_backward]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Left"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->left = Environment->addButton(rect, this, GUI_ID_KEY_LEFT_BUTTON, narrow_to_wide(KeyNames[key_left]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Right"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->right = Environment->addButton(rect, this, GUI_ID_KEY_RIGHT_BUTTON, narrow_to_wide(KeyNames[key_right]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Use"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->use = Environment->addButton(rect, this, GUI_ID_KEY_USE_BUTTON, narrow_to_wide(KeyNames[key_use]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Sneak"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->sneak = Environment->addButton(rect, this, GUI_ID_KEY_SNEAK_BUTTON, narrow_to_wide(KeyNames[key_sneak]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Jump"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->jump = Environment->addButton(rect, this, GUI_ID_KEY_JUMP_BUTTON, narrow_to_wide(KeyNames[key_jump]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Inventory"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->inventory = Environment->addButton(rect, this, GUI_ID_KEY_INVENTORY_BUTTON, narrow_to_wide(KeyNames[key_inventory]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Chat"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->chat = Environment->addButton(rect, this, GUI_ID_KEY_CHAT_BUTTON, narrow_to_wide(KeyNames[key_chat]).c_str()); } //next col offset = v2s32(250, 40); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Toggle fly"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->fly = Environment->addButton(rect, this, GUI_ID_KEY_FLY_BUTTON, narrow_to_wide(KeyNames[key_fly]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Toggle fast"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->fast = Environment->addButton(rect, this, GUI_ID_KEY_FAST_BUTTON, narrow_to_wide(KeyNames[key_fast]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Range select"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->range = Environment->addButton(rect, this, GUI_ID_KEY_RANGE_BUTTON, narrow_to_wide(KeyNames[key_range]).c_str()); } offset += v2s32(0, 25); { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); const wchar_t *text = L"Print stacks"; Environment->addStaticText(text, rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(offset.X + 105, offset.Y - 5); this->dump = Environment->addButton(rect, this, GUI_ID_KEY_DUMP_BUTTON, narrow_to_wide(KeyNames[key_dump]).c_str()); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40); Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, L"Save"); } { core::rect < s32 > rect(0, 0, 100, 30); rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40); Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, L"Cancel"); } }
bool GUIKeyChangeMenu::OnEvent(const SEvent& event) { if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0 && event.KeyInput.PressedDown) { if (activeKey == GUI_ID_KEY_FORWARD_BUTTON) { this->forward->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_forward = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_BACKWARD_BUTTON) { this->backward->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_backward = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_LEFT_BUTTON) { this->left->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_left = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_RIGHT_BUTTON) { this->right->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_right = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_JUMP_BUTTON) { this->jump->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_jump = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_SNEAK_BUTTON) { this->sneak->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_sneak = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_INVENTORY_BUTTON) { this->inventory->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_inventory = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_CHAT_BUTTON) { this->chat->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_chat = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_RANGE_BUTTON) { this->range->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_range = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_FLY_BUTTON) { this->fly->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_fly = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_FAST_BUTTON) { this->fast->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_fast = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_USE_BUTTON) { this->use->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_use = event.KeyInput.Key; } else if (activeKey == GUI_ID_KEY_DUMP_BUTTON) { this->dump->setText( narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str()); this->key_dump = event.KeyInput.Key; } activeKey = -1; return true; } if (event.EventType == EET_GUI_EVENT) { if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { if (!canTakeFocus(event.GUIEvent.Element)) { dstream << "GUIMainMenu: Not allowing focus change." << std::endl; // Returning true disables focus change return true; } } if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) { switch (event.GUIEvent.Caller->getID()) { case GUI_ID_BACK_BUTTON: //back acceptInput(); quitMenu(); return true; case GUI_ID_ABORT_BUTTON: //abort quitMenu(); return true; case GUI_ID_KEY_FORWARD_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->forward->setText(L"press Key"); break; case GUI_ID_KEY_BACKWARD_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->backward->setText(L"press Key"); break; case GUI_ID_KEY_LEFT_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->left->setText(L"press Key"); break; case GUI_ID_KEY_RIGHT_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->right->setText(L"press Key"); break; case GUI_ID_KEY_USE_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->use->setText(L"press Key"); break; case GUI_ID_KEY_FLY_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->fly->setText(L"press Key"); break; case GUI_ID_KEY_FAST_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->fast->setText(L"press Key"); break; case GUI_ID_KEY_JUMP_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->jump->setText(L"press Key"); break; case GUI_ID_KEY_CHAT_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->chat->setText(L"press Key"); break; case GUI_ID_KEY_SNEAK_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->sneak->setText(L"press Key"); break; case GUI_ID_KEY_INVENTORY_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->inventory->setText(L"press Key"); break; case GUI_ID_KEY_DUMP_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->dump->setText(L"press Key"); break; case GUI_ID_KEY_RANGE_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); this->range->setText(L"press Key"); break; } //Buttons } } return Parent ? Parent->OnEvent(event) : false; }
int main(int argc, char *argv[]) { /* Initialization */ log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); log_register_thread("main"); // Set locale. This is for forcing '.' as the decimal point. std::locale::global(std::locale("C")); // This enables printing all characters in bitmap font setlocale(LC_CTYPE, "en_US"); /* Parse command line */ // List all allowed options core::map<std::string, ValueSpec> allowed_options; allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG, "Show allowed options")); allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, "Run server directly")); allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, "Load configuration from specified file")); allowed_options.insert("port", ValueSpec(VALUETYPE_STRING, "Set network port to connect to")); allowed_options.insert("address", ValueSpec(VALUETYPE_STRING, "Address to connect to")); allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG, "Enable random user input, for testing")); allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG, "Disable unit tests")); allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG, "Enable unit tests")); allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING, "Map directory (where everything in the world is stored)")); #ifdef _WIN32 allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG)); #endif allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG, "Run speed tests")); allowed_options.insert("info-on-stderr", ValueSpec(VALUETYPE_FLAG, "Print debug information to console")); Settings cmd_args; bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); if(ret == false || cmd_args.getFlag("help")) { dstream<<"Allowed options:"<<std::endl; for(core::map<std::string, ValueSpec>::Iterator i = allowed_options.getIterator(); i.atEnd() == false; i++) { dstream<<" --"<<i.getNode()->getKey(); if(i.getNode()->getValue().type == VALUETYPE_FLAG) { } else { dstream<<" <value>"; } dstream<<std::endl; if(i.getNode()->getValue().help != NULL) { dstream<<" "<<i.getNode()->getValue().help <<std::endl; } } return cmd_args.getFlag("help") ? 0 : 1; } /* Low-level initialization */ bool disable_stderr = false; #ifdef _WIN32 if(cmd_args.getFlag("dstream-on-stderr") == false) disable_stderr = true; #endif if(cmd_args.getFlag("info-on-stderr")) log_add_output(&main_stderr_log_out, LMT_INFO); porting::signal_handler_init(); bool &kill = *porting::signal_handler_killstatus(); // Initialize porting::path_data and porting::path_userdata porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_userdata); init_gettext((porting::path_data+DIR_DELIM+".."+DIR_DELIM+"locale").c_str()); // Initialize debug streams #ifdef RUN_IN_PLACE std::string debugfile = DEBUGFILE; #else std::string debugfile = porting::path_userdata+DIR_DELIM+DEBUGFILE; #endif debugstreams_init(disable_stderr, debugfile.c_str()); // Initialize debug stacks debug_stacks_init(); DSTACK(__FUNCTION_NAME); // Init material properties table //initializeMaterialProperties(); // Debug handler BEGIN_DEBUG_EXCEPTION_HANDLER // Print startup message actionstream<<PROJECT_NAME<< " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST <<", "<<BUILD_INFO <<std::endl; /* Basic initialization */ // Initialize default settings set_default_settings(g_settings); // Initialize sockets sockets_init(); atexit(sockets_cleanup); /* Read config file */ // Path of configuration file in use std::string configpath = ""; if(cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if(r == false) { errorstream<<"Could not read configuration from \"" <<cmd_args.get("config")<<"\""<<std::endl; return 1; } configpath = cmd_args.get("config"); } else { core::array<std::string> filenames; filenames.push_back(porting::path_userdata + DIR_DELIM + "minetest.conf"); #ifdef RUN_IN_PLACE filenames.push_back(porting::path_userdata + DIR_DELIM + ".." + DIR_DELIM + "minetest.conf"); #endif for(u32 i=0; i<filenames.size(); i++) { bool r = g_settings->readConfigFile(filenames[i].c_str()); if(r) { configpath = filenames[i]; break; } } // If no path found, use the first one (menu creates the file) if(configpath == "") configpath = filenames[0]; } // Initialize random seed srand(time(0)); mysrand(time(0)); /* Run unit tests */ if((ENABLE_TESTS && cmd_args.getFlag("disable-unittests") == false) || cmd_args.getFlag("enable-unittests") == true) { run_tests(); } /*for(s16 y=-100; y<100; y++) for(s16 x=-100; x<100; x++) { std::cout<<noise2d_gradient((double)x/10,(double)y/10, 32415)<<std::endl; } return 0;*/ /* Game parameters */ // Port u16 port = 30000; if(cmd_args.exists("port")) port = cmd_args.getU16("port"); else if(g_settings->exists("port")) port = g_settings->getU16("port"); if(port == 0) port = 30000; // Map directory std::string map_dir = porting::path_userdata+DIR_DELIM+"world"; if(cmd_args.exists("map-dir")) map_dir = cmd_args.get("map-dir"); else if(g_settings->exists("map-dir")) map_dir = g_settings->get("map-dir"); // Run dedicated server if asked to if(cmd_args.getFlag("server")) { DSTACK("Dedicated server branch"); // Create time getter g_timegetter = new SimpleTimeGetter(); // Create server Server server(map_dir.c_str(), configpath); server.start(port); // Run server dedicated_server_loop(server, kill); return 0; } /* More parameters */ // Address to connect to std::string address = ""; if(cmd_args.exists("address")) { address = cmd_args.get("address"); } else { address = g_settings->get("address"); } std::string playername = g_settings->get("name"); /* Device initialization */ // Resolution selection bool fullscreen = false; u16 screenW = g_settings->getU16("screenW"); u16 screenH = g_settings->getU16("screenH"); // Determine driver video::E_DRIVER_TYPE driverType; std::string driverstring = g_settings->get("video_driver"); if(driverstring == "null") driverType = video::EDT_NULL; else if(driverstring == "software") driverType = video::EDT_SOFTWARE; else if(driverstring == "burningsvideo") driverType = video::EDT_BURNINGSVIDEO; else if(driverstring == "direct3d8") driverType = video::EDT_DIRECT3D8; else if(driverstring == "direct3d9") driverType = video::EDT_DIRECT3D9; else if(driverstring == "opengl") driverType = video::EDT_OPENGL; else { errorstream<<"WARNING: Invalid video_driver specified; defaulting " "to opengl"<<std::endl; driverType = video::EDT_OPENGL; } /* Create device and exit if creation failed */ MyEventReceiver receiver; IrrlichtDevice *device; device = createDevice(driverType, core::dimension2d<u32>(screenW, screenH), 16, fullscreen, false, false, &receiver); if (device == 0) return 1; // could not create selected driver. /* Continue initialization */ video::IVideoDriver* driver = device->getVideoDriver(); // Disable mipmaps (because some of them look ugly) driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); /* This changes the minimum allowed number of vertices in a VBO. Default is 500. */ //driver->setMinHardwareBufferVertexCount(50); // Set the window caption device->setWindowCaption(L"Minetest [Main Menu]"); // Create time getter g_timegetter = new IrrlichtTimeGetter(device); // Create game callback for menus g_gamecallback = new MainGameCallback(device); /* Speed tests (done after irrlicht is loaded to get timer) */ if(cmd_args.getFlag("speedtests")) { dstream<<"Running speed tests"<<std::endl; SpeedTests(); return 0; } device->setResizable(true); bool random_input = g_settings->getBool("random_input") || cmd_args.getFlag("random-input"); InputHandler *input = NULL; if(random_input) input = new RandomInputHandler(); else input = new RealInputHandler(device, &receiver); scene::ISceneManager* smgr = device->getSceneManager(); guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); if(font) skin->setFont(font); else errorstream<<"WARNING: Font file was not found." " Using default font."<<std::endl; // If font was not found, this will get us one font = skin->getFont(); assert(font); u32 text_height = font->getDimension(L"Hello, world!").Height; infostream<<"text_height="<<text_height<<std::endl; //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); /* GUI stuff */ /* 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""; // The password entered during the menu screen, std::string password; /* Menu-game loop */ while(device->run() && kill == false) { // This is used for catching disconnects try { /* Clear everything from the GUIEnvironment */ guienv->clear(); /* 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<s32>(0, 0, 10000, 10000)); /* Out-of-game menu loop. Loop quits when menu returns proper parameters. */ while(kill == false) { // 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.fancy_trees = g_settings->getBool("new_style_leaves"); menudata.smooth_lighting = g_settings->getBool("smooth_lighting"); menudata.clouds_3d = g_settings->getBool("enable_3d_clouds"); menudata.opaque_water = g_settings->getBool("opaque_water"); menudata.creative_mode = g_settings->getBool("creative_mode"); menudata.enable_damage = g_settings->getBool("enable_damage"); GUIMainMenu *menu = new GUIMainMenu(guienv, guiroot, -1, &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); if(error_message != L"") { errorstream<<"error_message = " <<wide_to_narrow(error_message)<<std::endl; GUIMessageMenu *menu2 = new GUIMessageMenu(guienv, guiroot, -1, &g_menumgr, error_message.c_str()); menu2->drop(); error_message = L""; } video::IVideoDriver* driver = device->getVideoDriver(); infostream<<"Created main menu"<<std::endl; while(device->run() && kill == false) { 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)); drawMenuBackground(driver); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be // automatically limited sleep_ms(25); } // Break out of menu-game loop to shut down cleanly if(device->run() == false || kill == true) break; infostream<<"Dropping main menu"<<std::endl; menu->drop(); // Delete map if requested if(menudata.delete_map) { bool r = fs::RecursiveDeleteContent(map_dir); if(r == false) error_message = L"Delete failed"; continue; } playername = wide_to_narrow(menudata.name); password = translatePassword(playername, menudata.password); //infostream<<"Main: password hash: '"<<password<<"'"<<std::endl; address = wide_to_narrow(menudata.address); int newport = stoi(wide_to_narrow(menudata.port)); if(newport != 0) port = newport; 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)); g_settings->set("opaque_water", itos(menudata.opaque_water)); g_settings->set("creative_mode", itos(menudata.creative_mode)); g_settings->set("enable_damage", itos(menudata.enable_damage)); // NOTE: These are now checked server side; no need to do it // here, so let's not do it here. /*// Check for valid parameters, restart menu if invalid. if(playername == "") { error_message = L"Name required."; continue; } // Check that name has only valid chars if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false) { error_message = L"Characters allowed: " +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS); 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(device->run() == false || kill == true) break; /* Run game */ the_game( kill, random_input, input, device, font, map_dir, playername, password, address, port, error_message, configpath ); } //try catch(con::PeerNotFoundException &e) { errorstream<<"Connection error (timed out?)"<<std::endl; error_message = L"Connection error (timed out?)"; } catch(SocketException &e) { errorstream<<"Socket error (port already in use?)"<<std::endl; error_message = L"Socket error (port already in use?)"; } catch(ModError &e) { errorstream<<e.what()<<std::endl; error_message = narrow_to_wide(e.what()) + L"\nCheck debug.txt for details."; } #ifdef NDEBUG catch(std::exception &e) { std::string narrow_message = "Some exception, what()=\""; narrow_message += e.what(); narrow_message += "\""; errorstream<<narrow_message<<std::endl; error_message = narrow_to_wide(narrow_message); } #endif } // Menu-game loop delete input; /* In the end, delete the Irrlicht device. */ device->drop(); END_DEBUG_EXCEPTION_HANDLER(errorstream) debugstreams_deinit(); return 0; }
bool GUIMainMenu::OnEvent(const SEvent& event) { if(event.EventType==EET_KEY_INPUT_EVENT) { if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown) { m_gamecallback->exitToOS(); quitMenu(); return true; } if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown) { acceptInput(); quitMenu(); return true; } } if(event.EventType==EET_GUI_EVENT) { if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { if(!canTakeFocus(event.GUIEvent.Element)) { dstream<<"GUIMainMenu: Not allowing focus change." <<std::endl; // Returning true disables focus change return true; } } if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED) { if(!m_is_regenerating) regenerateGui(m_screensize_old); return true; } if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST) { serverListOnSelected(); return true; } if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_JOIN_GAME_BUTTON: { MainMenuData cur; readInput(&cur); if (getTab() == TAB_MULTIPLAYER && cur.address == L"") { wchar_t* text = wgettext("Address required."); (new GUIMessageMenu(env, parent, -1, menumgr, text) )->drop(); delete[] text; return true; } acceptInput(); quitMenu(); return true; } case GUI_ID_CHANGE_KEYS_BUTTON: { GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr); kmenu->drop(); return true; } case GUI_ID_DELETE_WORLD_BUTTON: { MainMenuData cur; readInput(&cur); if(cur.selected_world == -1){ wchar_t* text = wgettext("Cannot delete world: Nothing selected"); (new GUIMessageMenu(env, parent, -1, menumgr, text) )->drop(); delete[] text; } else { WorldSpec spec = m_data->worlds[cur.selected_world]; // Get files and directories involved std::vector<std::string> paths; paths.push_back(spec.path); fs::GetRecursiveSubPaths(spec.path, paths); // Launch confirmation dialog ConfirmDestDeleteWorld *dest = new ConfirmDestDeleteWorld(spec, this, paths); wchar_t* text1 = wgettext("Delete world"); wchar_t* text2 = wgettext("Files to be deleted"); std::wstring text = text1; text += L" \""; text += narrow_to_wide(spec.name); text += L"\"?\n\n"; text += text2; text += L":\n"; delete[] text1; delete[] text2; for(u32 i=0; i<paths.size(); i++){ if(i == 3){ text += L"..."; break; } text += narrow_to_wide(paths[i]) + L"\n"; } (new GUIConfirmMenu(env, parent, -1, menumgr, dest, text.c_str()))->drop(); } return true; } case GUI_ID_CREATE_WORLD_BUTTON: { 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, -1, menumgr, text); menu->drop(); delete[] text; } else { CreateWorldDest *dest = new CreateWorldDestMainMenu(this); GUICreateWorld *menu = new GUICreateWorld(env, parent, -1, menumgr, dest, games, m_data->selected_game); menu->drop(); } return true; } case GUI_ID_CONFIGURE_WORLD_BUTTON: { MainMenuData cur; readInput(&cur); if(cur.selected_world == -1) { wchar_t* text = wgettext("Cannot configure world: Nothing selected"); (new GUIMessageMenu(env, parent, -1, menumgr, text) )->drop(); delete[] text; } else { WorldSpec wspec = m_data->worlds[cur.selected_world]; GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent, -1, menumgr, wspec); menu->drop(); } return true; } case GUI_ID_SERVERLIST_DELETE: { gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST); s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected(); if (selected == -1) return true; ServerList::deleteEntry(m_data->servers[selected]); m_data->servers = ServerList::getLocal(); updateGuiServerList(); if (selected > 0) selected -= 1; serverlist->setSelected(selected); serverListOnSelected(); return true; } #if USE_CURL case GUI_ID_SERVERLIST_TOGGLE: { gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE); gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE); gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST); gui::IGUIElement *title = getElementFromId(GUI_ID_SERVERLIST_TITLE); if (m_data->selected_serverlist == SERVERLIST_PUBLIC) // switch to favorite list { m_data->servers = ServerList::getLocal(); wchar_t* text1 = wgettext("Show Public"); wchar_t* text2 = wgettext("Favorites:"); togglebutton->setText(text1); title->setText(text2); delete[] text1; delete[] text2; deletebutton->setVisible(true); updateGuiServerList(); serverlist->setSelected(0); m_data->selected_serverlist = SERVERLIST_FAVORITES; } else // switch to online list { m_data->servers = ServerList::getOnline(); wchar_t* text1 = wgettext("Show Favorites"); wchar_t* text2 = wgettext("Public Server List:"); togglebutton->setText(text1); title->setText(text2); delete[] text1; delete[] text2; deletebutton->setVisible(false); updateGuiServerList(); serverlist->setSelected(0); m_data->selected_serverlist = SERVERLIST_PUBLIC; } serverListOnSelected(); } #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; m_data->selected_game_name = m_data->games[eid - GUI_ID_GAME_BUTTON_FIRST].name; regenerateGui(m_screensize_old); } } if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264: MainMenuData cur; readInput(&cur); if (getTab() == TAB_MULTIPLAYER && cur.address == L"") { wchar_t* text = wgettext("Address required."); (new GUIMessageMenu(env, parent, -1, menumgr, text) )->drop(); delete[] text; return true; } acceptInput(); quitMenu(); return true; } } if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED) { readInput(m_data); } if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN) { switch(event.GUIEvent.Caller->getID()) { case GUI_ID_WORLD_LISTBOX: acceptInput(); if(getTab() != TAB_SINGLEPLAYER) m_data->address = L""; // Force local game quitMenu(); return true; case GUI_ID_SERVERLIST: gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST); if (serverlist->getSelected() > -1) { acceptInput(); quitMenu(); return true; } } } } return Parent ? Parent->OnEvent(event) : false; }
void GUIPauseMenu::regenerateGui(v2u32 screensize) { /* Remove stuff */ removeChildren(); /* Calculate new sizes and positions */ core::rect<s32> rect( screensize.X/2 - 580/2, screensize.Y/2 - 300/2, screensize.X/2 + 580/2, screensize.Y/2 + 300/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); v2s32 size = rect.getSize(); /* Add stuff */ const s32 btn_height = 30; const s32 btn_gap = 20; const s32 btn_num = 4; s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2; changeCtype(""); { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 256, wgettext("Continue")); } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 261, wgettext("Change Password")); } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 260, wgettext("Disconnect")); } btn_y += btn_height + btn_gap; { core::rect<s32> rect(0, 0, 140, btn_height); rect = rect + v2s32(size.X/2-140/2, btn_y); Environment->addButton(rect, this, 257, wgettext("Exit to OS")); } { core::rect<s32> rect(0, 0, 180, 240); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); Environment->addStaticText(chartowchar_t(gettext( "Default Controls:\n" "- WASD: Walk\n" "- Mouse left: dig/hit\n" "- Mouse right: place/use\n" "- Mouse wheel: select item\n" "- 0...9: select item\n" "- Shift: sneak\n" "- R: Toggle viewing all loaded chunks\n" "- I: Inventory menu\n" "- ESC: This menu\n" "- T: Chat\n" )), rect, false, true, this, 258); } { core::rect<s32> rect(0, 0, 180, 220); rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2); v2u32 max_texture_size; { video::IVideoDriver* driver = Environment->getVideoDriver(); max_texture_size = driver->getMaxTextureSize(); } /*wchar_t text[200]; swprintf(text, 200, L"Minetest-c55\n" L"by Perttu Ahola\n" L"[email protected]\n\n" SWPRINTF_CHARSTRING L"\n" L"userdata path = " SWPRINTF_CHARSTRING , BUILD_INFO, porting::path_userdata.c_str() );*/ std::ostringstream os; os<<"Minetest\n"; os<<"by Perttu Ahola and contributors\n"; os<<"[email protected]\n"; os<<BUILD_INFO<<"\n"; os<<"ud_path = "<<wrap_rows(porting::path_userdata, 20)<<"\n"; Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259); } changeCtype("C"); }
void Hud::drawLuaElements() { for (size_t i = 0; i != player->hud.size(); i++) { HudElement *e = player->hud[i]; if (!e) continue; v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y); switch (e->type) { case HUD_ELEM_IMAGE: { video::ITexture *texture = tsrc->getTexture(e->text); if (!texture) continue; const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; core::dimension2di imgsize(texture->getOriginalSize()); v2s32 dstsize(imgsize.Width * e->scale.X, imgsize.Height * e->scale.Y); if (e->scale.X < 0) dstsize.X = screensize.X * (e->scale.X * -0.01); if (e->scale.Y < 0) dstsize.Y = screensize.Y * (e->scale.Y * -0.01); v2s32 offset((e->align.X - 1.0) * dstsize.X / 2, (e->align.Y - 1.0) * dstsize.Y / 2); core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y); rect += pos + offset + v2s32(e->offset.X, e->offset.Y); driver->draw2DImage(texture, rect, core::rect<s32>(core::position2d<s32>(0,0), imgsize), NULL, colors, true); break; } case HUD_ELEM_TEXT: { video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y); std::wstring text = narrow_to_wide(e->text); core::dimension2d<u32> textsize = font->getDimension(text.c_str()); v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), (e->align.Y - 1.0) * (textsize.Height / 2)); v2s32 offs(e->offset.X, e->offset.Y); font->draw(text.c_str(), size + pos + offset + offs, color); break; } case HUD_ELEM_STATBAR: { v2s32 offs(e->offset.X, e->offset.Y); drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs); break; } case HUD_ELEM_INVENTORY: { InventoryList *inv = inventory->getList(e->text); drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir); break; } case HUD_ELEM_WAYPOINT: { v3f p_pos = player->getPosition() / BS; v3f w_pos = e->world_pos * BS; float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10; scene::ICameraSceneNode* camera = smgr->getActiveCamera(); core::matrix4 trans = camera->getProjectionMatrix(); trans *= camera->getViewMatrix(); f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f }; trans.multiplyWith1x4Matrix(transformed_pos); if (transformed_pos[3] < 0) break; f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : core::reciprocal(transformed_pos[3]); pos.X = screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5); pos.Y = screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5); video::SColor color(255, (e->number >> 16) & 0xFF, (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect<s32> size(0, 0, 200, 2 * text_height); std::wstring text = narrow_to_wide(e->name); font->draw(text.c_str(), size + pos, color); std::ostringstream os; os<<distance<<e->text; text = narrow_to_wide(os.str()); pos.Y += text_height; font->draw(text.c_str(), size + pos, color); break; } default: infostream << "Hud::drawLuaElements: ignoring drawform " << e->type << " of hud element ID " << i << " due to unrecognized type" << std::endl; } } }