// ==============================================================
//	This file is part of Glest (www.glest.org)
//
//	Copyright (C) 2001-2008 Martiño Figueroa
//
//	You can redistribute this code and/or modify it under
//	the terms of the GNU General Public License as published
//	by the Free Software Foundation; either version 2 of the
//	License, or (at your option) any later version
// ==============================================================

#include "tileset.h"

#include <cassert>
#include <ctime>

#include "logger.h"
#include "util.h"
#include "renderer.h"
#include "game_util.h"
#include "leak_dumper.h"
#include "properties.h"
#include "lang.h"
#include "platform_util.h"

using namespace Shared::Util;
using namespace Shared::Xml;
using namespace Shared::Graphics;

namespace Glest{ namespace Game{

const float Tileset::standardAirHeight= 5.0f;
const float Tileset::standardShadowIntensity= 0.2f;
// =====================================================
// 	class AmbientSounds
// =====================================================

void AmbientSounds::load(const string &dir, const XmlNode *xmlNode,
		std::map<string,vector<pair<string, string> > > &loadedFileList, string parentLoader) {
	string path="";

	//day
	const XmlNode *dayNode= xmlNode->getChild("day-sound");
	enabledDay= dayNode->getAttribute("enabled")->getBoolValue();
	if(enabledDay) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= dayNode->getAttribute("path")->getRestrictedValue(currentPath);
		day.open(path);
		loadedFileList[path].push_back(make_pair(parentLoader,dayNode->getAttribute("path")->getRestrictedValue()));

		alwaysPlayDay= dayNode->getAttribute("play-always")->getBoolValue();
	}

	//night
	const XmlNode *nightNode= xmlNode->getChild("night-sound");
	enabledNight= nightNode->getAttribute("enabled")->getBoolValue();
	if(enabledNight) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= nightNode->getAttribute("path")->getRestrictedValue(currentPath);
		night.open(path);
		loadedFileList[path].push_back(make_pair(parentLoader,nightNode->getAttribute("path")->getRestrictedValue()));

		alwaysPlayNight= nightNode->getAttribute("play-always")->getBoolValue();
	}

	//rain
	const XmlNode *rainNode= xmlNode->getChild("rain-sound");
	enabledRain= rainNode->getAttribute("enabled")->getBoolValue();
	if(enabledRain) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= rainNode->getAttribute("path")->getRestrictedValue(currentPath);
		rain.open(path);
		loadedFileList[path].push_back(make_pair(parentLoader,rainNode->getAttribute("path")->getRestrictedValue()));
	}

	//snow
	const XmlNode *snowNode= xmlNode->getChild("snow-sound");
	enabledSnow= snowNode->getAttribute("enabled")->getBoolValue();
	if(enabledSnow) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= snowNode->getAttribute("path")->getRestrictedValue(currentPath);
		snow.open(path);
		loadedFileList[path].push_back(make_pair(parentLoader,snowNode->getAttribute("path")->getRestrictedValue()));
	}

	//dayStart
	const XmlNode *dayStartNode= xmlNode->getChild("day-start-sound");
	enabledDayStart= dayStartNode->getAttribute("enabled")->getBoolValue();
	if(enabledDayStart) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= dayStartNode->getAttribute("path")->getRestrictedValue(currentPath);
		dayStart.load(path);
		loadedFileList[path].push_back(make_pair(parentLoader,dayStartNode->getAttribute("path")->getRestrictedValue()));
	}

	//nightStart
	const XmlNode *nightStartNode= xmlNode->getChild("night-start-sound");
	enabledNightStart= nightStartNode->getAttribute("enabled")->getBoolValue();
	if(enabledNightStart) {
		string currentPath = dir;
		endPathWithSlash(currentPath);

		path= nightStartNode->getAttribute("path")->getRestrictedValue(currentPath);
		nightStart.load(path);
		loadedFileList[path].push_back(make_pair(parentLoader,nightStartNode->getAttribute("path")->getRestrictedValue()));
	}
}

// =====================================================
// 	class Tileset
// =====================================================

Checksum Tileset::loadTileset(const vector<string> pathList, const string &tilesetName,
		Checksum* checksum, std::map<string,vector<pair<string, string> > > &loadedFileList) {
    Checksum tilesetChecksum;

    bool found = false;
    for(int idx = 0; idx < (int)pathList.size(); idx++) {
		string currentPath = pathList[idx];
		endPathWithSlash(currentPath);
        string path = currentPath + tilesetName;
        if(isdir(path.c_str()) == true) {
            load(path, checksum, &tilesetChecksum, loadedFileList);
            found = true;
            break;
        }
    }
    if(found == false) {
		throw megaglest_runtime_error("Error could not find tileset [" + tilesetName + "]\n",true);

    }
    return tilesetChecksum;
}


void Tileset::load(const string &dir, Checksum *checksum, Checksum *tilesetChecksum,
		std::map<string,vector<pair<string, string> > > &loadedFileList) {
	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

	random.init(time(NULL));

	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

	string name= lastDir(dir);
	tileset_name = name;
	string currentPath = dir;
	endPathWithSlash(currentPath);
	string path= currentPath + name + ".xml";
	string sourceXMLFile = path;

	checksum->addFile(path);
	tilesetChecksum->addFile(path);
	checksumValue.addFile(path);

	try {
		char szBuf[8096]="";
		snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingTileset","",true).c_str(),formatString(name).c_str());
		Logger::getInstance().add(szBuf, true);

		Renderer &renderer= Renderer::getInstance();

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//printf("About to load tileset [%s]\n",path.c_str());
		//parse xml
		XmlTree xmlTree;
		xmlTree.load(path,Properties::getTagReplacementValues());
		loadedFileList[path].push_back(make_pair(currentPath,currentPath));

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		const XmlNode *tilesetNode= xmlTree.getRootNode();

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//surfaces
		const XmlNode *surfacesNode= tilesetNode->getChild("surfaces");
		int partsize= 0;
		for(int i=0; i < surfCount; ++i) {

			const XmlNode *surfaceNode;
			if(surfacesNode->hasChildAtIndex("surface",i)){
				surfaceNode= surfacesNode->getChild("surface", i);
			}
			else {
				// cliff texture does not exist, use texture 2 instead
				surfaceNode= surfacesNode->getChild("surface", 2);
			}

			if(surfaceNode->hasAttribute("partsize")){
				partsize=surfaceNode->getAttribute("partsize",true)->getIntValue();
			}
			else{
				partsize=0;
			}

			if(partsize==0){
				int childCount= (int)surfaceNode->getChildCount();
				surfPixmaps[i].resize(childCount);
				surfProbs[i].resize(childCount);

				for(int j = 0; j < childCount; ++j) {
					surfPixmaps[i][j] = NULL;
				}

				for(int j = 0; j < childCount; ++j) {
					const XmlNode *textureNode= surfaceNode->getChild("texture", j);
					if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
						surfPixmaps[i][j] = new Pixmap2D();
						surfPixmaps[i][j]->init(3);
						surfPixmaps[i][j]->load(textureNode->getAttribute("path")->getRestrictedValue(currentPath));
					}
					loadedFileList[textureNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,textureNode->getAttribute("path")->getRestrictedValue()));

					surfProbs[i][j]= textureNode->getAttribute("prob")->getFloatValue();
				}
			}
			else {
				// read single big texture and cut it into pieces
				const XmlNode *textureNode= surfaceNode->getChild("texture", 0);

				// There is no way to figure out parts without loading the texture
				// unfortunately we must load it even for headless server
				// to get width and height
				bool switchOffNonGraphicalModeEnabled = GlobalStaticFlags::getIsNonGraphicalModeEnabled();
				if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
					GlobalStaticFlags::setIsNonGraphicalModeEnabled(false);
				}

				string exceptionError = "";
				Pixmap2D *pixmap 	= NULL;
				int width 			= 0;
				int height 			= 0;

				try {
					pixmap=new Pixmap2D();
					pixmap->init(3);
					pixmap->load(textureNode->getAttribute("path")->getRestrictedValue(currentPath));
					loadedFileList[textureNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,textureNode->getAttribute("path")->getRestrictedValue()));

					width  = pixmap->getW();
					height = pixmap->getW();
				}
			    catch(megaglest_runtime_error& ex) {
					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
					throw megaglest_runtime_error("Error loading tileset: "+ path + "\nMessage: " + ex.what(),!ex.wantStackTrace() );
			    }
				catch(const exception &ex) {
					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());

					exceptionError = "Error: " + path + "\n" + ex.what();
				}

				if(switchOffNonGraphicalModeEnabled == true) {
					GlobalStaticFlags::setIsNonGraphicalModeEnabled(true);

					delete pixmap;
					pixmap = NULL;
				}

				if(exceptionError != "") {
					throw megaglest_runtime_error(exceptionError.c_str());
				}

				if(width != height) {
					throw megaglest_runtime_error("width != height");
				}
				if(width % 64 != 0) {
					throw megaglest_runtime_error("width % 64 != 0");
				}
				if(width % partsize != 0) {
					throw megaglest_runtime_error("width % partsize != 0");
				}

				int parts=width/partsize;
				int numberOfPieces=parts*parts;
				partsArray[i]=parts;
				surfPixmaps[i].resize(numberOfPieces);
				surfProbs[i].resize(numberOfPieces);
				int j=0;
				for(int x = 0; x < parts; ++x) {
					for(int y = 0; y < parts; ++y) {
						if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
							surfPixmaps[i][j] = new Pixmap2D();
							surfPixmaps[i][j]->init(partsize,partsize,3);
							surfPixmaps[i][j]->copyImagePart(x*partsize,y*partsize,pixmap);
						}
						surfProbs[i][j]=-1;
						j++;
					}
				}
			}
		}

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//object models
		const XmlNode *objectsNode= tilesetNode->getChild("objects");
		for(int i=0; i<objCount; ++i){
			const XmlNode *objectNode= objectsNode->getChild("object", i);
			int childCount= (int)objectNode->getChildCount();

			int objectHeight = 0;
			bool walkable = objectNode->getAttribute("walkable")->getBoolValue();
			if(walkable == false) {
				const XmlAttribute *heightAttribute = objectNode->getAttribute("height",false);
				if(heightAttribute != NULL) {
					objectHeight = heightAttribute->getIntValue();
				}
			}

			objectTypes[i].init(childCount, i, walkable,objectHeight);
			for(int j=0; j<childCount; ++j) {
				const XmlNode *modelNode= objectNode->getChild("model", j);
				const XmlAttribute *pathAttribute= modelNode->getAttribute("path");
				TilesetModelType* tmt=objectTypes[i].loadModel(pathAttribute->getRestrictedValue(currentPath),&loadedFileList, sourceXMLFile);
				loadedFileList[pathAttribute->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,pathAttribute->getRestrictedValue()));

				if(modelNode->hasAttribute("anim-speed") == true) {
					int animSpeed= modelNode->getAttribute("anim-speed")->getIntValue();
					tmt->setAnimSpeed(animSpeed);
				}

				if(modelNode->hasChild("particles")){
					const XmlNode *particleNode= modelNode->getChild("particles");
					bool particleEnabled= particleNode->getAttribute("value")->getBoolValue();
					if(particleEnabled){
						for(int k=0; k < (int)particleNode->getChildCount(); ++k){
							const XmlNode *particleFileNode= particleNode->getChild("particle-file", k);
							string path= particleFileNode->getAttribute("path")->getRestrictedValue();
							ObjectParticleSystemType *objectParticleSystemType= new ObjectParticleSystemType();
							objectParticleSystemType->load(particleFileNode, dir, currentPath + path,
									&Renderer::getInstance(), loadedFileList, sourceXMLFile,"");
							loadedFileList[currentPath + path].push_back(make_pair(sourceXMLFile,particleFileNode->getAttribute("path")->getRestrictedValue()));

							tmt->addParticleSystem(objectParticleSystemType);
						}
					}
				}

				//rotationAllowed
				if(modelNode->hasAttribute("rotationAllowed") == true) {
					tmt->setRotationAllowed(modelNode->getAttribute("rotationAllowed")->getBoolValue());
				}
				else if(modelNode->hasChild("rotationAllowed")){
					const XmlNode *rotationAllowedNode= modelNode->getChild("rotationAllowed");
					tmt->setRotationAllowed(rotationAllowedNode->getAttribute("value")->getBoolValue());
				}
				else{
					tmt->setRotationAllowed(true);
				}
				//randomPositionEnabled
				if(modelNode->hasAttribute("randomPositionEnabled") == true) {
					tmt->setRandomPositionEnabled(modelNode->getAttribute("randomPositionEnabled")->getBoolValue());
				}
				else{
					tmt->setRandomPositionEnabled(true);
				}

				//smoothTwoFrameAnim
				if(modelNode->hasAttribute("smoothTwoFrameAnim") == true) {
					tmt->setSmoothTwoFrameAnim(modelNode->getAttribute("smoothTwoFrameAnim")->getBoolValue());
				}
				else{
					tmt->setSmoothTwoFrameAnim(false);
				}
			}
		}

		// Now free up the pixmap memory
		for(int i=0; i<objCount; ++i){
			objectTypes[i].deletePixels();
		}

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//ambient sounds
		ambientSounds.load(dir, tilesetNode->getChild("ambient-sounds"), loadedFileList, sourceXMLFile);

		//parameters
		const XmlNode *parametersNode= tilesetNode->getChild("parameters");

		//water
		const XmlNode *waterNode= parametersNode->getChild("water");
		waterTex= renderer.newTexture3D(rsGame);
		if(waterTex) {
			waterTex->setMipmap(false);
			waterTex->setWrapMode(Texture::wmRepeat);
		}
		waterEffects= waterNode->getAttribute("effects")->getBoolValue();

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		int waterFrameCount= (int)waterNode->getChildCount();
		if(waterTex) {
			waterTex->getPixmap()->init(waterFrameCount, 4);
		}
		for(int i=0; i<waterFrameCount; ++i){
			const XmlNode *waterFrameNode= waterNode->getChild("texture", i);
			if(waterTex) {
				waterTex->getPixmap()->loadSlice(waterFrameNode->getAttribute("path")->getRestrictedValue(currentPath), i);
			}
			loadedFileList[waterFrameNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,waterFrameNode->getAttribute("path")->getRestrictedValue()));
		}

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//fog
		const XmlNode *fogNode= parametersNode->getChild("fog");
		fog= fogNode->getAttribute("enabled")->getBoolValue();
		if(fog){
			fogMode= fogNode->getAttribute("mode")->getIntValue(1, 2);
			fogDensity= fogNode->getAttribute("density")->getFloatValue();
			fogColor.x= fogNode->getAttribute("color-red")->getFloatValue(0.f, 1.f);
			fogColor.y= fogNode->getAttribute("color-green")->getFloatValue(0.f, 1.f);
			fogColor.z= fogNode->getAttribute("color-blue")->getFloatValue(0.f, 1.f);
		}

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//sun and moon light colors
		const XmlNode *sunLightColorNode= parametersNode->getChild("sun-light");
		sunLightColor.x= sunLightColorNode->getAttribute("red")->getFloatValue();
		sunLightColor.y= sunLightColorNode->getAttribute("green")->getFloatValue();
		sunLightColor.z= sunLightColorNode->getAttribute("blue")->getFloatValue();

		const XmlNode *moonLightColorNode= parametersNode->getChild("moon-light");
		moonLightColor.x= moonLightColorNode->getAttribute("red")->getFloatValue();
		moonLightColor.y= moonLightColorNode->getAttribute("green")->getFloatValue();
		moonLightColor.z= moonLightColorNode->getAttribute("blue")->getFloatValue();

		if(parametersNode->hasChild("shadow-intensity")) {
			const XmlNode *shadowIntenseNode= parametersNode->getChild("shadow-intensity");
			shadowIntensity= shadowIntenseNode->getAttribute("value")->getFloatValue();
		} else {
			shadowIntensity=standardShadowIntensity;
		}

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		//weather
		const XmlNode *weatherNode= parametersNode->getChild("weather");
		float sunnyProb= weatherNode->getAttribute("sun")->getFloatValue(0.f, 1.f);
		float rainyProb= weatherNode->getAttribute("rain")->getFloatValue(0.f, 1.f) + sunnyProb;

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

#ifdef USE_STREFLOP
		float rnd= streflop::fabs(static_cast<streflop::Simple>(random.randRange(-1.f, 1.f)));
#else
		float rnd= fabs(random.randRange(-1.f, 1.f));
#endif

		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

		if(rnd < sunnyProb) {
			weather= wSunny;
		}
		else if(rnd < rainyProb) {
			weather= wRainy;
		}
		else {
			weather= wSnowy;
		}

		//printf("==> Weather is: %d rnd = %f [sun: %f rainyProb: %f]",weather,rnd,sunnyProb,rainyProb);

		//airHeight
		if(parametersNode->hasChild("air-height")) {
			const XmlNode *node= parametersNode->getChild("air-height");
			airHeight= node->getAttribute("value")->getFloatValue();
			// airHeight should not be lower than default
			if( airHeight<Tileset::standardAirHeight){
				airHeight=standardAirHeight;
			}
			// airHeight should not be bigger than 3 x default
			if( airHeight>3*Tileset::standardAirHeight){
				airHeight=3*Tileset::standardAirHeight;
			}
		}



		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);

	}
	//Exception handling (conversions and so on);
    catch(megaglest_runtime_error& ex) {
		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
		throw megaglest_runtime_error("Error loading tileset: "+ path + "\nMessage: " + ex.what(),!ex.wantStackTrace() );
    }
    catch(const exception &e) {
		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
		throw megaglest_runtime_error("Error: " + path + "\n" + e.what());
	}

    Lang &lang = Lang::getInstance();
    lang.loadTilesetStrings(name);
}

Tileset::~Tileset() {
	for(int i = 0; i < surfCount; ++i) {
		deleteValues(surfPixmaps[i].begin(),surfPixmaps[i].end());
		surfPixmaps[i].clear();
	}

	Logger::getInstance().add(Lang::getInstance().getString("LogScreenGameUnLoadingTileset","",true), true);
}

const Pixmap2D *Tileset::getSurfPixmap(int type, int var) const{
	int vars= (int)surfPixmaps[type].size();
	return surfPixmaps[type][var % vars];
}

void Tileset::addSurfTex(int leftUp, int rightUp, int leftDown, int rightDown, Vec2f &coord, const Texture2D *&texture, int mapX, int mapY) {
	//center textures
	if(leftUp == rightUp && leftUp == leftDown && leftUp == rightDown) {
		//texture variation according to probability
		float r= random.randRange(0.f, 1.f);
		const Pixmap2D *pixmap = NULL;

		if(surfProbs[leftUp][0] < 0) {
			// big textures use coordinates
			int parts = partsArray[leftUp];
			pixmap = getSurfPixmap(leftUp, (mapY % parts) * parts + (mapX % parts));
		}
		else {
			float max= 0.f;
			int var= 0;
			for(int i=0; i < (int)surfProbs[leftUp].size(); ++i) {
				max += surfProbs[leftUp][i];
				if(r <= max) {
					var= i;
					break;
				}
			}
			pixmap=getSurfPixmap(leftUp, var);
		}
		SurfaceInfo si(pixmap);
		surfaceAtlas.addSurface(&si);
		coord= si.getCoord();
		// only for 512px printf("coord.x=%f coord.y=%f mapX=%d mapY=%d  result=%d\n",coord.x,coord.y,mapX,mapY,(mapY%8)*8+(mapX%8));
		texture= si.getTexture();
	}
	//spatted textures
	else {
		int var= random.randRange(0, transitionVars);

		SurfaceInfo si( getSurfPixmap(leftUp, var),
						getSurfPixmap(rightUp, var),
						getSurfPixmap(leftDown, var),
						getSurfPixmap(rightDown, var));
		surfaceAtlas.addSurface(&si);
		coord= si.getCoord();
		texture= si.getTexture();
	}
}

}}// end namespace
