1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "tileset.h"
13 
14 #include <cassert>
15 #include <ctime>
16 
17 #include "logger.h"
18 #include "util.h"
19 #include "renderer.h"
20 #include "game_util.h"
21 #include "leak_dumper.h"
22 #include "properties.h"
23 #include "lang.h"
24 #include "platform_util.h"
25 
26 using namespace Shared::Util;
27 using namespace Shared::Xml;
28 using namespace Shared::Graphics;
29 
30 namespace Glest{ namespace Game{
31 
32 const float Tileset::standardAirHeight= 5.0f;
33 const float Tileset::standardShadowIntensity= 0.2f;
34 // =====================================================
35 // 	class AmbientSounds
36 // =====================================================
37 
load(const string & dir,const XmlNode * xmlNode,std::map<string,vector<pair<string,string>>> & loadedFileList,string parentLoader)38 void AmbientSounds::load(const string &dir, const XmlNode *xmlNode,
39 		std::map<string,vector<pair<string, string> > > &loadedFileList, string parentLoader) {
40 	string path="";
41 
42 	//day
43 	const XmlNode *dayNode= xmlNode->getChild("day-sound");
44 	enabledDay= dayNode->getAttribute("enabled")->getBoolValue();
45 	if(enabledDay) {
46 		string currentPath = dir;
47 		endPathWithSlash(currentPath);
48 
49 		path= dayNode->getAttribute("path")->getRestrictedValue(currentPath);
50 		day.open(path);
51 		loadedFileList[path].push_back(make_pair(parentLoader,dayNode->getAttribute("path")->getRestrictedValue()));
52 
53 		alwaysPlayDay= dayNode->getAttribute("play-always")->getBoolValue();
54 	}
55 
56 	//night
57 	const XmlNode *nightNode= xmlNode->getChild("night-sound");
58 	enabledNight= nightNode->getAttribute("enabled")->getBoolValue();
59 	if(enabledNight) {
60 		string currentPath = dir;
61 		endPathWithSlash(currentPath);
62 
63 		path= nightNode->getAttribute("path")->getRestrictedValue(currentPath);
64 		night.open(path);
65 		loadedFileList[path].push_back(make_pair(parentLoader,nightNode->getAttribute("path")->getRestrictedValue()));
66 
67 		alwaysPlayNight= nightNode->getAttribute("play-always")->getBoolValue();
68 	}
69 
70 	//rain
71 	const XmlNode *rainNode= xmlNode->getChild("rain-sound");
72 	enabledRain= rainNode->getAttribute("enabled")->getBoolValue();
73 	if(enabledRain) {
74 		string currentPath = dir;
75 		endPathWithSlash(currentPath);
76 
77 		path= rainNode->getAttribute("path")->getRestrictedValue(currentPath);
78 		rain.open(path);
79 		loadedFileList[path].push_back(make_pair(parentLoader,rainNode->getAttribute("path")->getRestrictedValue()));
80 	}
81 
82 	//snow
83 	const XmlNode *snowNode= xmlNode->getChild("snow-sound");
84 	enabledSnow= snowNode->getAttribute("enabled")->getBoolValue();
85 	if(enabledSnow) {
86 		string currentPath = dir;
87 		endPathWithSlash(currentPath);
88 
89 		path= snowNode->getAttribute("path")->getRestrictedValue(currentPath);
90 		snow.open(path);
91 		loadedFileList[path].push_back(make_pair(parentLoader,snowNode->getAttribute("path")->getRestrictedValue()));
92 	}
93 
94 	//dayStart
95 	const XmlNode *dayStartNode= xmlNode->getChild("day-start-sound");
96 	enabledDayStart= dayStartNode->getAttribute("enabled")->getBoolValue();
97 	if(enabledDayStart) {
98 		string currentPath = dir;
99 		endPathWithSlash(currentPath);
100 
101 		path= dayStartNode->getAttribute("path")->getRestrictedValue(currentPath);
102 		dayStart.load(path);
103 		loadedFileList[path].push_back(make_pair(parentLoader,dayStartNode->getAttribute("path")->getRestrictedValue()));
104 	}
105 
106 	//nightStart
107 	const XmlNode *nightStartNode= xmlNode->getChild("night-start-sound");
108 	enabledNightStart= nightStartNode->getAttribute("enabled")->getBoolValue();
109 	if(enabledNightStart) {
110 		string currentPath = dir;
111 		endPathWithSlash(currentPath);
112 
113 		path= nightStartNode->getAttribute("path")->getRestrictedValue(currentPath);
114 		nightStart.load(path);
115 		loadedFileList[path].push_back(make_pair(parentLoader,nightStartNode->getAttribute("path")->getRestrictedValue()));
116 	}
117 }
118 
119 // =====================================================
120 // 	class Tileset
121 // =====================================================
122 
loadTileset(const vector<string> pathList,const string & tilesetName,Checksum * checksum,std::map<string,vector<pair<string,string>>> & loadedFileList)123 Checksum Tileset::loadTileset(const vector<string> pathList, const string &tilesetName,
124 		Checksum* checksum, std::map<string,vector<pair<string, string> > > &loadedFileList) {
125     Checksum tilesetChecksum;
126 
127     bool found = false;
128     for(int idx = 0; idx < (int)pathList.size(); idx++) {
129 		string currentPath = pathList[idx];
130 		endPathWithSlash(currentPath);
131         string path = currentPath + tilesetName;
132         if(isdir(path.c_str()) == true) {
133             load(path, checksum, &tilesetChecksum, loadedFileList);
134             found = true;
135             break;
136         }
137     }
138     if(found == false) {
139 		throw megaglest_runtime_error("Error could not find tileset [" + tilesetName + "]\n",true);
140 
141     }
142     return tilesetChecksum;
143 }
144 
145 
load(const string & dir,Checksum * checksum,Checksum * tilesetChecksum,std::map<string,vector<pair<string,string>>> & loadedFileList)146 void Tileset::load(const string &dir, Checksum *checksum, Checksum *tilesetChecksum,
147 		std::map<string,vector<pair<string, string> > > &loadedFileList) {
148 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
149 
150 	random.init(time(NULL));
151 
152 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
153 
154 	string name= lastDir(dir);
155 	tileset_name = name;
156 	string currentPath = dir;
157 	endPathWithSlash(currentPath);
158 	string path= currentPath + name + ".xml";
159 	string sourceXMLFile = path;
160 
161 	checksum->addFile(path);
162 	tilesetChecksum->addFile(path);
163 	checksumValue.addFile(path);
164 
165 	try {
166 		char szBuf[8096]="";
167 		snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingTileset","",true).c_str(),formatString(name).c_str());
168 		Logger::getInstance().add(szBuf, true);
169 
170 		Renderer &renderer= Renderer::getInstance();
171 
172 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
173 
174 		//printf("About to load tileset [%s]\n",path.c_str());
175 		//parse xml
176 		XmlTree xmlTree;
177 		xmlTree.load(path,Properties::getTagReplacementValues());
178 		loadedFileList[path].push_back(make_pair(currentPath,currentPath));
179 
180 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
181 
182 		const XmlNode *tilesetNode= xmlTree.getRootNode();
183 
184 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
185 
186 		//surfaces
187 		const XmlNode *surfacesNode= tilesetNode->getChild("surfaces");
188 		int partsize= 0;
189 		for(int i=0; i < surfCount; ++i) {
190 
191 			const XmlNode *surfaceNode;
192 			if(surfacesNode->hasChildAtIndex("surface",i)){
193 				surfaceNode= surfacesNode->getChild("surface", i);
194 			}
195 			else {
196 				// cliff texture does not exist, use texture 2 instead
197 				surfaceNode= surfacesNode->getChild("surface", 2);
198 			}
199 
200 			if(surfaceNode->hasAttribute("partsize")){
201 				partsize=surfaceNode->getAttribute("partsize",true)->getIntValue();
202 			}
203 			else{
204 				partsize=0;
205 			}
206 
207 			if(partsize==0){
208 				int childCount= (int)surfaceNode->getChildCount();
209 				surfPixmaps[i].resize(childCount);
210 				surfProbs[i].resize(childCount);
211 
212 				for(int j = 0; j < childCount; ++j) {
213 					surfPixmaps[i][j] = NULL;
214 				}
215 
216 				for(int j = 0; j < childCount; ++j) {
217 					const XmlNode *textureNode= surfaceNode->getChild("texture", j);
218 					if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
219 						surfPixmaps[i][j] = new Pixmap2D();
220 						surfPixmaps[i][j]->init(3);
221 						surfPixmaps[i][j]->load(textureNode->getAttribute("path")->getRestrictedValue(currentPath));
222 					}
223 					loadedFileList[textureNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,textureNode->getAttribute("path")->getRestrictedValue()));
224 
225 					surfProbs[i][j]= textureNode->getAttribute("prob")->getFloatValue();
226 				}
227 			}
228 			else {
229 				// read single big texture and cut it into pieces
230 				const XmlNode *textureNode= surfaceNode->getChild("texture", 0);
231 
232 				// There is no way to figure out parts without loading the texture
233 				// unfortunately we must load it even for headless server
234 				// to get width and height
235 				bool switchOffNonGraphicalModeEnabled = GlobalStaticFlags::getIsNonGraphicalModeEnabled();
236 				if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
237 					GlobalStaticFlags::setIsNonGraphicalModeEnabled(false);
238 				}
239 
240 				string exceptionError = "";
241 				Pixmap2D *pixmap 	= NULL;
242 				int width 			= 0;
243 				int height 			= 0;
244 
245 				try {
246 					pixmap=new Pixmap2D();
247 					pixmap->init(3);
248 					pixmap->load(textureNode->getAttribute("path")->getRestrictedValue(currentPath));
249 					loadedFileList[textureNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,textureNode->getAttribute("path")->getRestrictedValue()));
250 
251 					width  = pixmap->getW();
252 					height = pixmap->getW();
253 				}
254 			    catch(megaglest_runtime_error& ex) {
255 					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
256 					throw megaglest_runtime_error("Error loading tileset: "+ path + "\nMessage: " + ex.what(),!ex.wantStackTrace() );
257 			    }
258 				catch(const exception &ex) {
259 					SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
260 
261 					exceptionError = "Error: " + path + "\n" + ex.what();
262 				}
263 
264 				if(switchOffNonGraphicalModeEnabled == true) {
265 					GlobalStaticFlags::setIsNonGraphicalModeEnabled(true);
266 
267 					delete pixmap;
268 					pixmap = NULL;
269 				}
270 
271 				if(exceptionError != "") {
272 					throw megaglest_runtime_error(exceptionError.c_str());
273 				}
274 
275 				if(width != height) {
276 					throw megaglest_runtime_error("width != height");
277 				}
278 				if(width % 64 != 0) {
279 					throw megaglest_runtime_error("width % 64 != 0");
280 				}
281 				if(width % partsize != 0) {
282 					throw megaglest_runtime_error("width % partsize != 0");
283 				}
284 
285 				int parts=width/partsize;
286 				int numberOfPieces=parts*parts;
287 				partsArray[i]=parts;
288 				surfPixmaps[i].resize(numberOfPieces);
289 				surfProbs[i].resize(numberOfPieces);
290 				int j=0;
291 				for(int x = 0; x < parts; ++x) {
292 					for(int y = 0; y < parts; ++y) {
293 						if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
294 							surfPixmaps[i][j] = new Pixmap2D();
295 							surfPixmaps[i][j]->init(partsize,partsize,3);
296 							surfPixmaps[i][j]->copyImagePart(x*partsize,y*partsize,pixmap);
297 						}
298 						surfProbs[i][j]=-1;
299 						j++;
300 					}
301 				}
302 			}
303 		}
304 
305 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
306 
307 		//object models
308 		const XmlNode *objectsNode= tilesetNode->getChild("objects");
309 		for(int i=0; i<objCount; ++i){
310 			const XmlNode *objectNode= objectsNode->getChild("object", i);
311 			int childCount= (int)objectNode->getChildCount();
312 
313 			int objectHeight = 0;
314 			bool walkable = objectNode->getAttribute("walkable")->getBoolValue();
315 			if(walkable == false) {
316 				const XmlAttribute *heightAttribute = objectNode->getAttribute("height",false);
317 				if(heightAttribute != NULL) {
318 					objectHeight = heightAttribute->getIntValue();
319 				}
320 			}
321 
322 			objectTypes[i].init(childCount, i, walkable,objectHeight);
323 			for(int j=0; j<childCount; ++j) {
324 				const XmlNode *modelNode= objectNode->getChild("model", j);
325 				const XmlAttribute *pathAttribute= modelNode->getAttribute("path");
326 				TilesetModelType* tmt=objectTypes[i].loadModel(pathAttribute->getRestrictedValue(currentPath),&loadedFileList, sourceXMLFile);
327 				loadedFileList[pathAttribute->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,pathAttribute->getRestrictedValue()));
328 
329 				if(modelNode->hasAttribute("anim-speed") == true) {
330 					int animSpeed= modelNode->getAttribute("anim-speed")->getIntValue();
331 					tmt->setAnimSpeed(animSpeed);
332 				}
333 
334 				if(modelNode->hasChild("particles")){
335 					const XmlNode *particleNode= modelNode->getChild("particles");
336 					bool particleEnabled= particleNode->getAttribute("value")->getBoolValue();
337 					if(particleEnabled){
338 						for(int k=0; k < (int)particleNode->getChildCount(); ++k){
339 							const XmlNode *particleFileNode= particleNode->getChild("particle-file", k);
340 							string path= particleFileNode->getAttribute("path")->getRestrictedValue();
341 							ObjectParticleSystemType *objectParticleSystemType= new ObjectParticleSystemType();
342 							objectParticleSystemType->load(particleFileNode, dir, currentPath + path,
343 									&Renderer::getInstance(), loadedFileList, sourceXMLFile,"");
344 							loadedFileList[currentPath + path].push_back(make_pair(sourceXMLFile,particleFileNode->getAttribute("path")->getRestrictedValue()));
345 
346 							tmt->addParticleSystem(objectParticleSystemType);
347 						}
348 					}
349 				}
350 
351 				//rotationAllowed
352 				if(modelNode->hasAttribute("rotationAllowed") == true) {
353 					tmt->setRotationAllowed(modelNode->getAttribute("rotationAllowed")->getBoolValue());
354 				}
355 				else if(modelNode->hasChild("rotationAllowed")){
356 					const XmlNode *rotationAllowedNode= modelNode->getChild("rotationAllowed");
357 					tmt->setRotationAllowed(rotationAllowedNode->getAttribute("value")->getBoolValue());
358 				}
359 				else{
360 					tmt->setRotationAllowed(true);
361 				}
362 				//randomPositionEnabled
363 				if(modelNode->hasAttribute("randomPositionEnabled") == true) {
364 					tmt->setRandomPositionEnabled(modelNode->getAttribute("randomPositionEnabled")->getBoolValue());
365 				}
366 				else{
367 					tmt->setRandomPositionEnabled(true);
368 				}
369 
370 				//smoothTwoFrameAnim
371 				if(modelNode->hasAttribute("smoothTwoFrameAnim") == true) {
372 					tmt->setSmoothTwoFrameAnim(modelNode->getAttribute("smoothTwoFrameAnim")->getBoolValue());
373 				}
374 				else{
375 					tmt->setSmoothTwoFrameAnim(false);
376 				}
377 			}
378 		}
379 
380 		// Now free up the pixmap memory
381 		for(int i=0; i<objCount; ++i){
382 			objectTypes[i].deletePixels();
383 		}
384 
385 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
386 
387 		//ambient sounds
388 		ambientSounds.load(dir, tilesetNode->getChild("ambient-sounds"), loadedFileList, sourceXMLFile);
389 
390 		//parameters
391 		const XmlNode *parametersNode= tilesetNode->getChild("parameters");
392 
393 		//water
394 		const XmlNode *waterNode= parametersNode->getChild("water");
395 		waterTex= renderer.newTexture3D(rsGame);
396 		if(waterTex) {
397 			waterTex->setMipmap(false);
398 			waterTex->setWrapMode(Texture::wmRepeat);
399 		}
400 		waterEffects= waterNode->getAttribute("effects")->getBoolValue();
401 
402 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
403 
404 		int waterFrameCount= (int)waterNode->getChildCount();
405 		if(waterTex) {
406 			waterTex->getPixmap()->init(waterFrameCount, 4);
407 		}
408 		for(int i=0; i<waterFrameCount; ++i){
409 			const XmlNode *waterFrameNode= waterNode->getChild("texture", i);
410 			if(waterTex) {
411 				waterTex->getPixmap()->loadSlice(waterFrameNode->getAttribute("path")->getRestrictedValue(currentPath), i);
412 			}
413 			loadedFileList[waterFrameNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,waterFrameNode->getAttribute("path")->getRestrictedValue()));
414 		}
415 
416 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
417 
418 		//fog
419 		const XmlNode *fogNode= parametersNode->getChild("fog");
420 		fog= fogNode->getAttribute("enabled")->getBoolValue();
421 		if(fog){
422 			fogMode= fogNode->getAttribute("mode")->getIntValue(1, 2);
423 			fogDensity= fogNode->getAttribute("density")->getFloatValue();
424 			fogColor.x= fogNode->getAttribute("color-red")->getFloatValue(0.f, 1.f);
425 			fogColor.y= fogNode->getAttribute("color-green")->getFloatValue(0.f, 1.f);
426 			fogColor.z= fogNode->getAttribute("color-blue")->getFloatValue(0.f, 1.f);
427 		}
428 
429 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
430 
431 		//sun and moon light colors
432 		const XmlNode *sunLightColorNode= parametersNode->getChild("sun-light");
433 		sunLightColor.x= sunLightColorNode->getAttribute("red")->getFloatValue();
434 		sunLightColor.y= sunLightColorNode->getAttribute("green")->getFloatValue();
435 		sunLightColor.z= sunLightColorNode->getAttribute("blue")->getFloatValue();
436 
437 		const XmlNode *moonLightColorNode= parametersNode->getChild("moon-light");
438 		moonLightColor.x= moonLightColorNode->getAttribute("red")->getFloatValue();
439 		moonLightColor.y= moonLightColorNode->getAttribute("green")->getFloatValue();
440 		moonLightColor.z= moonLightColorNode->getAttribute("blue")->getFloatValue();
441 
442 		if(parametersNode->hasChild("shadow-intensity")) {
443 			const XmlNode *shadowIntenseNode= parametersNode->getChild("shadow-intensity");
444 			shadowIntensity= shadowIntenseNode->getAttribute("value")->getFloatValue();
445 		} else {
446 			shadowIntensity=standardShadowIntensity;
447 		}
448 
449 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
450 
451 		//weather
452 		const XmlNode *weatherNode= parametersNode->getChild("weather");
453 		float sunnyProb= weatherNode->getAttribute("sun")->getFloatValue(0.f, 1.f);
454 		float rainyProb= weatherNode->getAttribute("rain")->getFloatValue(0.f, 1.f) + sunnyProb;
455 
456 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
457 
458 #ifdef USE_STREFLOP
459 		float rnd= streflop::fabs(static_cast<streflop::Simple>(random.randRange(-1.f, 1.f)));
460 #else
461 		float rnd= fabs(random.randRange(-1.f, 1.f));
462 #endif
463 
464 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
465 
466 		if(rnd < sunnyProb) {
467 			weather= wSunny;
468 		}
469 		else if(rnd < rainyProb) {
470 			weather= wRainy;
471 		}
472 		else {
473 			weather= wSnowy;
474 		}
475 
476 		//printf("==> Weather is: %d rnd = %f [sun: %f rainyProb: %f]",weather,rnd,sunnyProb,rainyProb);
477 
478 		//airHeight
479 		if(parametersNode->hasChild("air-height")) {
480 			const XmlNode *node= parametersNode->getChild("air-height");
481 			airHeight= node->getAttribute("value")->getFloatValue();
482 			// airHeight should not be lower than default
483 			if( airHeight<Tileset::standardAirHeight){
484 				airHeight=standardAirHeight;
485 			}
486 			// airHeight should not be bigger than 3 x default
487 			if( airHeight>3*Tileset::standardAirHeight){
488 				airHeight=3*Tileset::standardAirHeight;
489 			}
490 		}
491 
492 
493 
494 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
495 
496 	}
497 	//Exception handling (conversions and so on);
498     catch(megaglest_runtime_error& ex) {
499 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
500 		throw megaglest_runtime_error("Error loading tileset: "+ path + "\nMessage: " + ex.what(),!ex.wantStackTrace() );
501     }
502     catch(const exception &e) {
503 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
504 		throw megaglest_runtime_error("Error: " + path + "\n" + e.what());
505 	}
506 
507     Lang &lang = Lang::getInstance();
508     lang.loadTilesetStrings(name);
509 }
510 
~Tileset()511 Tileset::~Tileset() {
512 	for(int i = 0; i < surfCount; ++i) {
513 		deleteValues(surfPixmaps[i].begin(),surfPixmaps[i].end());
514 		surfPixmaps[i].clear();
515 	}
516 
517 	Logger::getInstance().add(Lang::getInstance().getString("LogScreenGameUnLoadingTileset","",true), true);
518 }
519 
getSurfPixmap(int type,int var) const520 const Pixmap2D *Tileset::getSurfPixmap(int type, int var) const{
521 	int vars= (int)surfPixmaps[type].size();
522 	return surfPixmaps[type][var % vars];
523 }
524 
addSurfTex(int leftUp,int rightUp,int leftDown,int rightDown,Vec2f & coord,const Texture2D * & texture,int mapX,int mapY)525 void Tileset::addSurfTex(int leftUp, int rightUp, int leftDown, int rightDown, Vec2f &coord, const Texture2D *&texture, int mapX, int mapY) {
526 	//center textures
527 	if(leftUp == rightUp && leftUp == leftDown && leftUp == rightDown) {
528 		//texture variation according to probability
529 		float r= random.randRange(0.f, 1.f);
530 		const Pixmap2D *pixmap = NULL;
531 
532 		if(surfProbs[leftUp][0] < 0) {
533 			// big textures use coordinates
534 			int parts = partsArray[leftUp];
535 			pixmap = getSurfPixmap(leftUp, (mapY % parts) * parts + (mapX % parts));
536 		}
537 		else {
538 			float max= 0.f;
539 			int var= 0;
540 			for(int i=0; i < (int)surfProbs[leftUp].size(); ++i) {
541 				max += surfProbs[leftUp][i];
542 				if(r <= max) {
543 					var= i;
544 					break;
545 				}
546 			}
547 			pixmap=getSurfPixmap(leftUp, var);
548 		}
549 		SurfaceInfo si(pixmap);
550 		surfaceAtlas.addSurface(&si);
551 		coord= si.getCoord();
552 		// 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));
553 		texture= si.getTexture();
554 	}
555 	//spatted textures
556 	else {
557 		int var= random.randRange(0, transitionVars);
558 
559 		SurfaceInfo si( getSurfPixmap(leftUp, var),
560 						getSurfPixmap(rightUp, var),
561 						getSurfPixmap(leftDown, var),
562 						getSurfPixmap(rightDown, var));
563 		surfaceAtlas.addSurface(&si);
564 		coord= si.getCoord();
565 		texture= si.getTexture();
566 	}
567 }
568 
569 }}// end namespace
570