1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
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/>.
21 #include "browser_model.h"
25 using namespace NLMISC
;
27 extern CTileBank tileBankBrowser
;
28 static const char* comp
[]={"Red", "Green", "Blue", "Alpha", ""};
30 static bool loadPic(const string
&path
, std::vector
<NLMISC::CBGRA
> &tampon
, uint
&width
, uint
&height
)
35 if (file
.open(path
.c_str()))
37 NLMISC::CBitmap bitmap
;
39 width
= bitmap
.getWidth();
40 height
= bitmap
.getHeight();
41 tampon
.resize(width
* height
);
42 bitmap
.convertToType(NLMISC::CBitmap::RGBA
);
43 for (uint y
= 0; y
< height
; ++y
)
45 for (uint x
= 0; x
< width
; ++x
)
47 NLMISC::CRGBA c
= bitmap
.getPixelColor(x
, y
, 0);
48 c
.R
= (c
.R
* c
.A
) / 255;
49 c
.G
= (c
.G
* c
.A
) / 255;
50 c
.B
= (c
.B
* c
.A
) / 255;
51 tampon
[(y
* width
) + x
] = c
;
57 catch (const NLMISC::Exception
& ) { }
61 bool RemovePath (std::string
& path
, const char* absolutePathToRemplace
);
64 void rotateBuffer (std::vector
<NLMISC::CBGRA
> &Buffer
, uint
&Width
, uint
&Height
)
67 std::vector
<NLMISC::CBGRA
> copy
= Buffer
;
70 for (uint y
=0; y
<Width
; y
++)
74 for (uint x
=0; x
<Width
; x
++)
76 Buffer
[y
+(Width
-x
-1)*Height
]=copy
[x
+tmp
];
86 /////////////////////////////////////////////////////////////////////////////
87 // Load a Pic and apply Alpha & Rotation
88 int loadPixmapBuffer(const std::string
& path
, std::vector
<NLMISC::CBGRA
>& Buffer
, std::vector
<NLMISC::CBGRA
>* Alpha
, int rot
)
92 if (loadPic(path
, Buffer
, Width
, Height
))
97 rotateBuffer (Buffer
, Width
, Height
);
101 if ( (Alpha
) && (Alpha
->size()==Buffer
.size()) )
103 // Pre mul RGB componates by Alpha one
104 int nPixelCount
=(int)(Width
*Height
);
105 for (int p
=0; p
<nPixelCount
; p
++)
108 int alpha
=(*Alpha
)[p
].A
;
109 Buffer
[p
].R
=(uint8
)(((int)Buffer
[p
].R
*alpha
)>>8);
110 Buffer
[p
].G
=(uint8
)(((int)Buffer
[p
].G
*alpha
)>>8);
111 Buffer
[p
].B
=(uint8
)(((int)Buffer
[p
].B
*alpha
)>>8);
122 /////////////////////////////////////////////////////////////////////////////
126 TileInfo::TileInfo():tileType(UnSet
)
129 this->nightLoaded
= 0;
130 this->alphaLoaded
= 0;
135 TileInfo::TileInfo(int id
, TileType tileType
):id(id
), tileType(tileType
)
138 this->nightLoaded
= 0;
139 this->alphaLoaded
= 0;
142 void TileInfo::Init(int id
, TileType tileType
)
145 this->tileType
= tileType
;
147 this->nightLoaded
= 0;
148 this->alphaLoaded
= 0;
152 bool TileInfo::Load (int index
, std::vector
<NLMISC::CBGRA
>* Alpha
)
155 if (!loaded
&& !getRelativeFileName (Diffuse
, index
).empty())
157 path
= fixPath(tileBankBrowser
.getAbsPath() + getRelativeFileName (Diffuse
, index
));
161 if ( !loadPixmapBuffer( path
, Bits
, Alpha
, 0))
164 QMessageBox::information( NULL
, QObject::tr("Can't load Diffuse file"), QString( (path
.c_str()) ));
170 if (!nightLoaded
&& !getRelativeFileName (Additive
, index
).empty())
172 nightPath
= fixPath(tileBankBrowser
.getAbsPath() + getRelativeFileName (Additive
, index
));
173 if (!loadPixmapBuffer( nightPath
, nightBits
, Alpha
, 0))
176 QMessageBox::information( NULL
, QObject::tr("Can't load Additive file"), QString( nightPath
.c_str() ) );
181 if (!alphaLoaded
&& !getRelativeFileName (::Alpha
, index
).empty())
183 alphaPath
= fixPath(tileBankBrowser
.getAbsPath() + getRelativeFileName (::Alpha
, index
));
184 if (!loadPixmapBuffer( alphaPath
, alphaBits
, NULL
, tileBankBrowser
.getTile (index
)->getRotAlpha ()))
187 QMessageBox::information( NULL
, QObject::tr("Can't load Alpha file"), QString( alphaPath
.c_str() ) );
197 std::string
TileInfo::fixPath(const std::string
&path
) {
198 // Fix the Windows path issues for subpaths.
199 std::string
searchStr("\\");
200 std::string
replaceStr("/");
201 string::size_type pos
= 0;
202 std::string pathStr
= path
;
204 while( (pos
= pathStr
.find(searchStr
, pos
)) != std::string::npos
) {
205 pathStr
.replace(pos
, searchStr
.size(), replaceStr
);
211 void TileInfo::Delete ()
223 const std::string
TileInfo::getRelativeFileName (TileTexture texture
, int index
)
225 nlassert(this->tileType
!= UnSet
);
227 std::string currentPath
;
228 if (tileType
!= Displace
)
230 currentPath
= tileBankBrowser
.getTile(index
)->getRelativeFileName ((CTile::TBitmap
)texture
);
234 if (texture
== Diffuse
)
236 currentPath
= tileBankBrowser
.getDisplacementMap(index
);
238 //TODO titegus: remove MAGIC STRING "EmptyDisplacementMap" in Nel \tile_bank.cpp\void CTileNoise::setEmpty () or add an IsEmpty() method !!!!
239 if (currentPath
== "EmptyDisplacementMap")
254 // Add 48 transitions
256 for (i
=0; i
<CTileSet::count
; i
++)
258 TileInfo
info(i
, Transition
);
259 theListTransition
.push_back (info
);
262 // Add 16 displacements
263 for (i
=0; i
<CTileSet::CountDisplace
; i
++)
265 TileInfo
info(i
, Displace
);
266 theListDisplacement
.push_back (info
);
271 int TileList::addTile128 ()
275 tileBankBrowser
.getTileSet (_tileSet
)->addTile128 (index
, tileBankBrowser
);
276 nlassert (index
==(sint
)theList128
.size());
278 TileInfo
info(index
, _128x128
);
279 theList128
.push_back (info
);
284 int TileList::addTile256 ()
287 tileBankBrowser
.getTileSet (_tileSet
)->addTile256 (index
, tileBankBrowser
);
288 nlassert (index
==(sint
)theList256
.size());
290 TileInfo
info(index
, _256x256
);
291 theList256
.push_back (info
);
296 bool TileList::setTile128 (int tile
, const std::string
& name
, NL3D::CTile::TBitmap type
)
298 // Remove the absolute path from the path name
299 std::string troncated
= name
;
300 if (RemovePath(troncated
, tileBankBrowser
.getAbsPath ().c_str()))
302 vector
<NLMISC::CBGRA
> tampon
;
305 if (!loadPic(tileBankBrowser
.getAbsPath ()+troncated
, tampon
, Width
, Height
))
307 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't load bitmap."), QString( ((tileBankBrowser
.getAbsPath ()+troncated
)+"\nContinue ?").c_str() ), QMessageBox::Yes
| QMessageBox::No
));
312 border
.set (Width
, Height
, tampon
);
314 CTileSet::TError error
;
317 if (type
== CTile::additive
)
320 error
=tileBankBrowser
.getTileSet(_tileSet
)->checkTile128 (type
, border
, pixel
, composante
);
322 if ((error
!=CTileSet::ok
)&&(error
!=CTileSet::addFirstA128128
))
324 QString pixelMessage
= QObject::tr("%1\nPixel: %2(%3).\nContinue ?").arg(CTileSet::getErrorMessage (error
)).arg(pixel
).arg(comp
[composante
]);
325 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't set Bitmap"), pixelMessage
, QMessageBox::Yes
| QMessageBox::No
) );
329 if (error
==CTileSet::addFirstA128128
)
330 tileBankBrowser
.getTileSet(_tileSet
)->setBorder (type
, border
);
332 tileBankBrowser
.getTileSet(_tileSet
)->setTile128 (tile
, troncated
, type
, tileBankBrowser
);
336 theList128
[tile
].loaded
=0;
338 case CTile::additive
:
339 theList128
[tile
].nightLoaded
=0;
342 theList128
[tile
].alphaLoaded
=0;
347 Reload(tile
, tile
+ 1, _128x128
);
353 // Error: bitmap not in the absolute path..
354 QString notInAbsolutePathMessage
= QObject::tr("The bitmap %1 is not in the absolute path %2.\nContinue ?").arg(name
.c_str()).arg(tileBankBrowser
.getAbsPath ().c_str());
355 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Load error"), notInAbsolutePathMessage
, QMessageBox::Yes
| QMessageBox::No
));
361 bool TileList::setTile256 (int tile
, const std::string
& name
, NL3D::CTile::TBitmap type
)
363 // Remove the absolute path from the path name
364 std::string troncated
=name
;
365 if (RemovePath (troncated
, tileBankBrowser
.getAbsPath ().c_str()))
367 vector
<NLMISC::CBGRA
> tampon
;
370 if (!loadPic(tileBankBrowser
.getAbsPath ()+troncated
, tampon
, Width
, Height
))
372 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't load bitmap."), QString( ((tileBankBrowser
.getAbsPath ()+troncated
)+"\nContinue ?").c_str() ), QMessageBox::Yes
| QMessageBox::No
) );
378 border
.set (Width
, Height
, tampon
);
380 CTileSet::TError error
;
384 if (type
== CTile::additive
)
387 error
=tileBankBrowser
.getTileSet(_tileSet
)->checkTile256 (type
, border
, pixel
, composante
);
388 if ((error
!=CTileSet::ok
))
390 QString pixelMessage
= QObject::tr("%1\nPixel: %2(%3).\nContinue ?").arg(CTileSet::getErrorMessage (error
)).arg(pixel
).arg(comp
[composante
]);
391 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't set Bitmap"), pixelMessage
, QMessageBox::Yes
| QMessageBox::No
) );
395 tileBankBrowser
.getTileSet(_tileSet
)->setTile256 (tile
, troncated
, type
, tileBankBrowser
);
399 theList256
[tile
].loaded
=0;
401 case CTile::additive
:
402 theList256
[tile
].nightLoaded
=0;
405 theList256
[tile
].alphaLoaded
=0;
410 Reload(tile
, tile
+ 1, _256x256
);
416 // Error: bitmap not in the absolute path..
417 QString notInAbsolutePathMessage
= QObject::tr("The bitmap %1 is not in the absolute path %2.\nContinue ?").arg(name
.c_str()).arg(tileBankBrowser
.getAbsPath ().c_str());
418 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Load error"), notInAbsolutePathMessage
, QMessageBox::Yes
| QMessageBox::No
));
424 bool TileList::setTileTransition (int tile
, const std::string
& name
, NL3D::CTile::TBitmap type
)
426 // Remove the absolute path from the path name
427 std::string troncated
=name
;
428 if (RemovePath (troncated
, tileBankBrowser
.getAbsPath ().c_str()))
430 // No alpha, use setTileTransitionAlpha
431 nlassert (CTile::alpha
!=type
);
433 vector
<NLMISC::CBGRA
> tampon
;
436 if (!loadPic(tileBankBrowser
.getAbsPath ()+troncated
, tampon
, Width
, Height
))
438 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't load bitmap."), QString( ((tileBankBrowser
.getAbsPath ()+troncated
)+"\nContinue ?").c_str() ), QMessageBox::Yes
| QMessageBox::No
) );
443 border
.set (Width
, Height
, tampon
);
445 CTileSet::TError error
;
448 if (type
== CTile::additive
)
451 error
=tileBankBrowser
.getTileSet(_tileSet
)->checkTile128 (type
, border
, pixel
, composante
);
452 if ((error
!=CTileSet::ok
)&&(error
!=CTileSet::addFirstA128128
))
454 QString pixelMessage
= QObject::tr("%1\nPixel: %2(%3).\nContinue ?").arg(CTileSet::getErrorMessage (error
)).arg(pixel
).arg(comp
[composante
]);
455 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't set Bitmap"), pixelMessage
, QMessageBox::Yes
| QMessageBox::No
) );
459 if (error
==CTileSet::addFirstA128128
)
460 tileBankBrowser
.getTileSet(_tileSet
)->setBorder (type
, border
);
461 tileBankBrowser
.getTileSet(_tileSet
)->setTileTransition ((CTileSet::TTransition
)tile
, troncated
, type
, tileBankBrowser
, border
);
465 theListTransition
[tile
].loaded
=0;
467 case CTile::additive
:
468 theListTransition
[tile
].nightLoaded
=0;
471 theListTransition
[tile
].alphaLoaded
=0;
476 Reload(tile
, tile
+ 1, Transition
);
482 // Error: bitmap not in the absolute path..
483 QString notInAbsolutePathMessage
= QObject::tr("The bitmap %1 is not in the absolute path %2.\nContinue ?").arg(name
.c_str()).arg(tileBankBrowser
.getAbsPath ().c_str());
484 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Load error"), notInAbsolutePathMessage
, QMessageBox::Yes
| QMessageBox::No
) );
490 bool TileList::setDisplacement (int tile
, const std::string
& name
, NL3D::CTile::TBitmap type
)
492 // Remove the absolute path from the path name
493 std::string troncated
=name
;
494 if (RemovePath (troncated
, tileBankBrowser
.getAbsPath ().c_str()))
497 vector
<NLMISC::CBGRA
> tampon
;
500 if (!loadPic(tileBankBrowser
.getAbsPath ()+troncated
, tampon
, Width
, Height
))
502 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't load bitmap"), QString( ((tileBankBrowser
.getAbsPath ()+troncated
)+"\nContinue ?").c_str() ), QMessageBox::Yes
| QMessageBox::No
) );
507 if ( (Width
!=32) || (Height
!=32) )
510 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't set Bitmap"), QString( (troncated
+"\nInvalid size: displacement map must be 32x32 8 bits.\nContinue ?").c_str()), QMessageBox::Yes
| QMessageBox::No
) );
514 // change the file name of the displacement map
515 tileBankBrowser
.getTileSet(_tileSet
)->setDisplacement ((CTileSet::TDisplacement
)tile
, troncated
, tileBankBrowser
);
518 theListDisplacement
[tile
].loaded
=0;
519 Reload(tile
, tile
+ 1, Displace
);
526 // Error: bitmap not in the absolute path..
527 QString notInAbsolutePathMessage
= QObject::tr("The bitmap %1 is not in the absolute path %2.\nContinue ?").arg(name
.c_str()).arg(tileBankBrowser
.getAbsPath ().c_str());
528 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Load error"), notInAbsolutePathMessage
, QMessageBox::Yes
| QMessageBox::No
) );
534 bool TileList::setTileTransitionAlpha (int tile
, const std::string
& name
, int rot
)
536 // Remove the absolute path from the path name
537 std::string troncated
=name
;
538 if (RemovePath (troncated
, tileBankBrowser
.getAbsPath ().c_str()))
540 vector
<NLMISC::CBGRA
> tampon
;
543 if (!loadPic(tileBankBrowser
.getAbsPath ()+troncated
, tampon
, Width
, Height
))
545 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't load bitmap"), QString( ((tileBankBrowser
.getAbsPath ()+troncated
)+"\nContinue ?").c_str() ), QMessageBox::Yes
| QMessageBox::No
) );
550 border
.set (Width
, Height
, tampon
);
560 CTileSet::TError error
;
564 if (((error
=tileBankBrowser
.getTileSet(_tileSet
)->checkTileTransition ((CTileSet::TTransition
)tile
, CTile::alpha
, border
, indexError
,
565 pixel
, composante
))!=CTileSet::ok
))
567 QString pixelMessage
;
568 if ((error
==CTileSet::topInterfaceProblem
)||(error
==CTileSet::bottomInterfaceProblem
)||(error
==CTileSet::leftInterfaceProblem
)
569 ||(error
==CTileSet::rightInterfaceProblem
)||(error
==CTileSet::topBottomNotTheSame
)||(error
==CTileSet::rightLeftNotTheSame
)
570 ||(error
==CTileSet::topInterfaceProblem
))
573 pixelMessage
= QObject::tr("%1.\nIncompatible with tile nb %4.\nPixel: %2(%3).\nContinue ?").arg(CTileSet::getErrorMessage (error
)).arg(pixel
).arg(comp
[composante
]).arg(indexError
);
575 pixelMessage
= QObject::tr("%1.\nIncompatible with the 128x128 tile.\nPixel: %2(%3).\nContinue ?").arg(CTileSet::getErrorMessage (error
)).arg(pixel
).arg(comp
[composante
]);
579 pixelMessage
= QObject::tr("%1.\nIncompatible filled tile.\nContinue ?").arg(CTileSet::getErrorMessage (error
));
581 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Can't set Bitmap"), pixelMessage
, QMessageBox::Yes
| QMessageBox::No
) );
585 tileBankBrowser
.getTileSet(_tileSet
)->setTileTransitionAlpha ((CTileSet::TTransition
)tile
, troncated
, tileBankBrowser
, border
, rot
);
586 theListTransition
[tile
].alphaLoaded
=0;
587 theListTransition
[tile
].Load (tileBankBrowser
.getTileSet(_tileSet
)->getTransition(tile
)->getTile(), NULL
);
593 // Error: bitmap not in the absolute path..
594 QString notInAbsolutePathMessage
= QObject::tr("The bitmap %1 is not in the absolute path %2.\nContinue ?").arg(name
.c_str()).arg(tileBankBrowser
.getAbsPath ().c_str());
595 return ( QMessageBox::Yes
== QMessageBox::question( NULL
, QObject::tr("Load error"), notInAbsolutePathMessage
, QMessageBox::Yes
| QMessageBox::No
) );
601 void TileList::removeTile128 (int index
)
603 tileBankBrowser
.getTileSet (_tileSet
)->removeTile128 (index
, tileBankBrowser
);
604 theList
[0].erase (theList
[0].begin()+index
);
605 for (int i
=0; i
<(sint
)theList
[0].size(); i
++)
607 theList
[0][i
].setId(i
);
611 void TileList::removeTile256 (int index
)
613 tileBankBrowser
.getTileSet (_tileSet
)->removeTile256 (index
, tileBankBrowser
);
614 theList
[1].erase (theList
[1].begin()+index
);
615 for (int i
=0; i
<(sint
)theList
[1].size(); i
++)
617 theList
[1][i
].setId(i
);
621 void TileList::clearTile128 (int index
, CTile::TBitmap bitmap
)
626 theList128
[index
].loaded
=0;
627 theList128
[index
].Bits
.resize(0);
629 case CTile::additive
:
630 theList128
[index
].nightLoaded
=0;
631 theList128
[index
].nightBits
.resize(0);
639 tileBankBrowser
.getTileSet (_tileSet
)->clearTile128 (index
, bitmap
, tileBankBrowser
);
642 void TileList::clearTile256 (int index
, CTile::TBitmap bitmap
)
647 theList256
[index
].loaded
=0;
648 theList256
[index
].Bits
.resize(0);
650 case CTile::additive
:
651 theList256
[index
].nightLoaded
=0;
652 theList256
[index
].nightBits
.resize(0);
660 tileBankBrowser
.getTileSet (_tileSet
)->clearTile256 (index
, bitmap
, tileBankBrowser
);
663 void TileList::clearTransition (int index
, CTile::TBitmap bitmap
)
668 theListTransition
[index
].loaded
=0;
669 theListTransition
[index
].Bits
.resize(0);
671 case CTile::additive
:
672 theListTransition
[index
].nightLoaded
=0;
673 theListTransition
[index
].nightBits
.resize(0);
676 theListTransition
[index
].alphaLoaded
=0;
677 theListTransition
[index
].alphaBits
.resize(0);
682 tileBankBrowser
.getTileSet (_tileSet
)->clearTransition ((CTileSet::TTransition
)index
, bitmap
, tileBankBrowser
);
685 void TileList::clearDisplacement (int index
, CTile::TBitmap bitmap
)
690 theListDisplacement
[index
].loaded
=0;
691 theListDisplacement
[index
].Bits
.resize(0);
693 case CTile::additive
:
703 tileBankBrowser
.getTileSet (_tileSet
)->clearDisplacement ((CTileSet::TDisplacement
)index
, tileBankBrowser
);
706 tilelist::iterator
TileList::GetFirst(int n
)
708 return theList
[n
].begin();
711 tilelist::iterator
TileList::GetLast(int n
)
713 return theList
[n
].end();
716 tilelist::iterator
TileList::Get(int i
, int n
)
718 return theList
[n
].begin()+i
;
722 int TileList::GetSize(int n
)
724 return (int)theList
[n
].size();
728 void TileList::Reload(int first
, int last
, TileType n
) //recharge en memoire une tranche de tiles
730 for (int i
=first
; i
<last
; i
++)
736 theList
[n
][i
].Load (tileBankBrowser
.getTileSet(_tileSet
)->getTile128 (i
), NULL
);
741 theList
[n
][i
].Load (tileBankBrowser
.getTileSet(_tileSet
)->getTile256 (i
), NULL
);
746 int index
=tileBankBrowser
.getTileSet(_tileSet
)->getTransition (i
)->getTile();
748 theList
[n
][i
].Load (index
, &theListTransition
[i
].alphaBits
);
753 int index
=tileBankBrowser
.getTileSet(_tileSet
)->getDisplacementTile ((CTileSet::TDisplacement
)i
);
755 theList
[n
][i
].Load (index
, NULL
);