Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / tile_bank.cpp
blobc8c232ecf3852f1e407745f3f210cdc34157879d
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/tile_bank.h"
23 #include "nel/3d/texture_file.h"
24 #include "nel/3d/tile_noise_map.h"
26 #include "nel/misc/stream.h"
27 #include "nel/misc/common.h"
28 #include "nel/misc/path.h"
29 #include "nel/misc/file.h"
30 #include <string>
32 using namespace NLMISC;
33 using namespace std;
35 #ifdef DEBUG_NEW
36 #define new DEBUG_NEW
37 #endif
39 namespace NL3D
43 // ***************************************************************************
44 // ***************************************************************************
45 // TileBankLand.
46 // ***************************************************************************
47 // ***************************************************************************
50 // ***************************************************************************
51 const sint CTileLand::_Version=0;
52 // ***************************************************************************
53 void CTileLand::serial(NLMISC::IStream &f)
55 (void)f.serialVersion(_Version);
57 f.serial (_Name);
58 f.serialCont (_TileSet);
60 // ***************************************************************************
61 void CTileLand::addTileSet (const std::string& name)
63 _TileSet.insert (name);
65 // ***************************************************************************
66 void CTileLand::removeTileSet (const std::string& name)
68 _TileSet.erase (name);
70 // ***************************************************************************
71 void CTileLand::setName (const std::string& name)
73 _Name=name;
75 // ***************************************************************************
78 // ***************************************************************************
79 // ***************************************************************************
80 // CTileBank.
81 // ***************************************************************************
82 // ***************************************************************************
85 // ***************************************************************************
86 const sint CTileBank::_Version=4;
87 // ***************************************************************************
88 CTileBank::CTileBank ()
90 // Default _DisplacementMap
91 _DisplacementMap.resize (1);
93 // Fill it with 0
94 _DisplacementMap[0].setEmpty ();
96 // ***************************************************************************
97 void CTileBank::serial(NLMISC::IStream &f)
99 f.serialCheck (std::string ("BANK"));
101 sint streamver = f.serialVersion(_Version);
103 // Version 1 not compatible
104 if (f.isReading())
106 if (streamver<2)
107 throw EOlderStream(f);
110 switch (streamver)
112 case 4:
113 // Displacement map array
114 f.serialCont (_DisplacementMap);
115 if (f.isReading())
117 // Checks
118 nlassert (!_DisplacementMap.empty());
120 // Set first empty
121 _DisplacementMap[0].setEmpty ();
123 case 3:
124 // Absolute path
125 f.serial (_AbsPath);
126 case 2:
127 // Serial all containers
128 f.serialCont (_LandVector);
129 f.serialCont (_TileSetVector);
130 f.serialCont (_TileVector);
133 // Compute XRef in read mode
134 if (f.isReading())
135 computeXRef ();
137 // If Version<=2, remove diffuse and alpha tiles in transitions
138 if (streamver<=2)
140 // Must be reading
141 nlassert (f.isReading());
143 // Reset _AbsPath
144 _AbsPath.clear();
146 // Remove diffuse and additive in transition
147 uint tileCount=(uint)getTileCount ();
148 for (uint i=0; i<tileCount; i++)
150 int tileSet;
151 int number;
152 TTileType type;
154 // Get xref
155 getTileXRef (i, tileSet, number, type);
157 // Transition ?
158 if (type==transition)
160 // Remove diffuse bitmap
161 getTileSet(tileSet)->clearTransition ((CTileSet::TTransition)number, CTile::diffuse, *this);
163 // Remove alpha bitmap
164 getTileSet(tileSet)->clearTransition ((CTileSet::TTransition)number, CTile::alpha, *this);
169 // ***************************************************************************
170 sint CTileBank::addLand (const std::string& name)
172 sint last=(sint)_LandVector.size();
173 _LandVector.push_back(CTileLand());
174 _LandVector[last].setName (name);
175 return last;
177 // ***************************************************************************
178 void CTileBank::removeLand (sint landIndex)
180 // Check args
181 nlassert (landIndex>=0);
182 nlassert (landIndex<(sint)_LandVector.size());
184 _LandVector.erase (_LandVector.begin ()+landIndex);
186 // ***************************************************************************
187 sint CTileBank::addTileSet (const std::string& name)
189 sint last=(sint)_TileSetVector.size();
190 _TileSetVector.push_back(CTileSet());
191 _TileSetVector[last].setName (name);
192 for (int i=0; i<CTileSet::count; i++)
194 _TileSetVector[last]._TileTransition[i]._Tile=createTile ();
196 return last;
198 // ***************************************************************************
199 void CTileBank::removeTileSet (sint setIndex)
201 // Check args
202 nlassert (setIndex>=0);
203 nlassert (setIndex<(sint)_TileSetVector.size());
205 for (int i=0; i<CTileSet::count; i++)
207 int index=_TileSetVector[setIndex]._TileTransition[i]._Tile;
208 if (index!=-1)
209 freeTile (index);
211 _TileSetVector.erase (_TileSetVector.begin ()+setIndex);
213 // ***************************************************************************
214 void CTileBank::clear ()
216 _LandVector.clear ();
217 _TileSetVector.clear ();
218 _TileVector.clear ();
219 _TileXRef.clear ();
220 _DisplacementMap.clear ();
221 _AbsPath.clear ();
223 // ***************************************************************************
224 sint CTileBank::createTile ()
226 // Look for a free tile
227 for (int i=0; i<(sint)_TileVector.size(); i++)
229 if (_TileVector[i].isFree())
231 _TileVector[i].setFileName (CTile::diffuse, "");
232 _TileVector[i].setFileName (CTile::additive, "");
233 _TileVector[i].setFileName (CTile::alpha, "");
234 return i;
238 // Nothing free, add a tile at the end
239 _TileVector.push_back (CTile());
240 _TileVector[_TileVector.size()-1].setFileName (CTile::diffuse, "");
241 _TileVector[_TileVector.size()-1].setFileName (CTile::additive, "");
242 _TileVector[_TileVector.size()-1].setFileName (CTile::alpha, "");
243 return (sint)_TileVector.size()-1;
245 // ***************************************************************************
246 void CTileBank::freeTile (int tileIndex)
248 // Check args
249 nlassert (tileIndex>=0);
250 nlassert (tileIndex<(sint)_TileVector.size());
252 // Free
253 _TileVector[tileIndex].freeBlock();
255 // Resize tile table
256 int i;
257 for (i=(sint)_TileVector.size()-1; i>=0; i--)
259 if (!_TileVector[i].isFree ())
260 break;
262 if (i<(sint)_TileVector.size()-1)
263 _TileVector.resize (i+1);
265 // ***************************************************************************
266 sint CTileBank::getNumBitmap (CTile::TBitmap bitmap) const
268 std::set<std::string> setString;
269 for (int i=0; i<(sint)_TileVector.size(); i++)
271 if (!_TileVector[i].isFree())
273 const std::string &str=_TileVector[i].getRelativeFileName (bitmap);
274 if (!str.empty())
276 std::vector<char> vect (str.length()+1);
277 memcpy (&*vect.begin(), str.c_str(), str.length()+1);
278 toLowerAscii(&*vect.begin());
279 setString.insert (std::string (&*vect.begin()));
283 return (sint)setString.size();
285 // ***************************************************************************
286 void CTileBank::computeXRef ()
288 // Resize
289 _TileXRef.resize (_TileVector.size());
291 // Erase number of the tileset in xref
292 for (int tile=0; tile<(sint)_TileVector.size(); tile++)
293 _TileXRef[tile]._XRefTileSet=-1;
295 // Erase number of the tileset in xref
296 for (int s=0; s<(sint)_TileSetVector.size(); s++)
298 int t;
299 CTileSet *tileSet=getTileSet (s);
300 for (t=0; t<tileSet->getNumTile128(); t++)
302 int index=tileSet->getTile128 (t);
303 _TileXRef[index]._XRefTileSet=s;
304 _TileXRef[index]._XRefTileNumber=t;
305 _TileXRef[index]._XRefTileType=_128x128;
307 for (t=0; t<tileSet->getNumTile256(); t++)
309 int index=tileSet->getTile256 (t);
310 _TileXRef[index]._XRefTileSet=s;
311 _TileXRef[index]._XRefTileNumber=t;
312 _TileXRef[index]._XRefTileType=_256x256;
314 for (t=0; t<CTileSet::count; t++)
316 int index=tileSet->getTransition (t)->getTile();
317 _TileXRef[index]._XRefTileSet=s;
318 _TileXRef[index]._XRefTileNumber=t;
319 _TileXRef[index]._XRefTileType=transition;
323 // ***************************************************************************
324 void CTileBank::xchgTileset (sint firstTileSet, sint secondTileSet)
326 // Some check
327 nlassert ((firstTileSet>=0)&&(firstTileSet<(sint)_TileSetVector.size()));
328 nlassert ((secondTileSet>=0)&&(secondTileSet<(sint)_TileSetVector.size()));
330 // Xchange the sets
331 CTileSet tmp=_TileSetVector[firstTileSet];
332 _TileSetVector[firstTileSet]=_TileSetVector[secondTileSet];
333 _TileSetVector[secondTileSet]=tmp;
335 // ***************************************************************************
336 void TroncFileName (char* sDest, const char* sSrc)
338 const char* ptr=strrchr (sSrc, '\\');
339 if (ptr==NULL)
340 ptr=strrchr (sSrc, '/');
341 if (ptr)
343 ptr++;
344 strcpy (sDest, ptr);
346 else
348 strcpy (sDest, sSrc);
351 // ***************************************************************************
352 // TODO: this is a temporary hack, see if it could be removed
353 void CTileBank::makeAllPathRelative ()
355 // For all tiles
356 for (sint nTile=0; nTile<(sint)_TileVector.size(); nTile++)
358 // Tronc filename
359 char sTmpFileName[512];
361 // Diffuse
362 TroncFileName (sTmpFileName, _TileVector[nTile].getRelativeFileName (CTile::diffuse).c_str());
363 _TileVector[nTile].setFileName (CTile::diffuse, sTmpFileName);
365 // Additive
366 TroncFileName (sTmpFileName, _TileVector[nTile].getRelativeFileName (CTile::additive).c_str());
367 _TileVector[nTile].setFileName (CTile::additive, sTmpFileName);
369 // Alpha
370 TroncFileName (sTmpFileName, _TileVector[nTile].getRelativeFileName (CTile::alpha).c_str());
371 _TileVector[nTile].setFileName (CTile::alpha, sTmpFileName);
374 // For all displaces
375 for (uint i=0; i<_DisplacementMap.size(); i++)
377 // Tronc filename
378 char sTmpFileName[512];
380 TroncFileName (sTmpFileName, _DisplacementMap[i]._FileName.c_str());
381 _DisplacementMap[i]._FileName = sTmpFileName;
386 // ***************************************************************************
387 void CTileBank::makeAllExtensionDDS ()
389 // For all tiles
390 for (sint nTile=0; nTile<(sint)_TileVector.size(); nTile++)
392 string tmp;
393 string::size_type pos;
395 // Diffuse
396 tmp= _TileVector[nTile].getRelativeFileName (CTile::diffuse);
397 pos= tmp.rfind(".tga");
398 if (pos == string::npos)
399 pos = tmp.rfind(".png");
400 if(pos!= string::npos)
402 tmp.replace(pos, 4, ".dds");
403 _TileVector[nTile].setFileName (CTile::diffuse, tmp);
406 // Additive.
407 tmp= _TileVector[nTile].getRelativeFileName (CTile::additive);
408 pos= tmp.rfind(".tga");
409 if (pos == string::npos)
410 pos = tmp.rfind(".png");
411 if(pos!= string::npos)
413 tmp.replace(pos, 4, ".dds");
414 _TileVector[nTile].setFileName (CTile::additive, tmp);
417 // Alpha.
418 tmp= _TileVector[nTile].getRelativeFileName (CTile::alpha);
419 pos= tmp.rfind(".tga");
420 if (pos == string::npos)
421 pos = tmp.rfind(".png");
422 if(pos!= string::npos)
424 tmp.replace(pos, 4, ".dds");
425 _TileVector[nTile].setFileName (CTile::alpha, tmp);
431 // ***************************************************************************
432 void CTileBank::cleanUnusedData ()
434 // Clean each tileset
435 for (uint i=0; i<_TileSetVector.size(); i++)
437 // Clean the tileset
438 _TileSetVector[i].cleanUnusedData ();
441 // Clear the land vector
442 _LandVector.clear();
444 // ***************************************************************************
445 CTileNoiseMap *CTileBank::getTileNoiseMap (uint tileNumber, uint tileSubNoise)
447 if (_DisplacementMap.empty())
449 // it happens when serial a tile bank with version < 4
450 return NULL;
453 // Check tile number..
454 if (tileNumber<_TileVector.size())
456 // Get tileset number
457 uint tileSet=_TileXRef[tileNumber]._XRefTileSet;
459 // Checks
460 if (tileSet<_TileSetVector.size())
462 nlassert (tileSubNoise<CTileSet::CountDisplace);
463 //nlassert (_TileSetVector[tileSet]._DisplacementBitmap[tileSubNoise]<_DisplacementMap.size());
465 if (_TileSetVector[tileSet]._DisplacementBitmap[tileSubNoise]>=_DisplacementMap.size())
466 return NULL;
468 // Return the tile noise map
469 CTileNoise &tileNoise=_DisplacementMap[_TileSetVector[tileSet]._DisplacementBitmap[tileSubNoise]];
471 // Not loaded ?
472 if (tileNoise._TileNoiseMap==NULL)
474 // Load a bitmap
475 CTextureFile texture (getAbsPath()+tileNoise._FileName);
476 texture.loadGrayscaleAsAlpha (false);
477 texture.generate ();
478 texture.convertToType (CBitmap::Luminance);
480 // Alloc
481 tileNoise._TileNoiseMap=new CTileNoiseMap;
483 // Good size ?
484 if ((texture.getWidth ()==NL3D_TILE_NOISE_MAP_SIZE)&&(texture.getHeight()==NL3D_TILE_NOISE_MAP_SIZE))
486 // Copy
487 memcpy (tileNoise._TileNoiseMap->Pixels, &texture.getPixels()[0], NL3D_TILE_NOISE_MAP_SIZE*NL3D_TILE_NOISE_MAP_SIZE);
489 // Remap lumels
490 for (uint i=0; i<NL3D_TILE_NOISE_MAP_SIZE*NL3D_TILE_NOISE_MAP_SIZE; i++)
492 tileNoise._TileNoiseMap->Pixels[i]=(sint8)((uint8)tileNoise._TileNoiseMap->Pixels[i]-128);
493 if (tileNoise._TileNoiseMap->Pixels[i]==-128)
494 tileNoise._TileNoiseMap->Pixels[i]=-127;
497 else
499 // This is not a normal behaviour.
500 string pathname= getAbsPath()+tileNoise._FileName;
501 if( texture.getWidth ()==0 || texture.getHeight ()==0 )
502 nlwarning("TileNoiseMap not found: %s.", pathname.c_str());
503 else
504 nlwarning("Bad TileNoiseMap size: %s.", pathname.c_str());
506 // Not good size, copy a static map
507 sint8 notGoodSizeForm[NL3D_TILE_NOISE_MAP_SIZE*NL3D_TILE_NOISE_MAP_SIZE]=
509 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
510 00, 99, 99, 99, 99, 99, 99, 99, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
511 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
512 00, 99, 00, 99, 99, 99, 99, 99, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
513 00, 99, 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
514 00, 99, 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
515 00, 99, 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
516 00, 99, 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
517 00, 99, 00, 99, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
518 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
519 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
520 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
521 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
522 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
523 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
524 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
525 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
526 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
527 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
528 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
529 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
530 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
531 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
532 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 99, 00,
533 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 99, 00,
534 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 99, 00,
535 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 99, 00,
536 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 99, 00,
537 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 99, 99, 99, 99, 99, 00, 99, 00,
538 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00,
539 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 99, 99, 99, 99, 99, 99, 99, 00,
540 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00
543 // Copy
544 memcpy (tileNoise._TileNoiseMap->Pixels, notGoodSizeForm, NL3D_TILE_NOISE_MAP_SIZE*NL3D_TILE_NOISE_MAP_SIZE);
548 // Return the noise map
549 return tileNoise._TileNoiseMap;
553 if (_DisplacementMap.empty() || _DisplacementMap[0]._TileNoiseMap)
554 return NULL;
556 // Checks
557 nlassert (_DisplacementMap[0]._TileNoiseMap);
558 return _DisplacementMap[0]._TileNoiseMap;
560 // ***************************************************************************
561 void CTileBank::removeDisplacementMap (uint mapId)
563 // Checks
564 nlassert (mapId<_DisplacementMap.size());
566 if (mapId!=0)
568 // Check if another tileSet uses it
569 uint tileSet;
570 for (tileSet=0; tileSet<_TileSetVector.size(); tileSet++)
572 // It uses it ?
573 uint tile;
574 for (tile=0; tile<CTileSet::CountDisplace; tile++)
576 // The same ?
577 if (_TileSetVector[tileSet]._DisplacementBitmap[tile]==mapId)
578 // Stop
579 break;
581 if (tile!=CTileSet::CountDisplace)
582 break;
584 if (tileSet==_TileSetVector.size())
586 // Remove it
587 _DisplacementMap[mapId].reset();
589 // Last element ?
590 if (mapId==_DisplacementMap.size()-1)
592 // Resize the array ?
593 while ((mapId>0)&&(_DisplacementMap[mapId]._FileName.empty()))
594 _DisplacementMap.resize (mapId--);
599 // ***************************************************************************
600 uint CTileBank::getDisplacementMap (const string &fileName)
602 // Lower string
603 string lower=toLowerAscii(fileName);
605 // Look for this texture filename
606 uint noiseTile;
607 for (noiseTile=0; noiseTile<_DisplacementMap.size(); noiseTile++)
609 // Same name ?
610 if (lower==_DisplacementMap[noiseTile]._FileName)
611 return noiseTile;
614 // Look for a free space
615 for (noiseTile=0; noiseTile<_DisplacementMap.size(); noiseTile++)
617 // Same name ?
618 if (_DisplacementMap[noiseTile]._FileName.empty())
619 break;
621 if (noiseTile==_DisplacementMap.size())
623 // Add a tile
624 _DisplacementMap.resize (noiseTile+1);
627 // Set the file name
628 _DisplacementMap[noiseTile]._FileName=lower;
630 return noiseTile;
632 // ***************************************************************************
633 const char* CTileBank::getDisplacementMap (uint noiseMap)
635 return _DisplacementMap[noiseMap]._FileName.c_str();
637 // ***************************************************************************
638 void CTileBank::setDisplacementMap (uint noiseMap, const char *newName)
640 _DisplacementMap[noiseMap]._FileName=newName;
642 // ***************************************************************************
643 uint CTileBank::getDisplacementMapCount () const
645 return (uint)_DisplacementMap.size();
649 // ***************************************************************************
650 const CTileVegetableDesc &CTileBank::getTileVegetableDesc(uint tileNumber) const
652 // Check tile number..
653 if (tileNumber<_TileVector.size())
655 // Get tileset number
656 uint tileSet=_TileXRef[tileNumber]._XRefTileSet;
658 // Checks
659 if (tileSet<_TileSetVector.size())
661 return _TileSetVector[tileSet].getTileVegetableDesc();
666 // if fails for any reason, return an empty tileVegetableDesc;
667 static CTileVegetableDesc emptyTvd;
668 return emptyTvd;
672 // ***************************************************************************
673 void CTileBank::loadTileVegetableDescs()
675 // For all tileSets.
676 uint tileSet;
678 for(tileSet=0; tileSet<_TileSetVector.size(); tileSet++)
680 // load their fileName
681 _TileSetVector[tileSet].loadTileVegetableDesc();
686 // ***************************************************************************
687 void CTileBank::initTileVegetableDescs(CVegetableManager *vegetableManager)
689 // For all tileSets.
690 uint tileSet;
692 for(tileSet=0; tileSet<_TileSetVector.size(); tileSet++)
694 CTileVegetableDesc &tvd= _TileSetVector[tileSet].getTileVegetableDesc();
695 tvd.registerToManager(vegetableManager);
700 // ***************************************************************************
701 void CTileBank::postfixTileFilename (const char *postfix)
703 // For each tiles
704 uint tile;
705 for (tile=0; tile<_TileVector.size (); tile++)
707 // For each bitmap
708 uint bitmap;
709 for (bitmap=0; bitmap<CTile::bitmapCount; bitmap++)
711 string &filename = _TileVector[tile]._BitmapName[bitmap];
712 if (!filename.empty())
714 string ext = CFile::getExtension(filename);
715 string name = CFile::getFilenameWithoutExtension(filename);
716 filename = CFile::getPath (filename);
717 filename += name;
718 filename += postfix;
719 filename += ".";
720 filename += ext;
727 // ***************************************************************************
728 void CTileBank::postfixTileVegetableDesc (const char *postfix)
730 // For each tiles
731 uint tileSet;
732 for (tileSet=0; tileSet<_TileSetVector.size (); tileSet++)
734 string &filename = _TileSetVector[tileSet]._TileVegetableDescFileName;
735 if (!filename.empty())
737 string ext = CFile::getExtension(filename);
738 string name = CFile::getFilenameWithoutExtension(filename);
739 filename = CFile::getPath (filename);
740 filename += name;
741 filename += postfix;
742 filename += ".";
743 filename += ext;
749 // ***************************************************************************
750 // ***************************************************************************
751 // CTile.
752 // ***************************************************************************
753 // ***************************************************************************
756 // ***************************************************************************
757 const sint CTile::_Version=4;
758 // ***************************************************************************
759 void CTile::serial(NLMISC::IStream &f)
761 sint streamver = f.serialVersion(_Version);
763 // Tmp value
764 bool tmp;
765 string tmpStr;
767 switch (streamver)
769 case 4:
770 case 3:
771 case 2:
772 f.serial (_Flags);
774 // Version 2, flags are not the same
775 if (streamver==2)
776 _Flags=(_Flags&NL3D_CTILE_ROT_MASK)|(_Flags&NL3D_CTILE_GROUP_MASK_V2)|(((_Flags&NL3D_CTILE_FREE_FLAG_V2)!=0)?NL3D_CTILE_FREE_FLAG:0);
777 if (streamver==3)
778 _Flags=(_Flags&NL3D_CTILE_ROT_MASK)|(_Flags&NL3D_CTILE_GROUP_MASK_V3)|(((_Flags&NL3D_CTILE_FREE_FLAG_V3)!=0)?NL3D_CTILE_FREE_FLAG:0);
780 f.serial (_BitmapName[diffuse]);
781 f.serial (_BitmapName[additive]);
782 f.serial (_BitmapName[alpha]);
783 break;
784 case 1:
785 // Don't need invert many more
786 f.serial (tmp);
787 case 0:
788 // Initialize flags
789 _Flags=0;
791 // Initialize alpha name
792 _BitmapName[alpha].clear();
794 // Read free flag
795 f.serial (tmp);
797 // If free, set the flag
798 if (tmp)
799 _Flags|=NL3D_CTILE_FREE_FLAG;
801 // Read diffuse bitmap and additive
802 f.serial (_BitmapName[diffuse]);
803 f.serial (_BitmapName[additive]);
805 // Don't need bump name
806 f.serial (tmpStr);
808 break;
811 // ***************************************************************************
812 void CTile::clearTile (CTile::TBitmap type)
814 _BitmapName[type].clear();
818 // ***************************************************************************
819 // ***************************************************************************
820 // CTileSet.
821 // ***************************************************************************
822 // ***************************************************************************
825 // ***************************************************************************
826 const sint CTileSet::_Version=5;
827 // ***************************************************************************
828 const char* CTileSet::_ErrorMessage[CTileSet::errorCount]=
830 "No error.", // ok
831 "Top interface is incompatible.", // topInterfaceProblem
832 "Bottom interface is incompatible.", // bottomInterfaceProblem
833 "Left interface is incompatible.", // leftInterfaceProblem
834 "Right interface is incompatible.", // rightInterfaceProblem
835 "Add first a 128x128 tile.", // addFirstA128128
836 "Top and bottom interface not the same.", // topBottomNotTheSame,
837 "Right and left interface not the same.", // rightLeftNotTheSame
838 "Invalide bitmap size.", // sizeInvalide
840 // ***************************************************************************
841 const CTileSet::TFlagBorder CTileSet::_TransitionFlags[CTileSet::count][4]=
843 {_0000,_1111,_0111,_0111}, // tile 0
844 {_0111,_1111,_0111,_1111}, // tile 1
845 {_0000,_0111,_0000,_0111}, // tile 2
846 {_1110,_1110,_1111,_0000}, // tile 3
847 {_1110,_1111,_1111,_0111}, // tile 4
848 {_0000,_1110,_0111,_0000}, // tile 5
850 {_0000,_1111,_0001,_0001}, // tile 6
851 {_0000,_1000,_0001,_0000}, // tile 7
852 {_1111,_1000,_1111,_1000}, // tile 8
853 {_1000,_1000,_1111,_0000}, // tile 9
854 {_1000,_0000,_1000,_0000}, // tile 10
855 {_1111,_0001,_1000,_1111}, // tile 11
857 {_0000,_1111,_0111,_0001}, // tile 12
858 {_0000,_1111,_0001,_0111}, // tile 13
859 {_0111,_1111,_0001,_1111}, // tile 14
860 {_1110,_1000,_1111,_0000}, // tile 15
861 {_1000,_1110,_1111,_0000}, // tile 16
862 {_1111,_0001,_1110,_1111}, // tile 17
864 {_1000,_0000,_1110,_0000}, // tile 18
865 {_0000,_0111,_0000,_0001}, // tile 19
866 {_1111,_1000,_1111,_1110}, // tile 21
867 {_0111,_0000,_0000,_1000}, // tile 21
868 {_0000,_1000,_0111,_0000}, // tile 22
869 {_1111,_0111,_1000,_1111}, // tile 23
871 {_1111,_0000,_1110,_1110}, // tile 24
872 {_1111,_1110,_1111,_1110}, // tile 25
873 {_1110,_0000,_1110,_0000}, // tile 26
874 {_0111,_0111,_0000,_1111}, // tile 27
875 {_1111,_0111,_1110,_1111}, // tile 28
876 {_0111,_0000,_0000,_1110}, // tile 29
878 {_1111,_0000,_1000,_1000}, // tile 30
879 {_0001,_0000,_0000,_1000}, // tile 31
880 {_0001,_1111,_0001,_1111}, // tile 32
881 {_0001,_0001,_0000,_1111}, // tile 33
882 {_0000,_0001,_0000,_0001}, // tile 34
883 {_1000,_1111,_1111,_0001}, // tile 35
885 {_1111,_0000,_1000,_1110}, // tile 36
886 {_1111,_0000,_1110,_1000}, // tile 37
887 {_1000,_1111,_1111,_0111}, // tile 38
888 {_0001,_0111,_0000,_1111}, // tile 39
889 {_0111,_0001,_0000,_1111}, // tile 40
890 {_1111,_1110,_1111,_1000}, // tile 41
892 {_0000,_0001,_0000,_0111}, // tile 42
893 {_1110,_0000,_1000,_0000}, // tile 43
894 {_0001,_1111,_0111,_1111}, // tile 44
895 {_0000,_1110,_0001,_0000}, // tile 45
896 {_0001,_0000,_0000,_1110}, // tile 46
897 {_1110,_1111,_1111,_0001} // tile 47
899 // ***************************************************************************
900 CTileSet::CTileSet ()
902 // Default, tileset 0
903 _Oriented = false;
904 uint displace;
905 for (displace=FirstDisplace; displace<CountDisplace; displace++)
906 _DisplacementBitmap[displace]=0;
908 // Default user surface data
909 SurfaceData = 0;
911 // ***************************************************************************
912 void CTileSet::setName (const std::string& name)
914 _Name=name;
916 // ***************************************************************************
917 const std::string& CTileSet::getName () const
919 return _Name;
921 // ***************************************************************************
922 void CTileSet::serial(NLMISC::IStream &f)
924 sint streamver = f.serialVersion(_Version);
926 CTileBorder tmp;
928 // serial the user surface data
929 if (streamver>=5)
931 f.serial (SurfaceData);
934 // serial the oriented info which tell if the tile has a special orientation
935 if (streamver>=4)
937 f.serial (_Oriented);
940 // serial vegetable info.
941 if (streamver>=3)
943 // serialisze only the FileName, not the descrpitor
944 f.serial(_TileVegetableDescFileName);
947 // New version
948 if (streamver>=2)
950 uint displace;
951 for (displace=FirstDisplace; displace<CountDisplace; displace++)
952 f.serial (_DisplacementBitmap[displace]);
955 // Serial displacement map filename, obsolete
956 if (streamver==1)
958 // Remove obsolete data
959 string tmp;
960 for (uint displace=FirstDisplace; displace<CountDisplace; displace++)
961 f.serial (tmp);
964 int i;
965 f.serial (_Name);
966 f.serialCont (_Tile128);
967 f.serialCont (_Tile256);
968 for (i=0; i<count; i++)
969 f.serial (_TileTransition[i]);
970 f.serialCont (_ChildName);
971 f.serial (_Border128[CTile::diffuse]);
972 f.serial (_Border128[CTile::additive]);
974 // old field, border bump 128
975 if (streamver==0)
976 f.serial (tmp);
978 f.serial (_Border256[CTile::diffuse]);
979 f.serial (_Border256[CTile::additive]);
981 // old field, border bump 256
982 if (streamver==0)
983 f.serial (tmp);
985 for (i=0; i<count; i++)
987 f.serial (_BorderTransition[i][CTile::diffuse]);
988 f.serial (_BorderTransition[i][CTile::additive]);
989 f.serial (_BorderTransition[i][CTile::alpha]);
991 // Reset the diffuse and alpha border if old version
992 if (streamver==0)
994 _BorderTransition[i][CTile::diffuse].reset();
995 _BorderTransition[i][CTile::alpha].reset();
999 // ***************************************************************************
1000 void CTileSet::addTile128 (int& indexInTileSet, CTileBank& bank)
1002 // Create a tile
1003 sint index=bank.createTile ();
1005 // Index of the new tile
1006 indexInTileSet=(int)_Tile128.size();
1008 // Add to the end of the list
1009 _Tile128.push_back (index);
1011 // ***************************************************************************
1012 void CTileSet::setBorder (CTile::TBitmap type, const CTileBorder& border)
1014 // This is our new border desc
1015 _Border128[type]=border;
1016 _Border256[type]=border;
1017 _Border256[type].doubleSize ();
1019 // ***************************************************************************
1020 void CTileSet::setTile128 (int indexInTileSet, const std::string& name, CTile::TBitmap type, CTileBank& bank)
1022 // Edit a tile
1023 CTile *tile=bank.getTile (_Tile128[indexInTileSet]);
1024 tile->setFileName (type, name);
1025 tile->setRotAlpha (0);
1027 // ***************************************************************************
1028 CTileSet::TError CTileSet::checkTile128 (CTile::TBitmap type, const CTileBorder& border, int& pixel, int& composante)
1030 // Self check
1031 if ((border.getWidth()!=128)||(border.getHeight()!=128))
1032 return sizeInvalide;
1033 if (!CTileBorder::compare (border, border, CTileBorder::top, CTileBorder::bottom, pixel, composante))
1034 return topBottomNotTheSame;
1035 if (!CTileBorder::compare (border, border, CTileBorder::left, CTileBorder::right, pixel, composante))
1036 return rightLeftNotTheSame;
1038 // Check
1039 if (_Border128[type].isSet())
1041 // Other check
1042 if (!CTileBorder::compare (border, _Border128[type], CTileBorder::top, CTileBorder::top, pixel, composante))
1043 return topInterfaceProblem;
1044 if (!CTileBorder::compare (border, _Border128[type], CTileBorder::bottom, CTileBorder::bottom, pixel, composante))
1045 return bottomInterfaceProblem;
1046 if (!CTileBorder::compare (border, _Border128[type], CTileBorder::left, CTileBorder::left, pixel, composante))
1047 return leftInterfaceProblem;
1048 if (!CTileBorder::compare (border, _Border128[type], CTileBorder::right, CTileBorder::right, pixel, composante))
1049 return rightInterfaceProblem;
1051 else
1053 return addFirstA128128;
1056 return ok;
1058 // ***************************************************************************
1059 void CTileSet::addTile256 (int& indexInTileSet, CTileBank& bank)
1061 // Create a tile
1062 sint index=bank.createTile ();
1064 // Index of the new tile
1065 indexInTileSet=(int)_Tile256.size();
1067 // Add to the end of the list
1068 _Tile256.push_back (index);
1070 // ***************************************************************************
1071 CTileSet::TError CTileSet::checkTile256 (CTile::TBitmap type, const CTileBorder& border, int& pixel, int& composante)
1073 // Self check
1074 if ((border.getWidth()!=256)||(border.getHeight()!=256))
1075 return sizeInvalide;
1076 if (!CTileBorder::compare (border, border, CTileBorder::top, CTileBorder::bottom, pixel, composante))
1077 return topBottomNotTheSame;
1078 if (!CTileBorder::compare (border, border, CTileBorder::left, CTileBorder::right, pixel, composante))
1079 return rightLeftNotTheSame;
1081 // Check if prb
1082 if ((!_Border256[type].isSet())&&(_Border128[type].isSet()))
1084 _Border256[type]=_Border128[type];
1085 _Border256[type].doubleSize ();
1088 // Check
1089 if (_Border256[type].isSet())
1092 // Other check
1093 if (!CTileBorder::compare (border, _Border256[type], CTileBorder::top, CTileBorder::top, pixel, composante))
1094 return topInterfaceProblem;
1095 if (!CTileBorder::compare (border, _Border256[type], CTileBorder::bottom, CTileBorder::bottom, pixel, composante))
1096 return bottomInterfaceProblem;
1097 if (!CTileBorder::compare (border, _Border256[type], CTileBorder::left, CTileBorder::left, pixel, composante))
1098 return leftInterfaceProblem;
1099 if (!CTileBorder::compare (border, _Border256[type], CTileBorder::right, CTileBorder::right, pixel, composante))
1100 return rightInterfaceProblem;
1102 else
1104 return addFirstA128128;
1107 return ok;
1109 // ***************************************************************************
1110 void CTileSet::setTile256 (int indexInTileSet, const std::string& name, CTile::TBitmap type, CTileBank& bank)
1112 // Edit a tile
1113 CTile *tile=bank.getTile (_Tile256[indexInTileSet]);
1114 tile->setFileName (type, name);
1115 tile->setRotAlpha (0);
1117 // ***************************************************************************
1118 void CTileSet::setTileTransition (TTransition transition, const std::string& name, CTile::TBitmap type, CTileBank& bank,
1119 const CTileBorder& border)
1121 // Check is not an alpha channel
1122 nlassert (type!=CTile::alpha); // use setTileTransitionAlpha
1124 // Create a tile
1125 _BorderTransition[transition][type]=border;
1127 // Set the tile file name
1128 CTile *tile=bank.getTile (_TileTransition[transition]._Tile);
1129 tile->setFileName (type, name);
1131 // ***************************************************************************
1132 void CTileSet::setTileTransitionAlpha (TTransition transition, const std::string& name, CTileBank& bank,
1133 const CTileBorder& border, uint8 rot)
1135 // Check some args
1136 nlassert (rot<4);
1138 // Create a tile
1139 _BorderTransition[transition][CTile::alpha]=border;
1141 // Set the tile file name
1142 CTile *tile=bank.getTile (_TileTransition[transition]._Tile);
1143 tile->setFileName (CTile::alpha, name);
1144 tile->setRotAlpha (rot);
1146 // ***************************************************************************
1147 CTileSet::TError CTileSet::checkTileTransition (TTransition transition, CTile::TBitmap type, const CTileBorder& border, int& indexError,
1148 int& pixel, int& composante)
1150 nlassert (transition>=0);
1151 nlassert (transition<count);
1153 // Check
1154 indexError=-1;
1156 // Top
1157 indexError=getExistingTransitionTile ((TFlagBorder)_TransitionFlags[transition][top], dontcare, dontcare, dontcare, transition, type);
1158 if (indexError!=-1)
1160 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::top, CTileBorder::top, pixel, composante))
1161 return topInterfaceProblem;
1163 indexError=getExistingTransitionTile (dontcare, (TFlagBorder)_TransitionFlags[transition][top], dontcare, dontcare, transition, type);
1164 if (indexError!=-1)
1166 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::top, CTileBorder::bottom, pixel, composante))
1167 return topInterfaceProblem;
1169 indexError=-1;
1170 if (_TransitionFlags[transition][top]==_1111)
1172 if (!CTileBorder::allAlphaSet (border, CTileBorder::top, pixel, composante))
1173 return topInterfaceProblem;
1176 // Bottom
1177 indexError=getExistingTransitionTile (dontcare, (TFlagBorder)_TransitionFlags[transition][bottom], dontcare, dontcare, transition, type);
1178 if (indexError!=-1)
1180 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::bottom, CTileBorder::bottom, pixel, composante))
1181 return bottomInterfaceProblem;
1183 indexError=getExistingTransitionTile ((TFlagBorder)_TransitionFlags[transition][bottom], dontcare, dontcare, dontcare, transition, type);
1184 if (indexError!=-1)
1186 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::bottom, CTileBorder::top, pixel, composante))
1187 return bottomInterfaceProblem;
1189 indexError=-1;
1190 if (_TransitionFlags[transition][bottom]==_1111)
1192 if (!CTileBorder::allAlphaSet (border, CTileBorder::bottom, pixel, composante))
1193 return bottomInterfaceProblem;
1196 // Left
1197 indexError=getExistingTransitionTile (dontcare, dontcare, (TFlagBorder)_TransitionFlags[transition][left], dontcare, transition, type);
1198 if (indexError!=-1)
1200 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::left, CTileBorder::left, pixel, composante))
1201 return leftInterfaceProblem;
1203 indexError=getExistingTransitionTile (dontcare, dontcare, dontcare, (TFlagBorder)_TransitionFlags[transition][left], transition, type);
1204 if (indexError!=-1)
1206 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::left, CTileBorder::right, pixel, composante))
1207 return leftInterfaceProblem;
1209 indexError=-1;
1210 if (_TransitionFlags[transition][left]==_1111)
1212 if (!CTileBorder::allAlphaSet (border, CTileBorder::left, pixel, composante))
1213 return leftInterfaceProblem;
1216 // Right
1217 indexError=getExistingTransitionTile (dontcare, dontcare, dontcare, (TFlagBorder)_TransitionFlags[transition][right], transition, type);
1218 if (indexError!=-1)
1220 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::right, CTileBorder::right, pixel, composante))
1221 return rightInterfaceProblem;
1223 indexError=getExistingTransitionTile (dontcare, dontcare, (TFlagBorder)_TransitionFlags[transition][right], dontcare, transition, type);
1224 if (indexError!=-1)
1226 if (!CTileBorder::compare (border, _BorderTransition[indexError][type], CTileBorder::right, CTileBorder::left, pixel, composante))
1227 return rightInterfaceProblem;
1229 indexError=-1;
1230 if (_TransitionFlags[transition][right]==_1111)
1232 if (!CTileBorder::allAlphaSet (border, CTileBorder::right, pixel, composante))
1233 return rightInterfaceProblem;
1235 return ok;
1237 // ***************************************************************************
1238 void CTileSet::removeTile128 (int indexInTileSet, CTileBank& bank)
1240 // Check args
1241 nlassert (indexInTileSet>=0);
1242 nlassert (indexInTileSet<(sint)_Tile128.size());
1244 // Old index
1245 int index=_Tile128[indexInTileSet];
1247 // Erase
1248 _Tile128.erase (_Tile128.begin()+indexInTileSet);
1249 bank.freeTile (index);
1251 // Erase border if it is the last texture
1252 deleteBordersIfLast (bank, CTile::diffuse);
1253 deleteBordersIfLast (bank, CTile::additive);
1254 deleteBordersIfLast (bank, CTile::alpha);
1256 // ***************************************************************************
1257 void CTileSet::removeTile256 (int indexInTileSet, CTileBank& bank)
1259 // Check args
1260 nlassert (indexInTileSet>=0);
1261 nlassert (indexInTileSet<(sint)_Tile256.size());
1263 // Old index
1264 int index=_Tile256[indexInTileSet];
1266 // Erase
1267 _Tile256.erase (_Tile256.begin()+indexInTileSet);
1268 bank.freeTile (index);
1270 // Erase border if it is the last texture
1271 deleteBordersIfLast (bank, CTile::diffuse);
1272 deleteBordersIfLast (bank, CTile::additive);
1273 deleteBordersIfLast (bank, CTile::alpha);
1275 // ***************************************************************************
1276 CTileSet::TTransition CTileSet::getTransitionTile (TFlagBorder _top, TFlagBorder _bottom, TFlagBorder _left, TFlagBorder _right)
1278 for (int n=first; n<count; n++)
1280 if (((_top==dontcare)||(_top==(TFlagBorder)_TransitionFlags[n][top]))&&
1281 ((_bottom==dontcare)||(_bottom==(TFlagBorder)_TransitionFlags[n][bottom]))&&
1282 ((_left==dontcare)||(_left==(TFlagBorder)_TransitionFlags[n][left]))&&
1283 ((_right==dontcare)||(_right==(TFlagBorder)_TransitionFlags[n][right])))
1285 return (TTransition)n;
1288 return notfound;
1290 // ***************************************************************************
1291 CTileSet::TTransition CTileSet::getExistingTransitionTile (TFlagBorder _top, TFlagBorder _bottom, TFlagBorder _left, TFlagBorder _right, int reject, CTile::TBitmap type)
1293 for (int n=first; n<count; n++)
1295 if ((n!=reject)&&
1296 (_BorderTransition[n][type].isSet ())&&
1297 ((_top==dontcare)||(_top==(TFlagBorder)_TransitionFlags[n][top]))&&
1298 ((_bottom==dontcare)||(_bottom==(TFlagBorder)_TransitionFlags[n][bottom]))&&
1299 ((_left==dontcare)||(_left==(TFlagBorder)_TransitionFlags[n][left]))&&
1300 ((_right==dontcare)||(_right==(TFlagBorder)_TransitionFlags[n][right])))
1302 return (TTransition)n;
1305 return notfound;
1307 // ***************************************************************************
1308 void CTileSet::addChild (const std::string& name)
1310 _ChildName.insert (name);
1312 // ***************************************************************************
1313 void CTileSet::removeChild (const std::string& name)
1315 _ChildName.erase (name);
1317 // ***************************************************************************
1318 CTileSet::TTransition CTileSet::getComplementaryTransition (TTransition transition)
1320 nlassert ((transition>=first)&&(transition<=last));
1321 TTransition trans=getTransitionTile (getComplementaryBorder (_TransitionFlags[transition][top]),
1322 getComplementaryBorder (_TransitionFlags[transition][bottom]),
1323 getComplementaryBorder (_TransitionFlags[transition][left]),
1324 getComplementaryBorder (_TransitionFlags[transition][right]));
1326 nlassert (trans!=notfound);
1328 return trans;
1330 // ***************************************************************************
1331 CTileSet::TFlagBorder CTileSet::getComplementaryBorder (TFlagBorder border)
1333 switch (border)
1335 case _0000:
1336 return _1111;
1337 case _0001:
1338 return _1110;
1339 case _0111:
1340 return _1000;
1341 case _1000:
1342 return _0111;
1343 case _1110:
1344 return _0001;
1345 case _1111:
1346 return _0000;
1347 default:
1348 nlassert (0); // no
1350 return _0000;
1352 // ***************************************************************************
1353 CTileSet::TFlagBorder CTileSet::getInvertBorder (TFlagBorder border)
1355 switch (border)
1357 case _0000:
1358 return _0000;
1359 case _0001:
1360 return _1000;
1361 case _0111:
1362 return _1110;
1363 case _1000:
1364 return _0001;
1365 case _1110:
1366 return _0111;
1367 case _1111:
1368 return _1111;
1369 default:
1370 nlassert (0); // no
1372 return _0000;
1374 // ***************************************************************************
1375 CTileSet::TFlagBorder CTileSet::getOrientedBorder (TBorder where, TFlagBorder border)
1377 switch (where)
1379 case left:
1380 case bottom:
1381 return border;
1382 case top:
1383 case right:
1384 return getInvertBorder (border);
1385 default:
1386 nlassert (0); // no
1388 return _0000;
1390 // ***************************************************************************
1391 CTileSet::TTransition CTileSet::rotateTransition (TTransition transition)
1393 return getTransitionTile (
1394 getOrientedBorder (top, getOrientedBorder (right, _TransitionFlags[transition][right])), // top
1395 getOrientedBorder (bottom, getOrientedBorder (left, _TransitionFlags[transition][left])), // bottom
1396 getOrientedBorder (left, getOrientedBorder (top, _TransitionFlags[transition][top])), // left
1397 getOrientedBorder (right, getOrientedBorder (bottom, _TransitionFlags[transition][bottom])) // right
1400 // ***************************************************************************
1401 void CTileSet::clearTile128 (int indexInTileSet, CTile::TBitmap type, CTileBank& bank)
1403 int nTile=_Tile128[indexInTileSet];
1404 bank.getTile (nTile)->clearTile(type);
1406 // Erase border if it is the last texture
1407 deleteBordersIfLast (bank, type);
1409 // ***************************************************************************
1410 void CTileSet::clearTile256 (int indexInTileSet, CTile::TBitmap type, CTileBank& bank)
1412 int nTile=_Tile256[indexInTileSet];
1413 bank.getTile (nTile)->clearTile(type);
1415 // Erase border if it is the last texture
1416 deleteBordersIfLast (bank, type);
1418 // ***************************************************************************
1419 void CTileSet::clearTransition (TTransition transition, CTile::TBitmap type, CTileBank& bank)
1421 int nTile=_TileTransition[transition]._Tile;
1422 if (nTile!=-1)
1423 bank.getTile (nTile)->clearTile(type);
1424 _BorderTransition[transition][type].reset();
1426 // Erase border if it is the last texture
1427 deleteBordersIfLast (bank, type);
1429 // ***************************************************************************
1430 // Delete 128 and 256 borders if no more valid texture file name for each bitmap type.
1431 void CTileSet::deleteBordersIfLast (const CTileBank& bank, CTile::TBitmap type)
1433 // delete is true
1434 bool bDelete=true;
1436 // iterator..
1437 std::vector<sint32>::iterator ite=_Tile128.begin();
1439 // Check all the 128x128 tiles
1440 while (ite!=_Tile128.end())
1442 // If the file name is valid
1443 if (!bank.getTile (*ite)->getRelativeFileName(type).empty())
1445 // Don't delete,
1446 bDelete=false;
1447 break;
1449 ite++;
1451 // If break, not empty, return
1452 if (ite!=_Tile128.end())
1453 return;
1455 // Check all the 256x256 tiles
1456 ite=_Tile256.begin();
1457 while (ite!=_Tile256.end())
1459 // If the file name is valid
1460 if (!bank.getTile (*ite)->getRelativeFileName(type).empty())
1462 // Don't delete,
1463 bDelete=false;
1464 break;
1466 ite++;
1468 // If break, not empty, return
1469 if (ite!=_Tile256.end())
1470 return;
1473 // Check all the transitions tiles
1474 sint trans;
1475 for (trans=0; trans<count; trans++)
1477 // Get the tile associed with the transition
1478 int nTile=_TileTransition[trans]._Tile;
1480 // If it is not NULL..
1481 if (nTile!=-1)
1483 // If the file name is valid
1484 if (!bank.getTile (nTile)->getRelativeFileName(type).empty())
1486 // Don't delete,
1487 bDelete=false;
1488 break;
1492 if (trans!=count)
1493 return;
1495 // Ok, erase borders because no tile use it anymore
1496 _Border128[type].reset();
1497 _Border256[type].reset();
1499 // ***************************************************************************
1500 void CTileSet::clearDisplacement (TDisplacement displacement, CTileBank& bank)
1502 // checks
1503 nlassert (displacement>=FirstDisplace);
1504 nlassert (displacement<=LastDisplace);
1506 // Backup the id
1507 int id=_DisplacementBitmap[displacement];
1509 // Clear map id
1510 _DisplacementBitmap[displacement]=0;
1512 // Tell the bank we remove it
1513 bank.removeDisplacementMap (id);
1515 // ***************************************************************************
1516 void CTileSet::setDisplacement (TDisplacement displacement, const std::string& fileName, CTileBank& bank)
1518 // checks
1519 nlassert (displacement>=FirstDisplace);
1520 nlassert (displacement<=LastDisplace);
1522 // Clear it
1523 bank.removeDisplacementMap (_DisplacementBitmap[displacement]);
1525 // Get displacement map
1526 _DisplacementBitmap[displacement]=bank.getDisplacementMap (fileName);
1528 // ***************************************************************************
1529 void CTileSet::cleanUnusedData ()
1531 _Name.clear();
1532 _ChildName.clear();
1533 _Border128[0].reset ();
1534 _Border128[1].reset ();
1535 _Border256[0].reset ();
1536 _Border256[1].reset ();
1537 for (uint i=0; i<count; i++)
1538 for (uint j=0; j<CTile::bitmapCount; j++)
1539 _BorderTransition[i][j].reset();
1543 // ***************************************************************************
1544 void CTileSet::setTileVegetableDescFileName (const std::string &fileName)
1546 _TileVegetableDescFileName= fileName;
1548 // ***************************************************************************
1549 const std::string& CTileSet::getTileVegetableDescFileName () const
1551 return _TileVegetableDescFileName;
1553 // ***************************************************************************
1554 void CTileSet::setTileVegetableDesc (const CTileVegetableDesc &tvd)
1556 _TileVegetableDesc= tvd;
1559 // ***************************************************************************
1560 CTileVegetableDesc &CTileSet::getTileVegetableDesc()
1562 return _TileVegetableDesc;
1565 // ***************************************************************************
1566 const CTileVegetableDesc &CTileSet::getTileVegetableDesc() const
1568 return _TileVegetableDesc;
1571 // ***************************************************************************
1572 void CTileSet::loadTileVegetableDesc()
1574 if(!_TileVegetableDescFileName.empty())
1578 string fname= CPath::lookup(_TileVegetableDescFileName);
1579 CIFile f(fname);
1580 // load the TileVegetableDesc
1581 f.serial(_TileVegetableDesc);
1583 catch(const Exception &e)
1585 nlinfo("Error loading TileVegetableDesc: %s", e.what());
1591 // ***************************************************************************
1592 // ***************************************************************************
1593 // CTileBorder.
1594 // ***************************************************************************
1595 // ***************************************************************************
1598 // ***************************************************************************
1599 const sint CTileBorder::_Version=0;
1600 // ***************************************************************************
1601 void CTileBorder::serial(NLMISC::IStream &f)
1603 (void)f.serialVersion(_Version);
1605 f.serial (_Set);
1606 f.serial (_Width);
1607 f.serial (_Height);
1608 f.serialCont (_Borders[top]);
1609 f.serialCont (_Borders[bottom]);
1610 f.serialCont (_Borders[left]);
1611 f.serialCont (_Borders[right]);
1613 // ***************************************************************************
1614 void CTileBorder::set (int width, int height, const std::vector<CBGRA>& array)
1616 // Check array size
1617 nlassert (width>0);
1618 nlassert (height>0);
1619 nlassert ((sint)array.size()==width*height);
1621 // Copy size
1622 _Width=width;
1623 _Height=height;
1625 // Last line
1626 int lastLine=(_Height-1)*width;
1627 int lastCol=(_Width-1);
1628 _Borders[top].resize (_Width);
1629 _Borders[bottom].resize (_Width);
1630 _Borders[left].resize (_Height);
1631 _Borders[right].resize (_Height);
1633 // Copy top/bottom border
1634 for (int w=0; w<_Width; w++)
1636 _Borders[top][w]=array[w];
1637 _Borders[bottom][w]=array[w+lastLine];
1640 // Copy left/right border
1641 for (int h=0; h<_Height; h++)
1643 _Borders[left][h]=array[h*_Width];
1644 _Borders[right][h]=array[h*_Width+lastCol];
1647 // Set
1648 _Set=true;
1650 // ***************************************************************************
1651 void CTileBorder::get (int &width, int &height, std::vector<CBGRA>& array) const
1653 // Go
1654 if (_Set)
1656 width=_Width;
1657 height=_Height;
1658 array.resize (0);
1659 array.resize (_Width*_Height);
1660 nlassert (_Borders[bottom].size()==(uint)_Width);
1661 nlassert (_Borders[top].size()==(uint)_Width);
1662 nlassert (_Borders[left].size()==(uint)_Height);
1663 nlassert (_Borders[right].size()==(uint)_Height);
1665 // Fill
1666 CBGRA black(0,0,0);
1667 for (int p=0; p<_Width*_Height; p++)
1669 array[p]=black;
1672 // Last line
1673 int lastLine=(_Height-1)*_Width;
1674 int lastCol=(_Width-1);
1676 // Copy top/bottom border
1677 for (int w=0; w<_Width; w++)
1679 array[w]=_Borders[top][w];
1680 array[w+lastLine]=_Borders[bottom][w];
1683 // Copy left/right border
1684 for (int h=0; h<_Height; h++)
1686 array[h*_Width]=_Borders[left][h];
1687 array[h*_Width+lastCol]=_Borders[right][h];
1690 else
1692 width=0;
1693 height=0;
1694 array.resize (0);
1697 // ***************************************************************************
1698 bool CTileBorder::compare (const CTileBorder& border1, const CTileBorder& border2, TBorder where1, TBorder where2, int& pixel, int& composante)
1700 // Check border is initialized
1701 nlassert (border1.isSet());
1702 nlassert (border2.isSet());
1704 if (border1._Borders[where1].size()!=border2._Borders[where2].size())
1705 return false;
1706 for (pixel=0; pixel<(int)border1._Borders[where1].size(); pixel++)
1708 if (border1._Borders[where1][pixel].R!=border2._Borders[where2][pixel].R)
1710 composante=0;
1711 return false;
1713 else if (border1._Borders[where1][pixel].G!=border2._Borders[where2][pixel].G)
1715 composante=1;
1716 return false;
1718 else if (border1._Borders[where1][pixel].B!=border2._Borders[where2][pixel].B)
1720 composante=2;
1721 return false;
1723 else if (border1._Borders[where1][pixel].A!=border2._Borders[where2][pixel].A)
1725 composante=3;
1726 return false;
1730 return true;
1732 // ***************************************************************************
1733 bool CTileBorder::allAlphaSet (const CTileBorder& border, TBorder where, int& pixel, int& composante)
1735 // Check border is initialized
1736 nlassert (border.isSet());
1738 // always Alpha
1739 composante=3;
1741 for (pixel=0; pixel<(int)border._Borders[where].size(); pixel++)
1743 if (border._Borders[where][pixel].A!=0xff)
1744 return false;
1747 return true;
1749 // ***************************************************************************
1750 bool CTileBorder::operator== (const CTileBorder& border) const
1752 return (_Width==border._Width) && (_Height==border._Height) && (_Borders==border._Borders);
1754 // ***************************************************************************
1755 void CTileBorder::operator= (const CTileBorder& border)
1757 _Set=border._Set;
1758 _Width=border._Width;
1759 _Height=border._Width;
1760 _Borders[top]=border._Borders[top];
1761 _Borders[bottom]=border._Borders[bottom];
1762 _Borders[left]=border._Borders[left];
1763 _Borders[right]=border._Borders[right];
1766 // ***************************************************************************
1767 void CTileBorder::doubleSize ()
1769 _Borders[top].resize (_Width*2);
1770 _Borders[bottom].resize (_Width*2);
1771 _Borders[left].resize (_Height*2);
1772 _Borders[right].resize (_Height*2);
1774 for (int w=0; w<_Width; w++)
1776 _Borders[top][w+_Width]=_Borders[top][w];
1777 _Borders[bottom][w+_Width]=_Borders[bottom][w];
1779 for (int h=0; h<_Height; h++)
1781 _Borders[left][h+_Height]=_Borders[left][h];
1782 _Borders[right][h+_Height]=_Borders[right][h];
1785 // ***************************************************************************
1786 void CTileBorder::rotate()
1788 // Copy the right
1789 std::vector<NLMISC::CBGRA> tmpLeft=_Borders[left];
1791 // Top inverted becomes left
1792 uint i, size;
1793 size=(uint)_Borders[top].size();
1794 _Borders[left].resize (size);
1796 // copy inverted
1797 for (i=0; i<size; i++)
1798 _Borders[left][i]=_Borders[top][size-i-1];
1800 // Right become top
1801 _Borders[top]=_Borders[right];
1803 // bottom inverted becomes right
1804 size=(uint)_Borders[bottom].size();
1805 _Borders[right].resize (size);
1807 // copy inverted
1808 for (i=0; i<size; i++)
1809 _Borders[right][i]=_Borders[bottom][size-i-1];
1811 // Left become bottom
1812 _Borders[bottom]=tmpLeft;
1814 // Invert size
1815 sint32 tmpSize=_Width;
1816 _Width=_Height;
1817 _Height=tmpSize;
1820 // ***************************************************************************
1821 // ***************************************************************************
1822 // CTileSetTransition.
1823 // ***************************************************************************
1824 // ***************************************************************************
1827 // ***************************************************************************
1828 const sint CTileSetTransition::_Version=1;
1829 // ***************************************************************************
1830 void CTileSetTransition::serial(NLMISC::IStream &f)
1832 sint streamver = f.serialVersion(_Version);
1834 switch (streamver)
1836 case 0:
1838 bool doomy;
1839 f.serial (_Tile);
1840 f.serial (doomy); // skip the old argu
1842 break;
1843 case 1:
1844 f.serial (_Tile);
1845 break;
1848 // ***************************************************************************
1851 // ***************************************************************************
1852 // ***************************************************************************
1853 // CTileNoise.
1854 // ***************************************************************************
1855 // ***************************************************************************
1858 // ***************************************************************************
1859 CTileNoise::CTileNoise ()
1861 // Not loaded
1862 _TileNoiseMap=NULL;
1864 // ***************************************************************************
1865 CTileNoise::CTileNoise (const CTileNoise &src)
1867 // Default ctor
1868 _TileNoiseMap=NULL;
1870 // Copy
1871 *this=src;
1873 // ***************************************************************************
1874 CTileNoise::~CTileNoise ()
1876 if (_TileNoiseMap)
1878 delete _TileNoiseMap;
1879 _TileNoiseMap=NULL;
1882 // ***************************************************************************
1883 CTileNoise& CTileNoise::operator= (const CTileNoise &src)
1885 // Copy the filename
1886 _FileName=src._FileName;
1888 // Tile noise map ?
1889 if (src._TileNoiseMap)
1891 if (_TileNoiseMap==NULL)
1893 // Allocate it
1894 _TileNoiseMap=new CTileNoiseMap;
1897 // Copy the noise map
1898 *_TileNoiseMap=*src._TileNoiseMap;
1900 else
1902 // Erase the map
1903 if (_TileNoiseMap)
1905 delete _TileNoiseMap;
1906 _TileNoiseMap=NULL;
1909 return *this;
1911 // ***************************************************************************
1912 void CTileNoise::serial (NLMISC::IStream& f)
1914 // Version
1915 f.serialVersion (0);
1917 // Serial the file name
1918 f.serial (_FileName);
1920 // ***************************************************************************
1921 void CTileNoise::setEmpty ()
1923 // Reset it
1924 reset();
1925 _FileName="EmptyDisplacementMap";
1926 _TileNoiseMap=new CTileNoiseMap();
1927 memset (_TileNoiseMap->Pixels, 0, NL3D_TILE_NOISE_MAP_SIZE*NL3D_TILE_NOISE_MAP_SIZE);
1929 // ***************************************************************************
1930 void CTileNoise::reset()
1932 // Erase the map
1933 if (_TileNoiseMap)
1935 delete _TileNoiseMap;
1936 _TileNoiseMap=NULL;
1939 // Erase filename
1940 _FileName.clear();
1942 // ***************************************************************************
1944 } // NL3D