Esempio n. 1
0
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)));
			}
		}
	}
}
Esempio n. 4
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
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_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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
	}
}
Esempio n. 12
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
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;
}
Esempio n. 17
0
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");
}
Esempio n. 18
0
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;
		}
	}
}