string MenuStateAbout::loadAdditionalCredits(){
	string data_path= getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
	if(data_path != ""){
		endPathWithSlash(data_path);
	}
	string result= "";
	const string dir= getGameCustomCoreDataPath(data_path,"data/core/menu/credits.txt");
	//printf("dir [%s]\n",dir.c_str());

	if(fileExists(dir) == true) {
#if defined(WIN32) && !defined(__MINGW32__)
		FILE *fp = _wfopen(utf8_decode(dir).c_str(), L"r");
		ifstream file(fp);
#else
		ifstream file(dir.c_str());
#endif
		std::string buffer;
		while(!file.eof()){
			getline(file, buffer);
			result+= buffer + "\n";
		}
		std::cout << buffer << std::endl;
		file.close();
#if defined(WIN32) && !defined(__MINGW32__)
		if(fp) fclose(fp);
#endif
	}
	return result;
}
MenuBackground::MenuBackground() : rps(NULL) {
	Renderer &renderer= Renderer::getInstance();

	//load data
	string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);

	XmlTree xmlTree;
	xmlTree.load(getGameCustomCoreDataPath(data_path, "data/core/menu/menu.xml"),Properties::getTagReplacementValues());
	const XmlNode *menuNode= xmlTree.getRootNode();

	//water
	const XmlNode *waterNode= menuNode->getChild("water");
	water= waterNode->getAttribute("value")->getBoolValue();
	if(water){
		waterHeight= waterNode->getAttribute("height")->getFloatValue();

		//water texture
		waterTexture= renderer.newTexture2D(rsMenu);
		if(waterTexture) {
			waterTexture->getPixmap()->init(4);
			waterTexture->getPixmap()->load(getGameCustomCoreDataPath(data_path, "data/core/menu/textures/water.tga"));
		}
	}

	//fog
	const XmlNode *fogNode= menuNode->getChild("fog");
	fog= fogNode->getAttribute("value")->getBoolValue();
	if(fog){
		fogDensity= fogNode->getAttribute("density")->getFloatValue();
	}

	//rain
	bool withRainEffect = Config::getInstance().getBool("RainEffectMenu","true");
	if(withRainEffect == true) {
		rain= menuNode->getChild("rain")->getAttribute("value")->getBoolValue();
		if(rain) {
			createRainParticleSystem();
		}
	}
	else {
		rain = false;
	}

	//camera
	const XmlNode *cameraNode= menuNode->getChild("camera");

	//position
	const XmlNode *positionNode= cameraNode->getChild("start-position");
	Vec3f startPosition;
    startPosition.x= positionNode->getAttribute("x")->getFloatValue();
	startPosition.y= positionNode->getAttribute("y")->getFloatValue();
	startPosition.z= positionNode->getAttribute("z")->getFloatValue();
	camera.setPosition(startPosition);

	//rotation
	const XmlNode *rotationNode= cameraNode->getChild("start-rotation");
	Vec3f startRotation;
    startRotation.x= rotationNode->getAttribute("x")->getFloatValue();
	startRotation.y= rotationNode->getAttribute("y")->getFloatValue();
	startRotation.z= rotationNode->getAttribute("z")->getFloatValue();
	camera.setOrientation(Quaternion(EulerAngles(
		degToRad(startRotation.x),
		degToRad(startRotation.y),
		degToRad(startRotation.z))));

	//load main model
	mainModel= renderer.newModel(rsMenu);
	if(mainModel) {
		string mainModelFile = "data/core/menu/main_model/menu_main.g3d";
		if(menuNode->hasChild("menu-background-model") == true) {
			//mainModel->load(data_path + "data/core/menu/main_model/menu_main.g3d");
			const XmlNode *mainMenuModelNode= menuNode->getChild("menu-background-model");
			mainModelFile = mainMenuModelNode->getAttribute("value")->getRestrictedValue();
		}
		mainModel->load(getGameCustomCoreDataPath(data_path, mainModelFile));
	}

	//models
	for(int i=0; i<5; ++i){
		characterModels[i]= renderer.newModel(rsMenu);
		if(characterModels[i]) {
			characterModels[i]->load(getGameCustomCoreDataPath(data_path, "data/core/menu/about_models/character"+intToStr(i)+".g3d"));
		}
	}

	//about position
	positionNode= cameraNode->getChild("about-position");
	aboutPosition.x= positionNode->getAttribute("x")->getFloatValue();
	aboutPosition.y= positionNode->getAttribute("y")->getFloatValue();
	aboutPosition.z= positionNode->getAttribute("z")->getFloatValue();
	rotationNode= cameraNode->getChild("about-rotation");

	targetCamera= NULL;
	t= 0.f;
	fade= 0.f;
	anim= 0.f;
}