1 // Ryzom Core Studio - Tile Editor plugin
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "tile_bank.h"
19 #include "nel/3d/tile_bank.h"
25 bool pixmapToCBGRA( QPixmap
&pixmap
, std::vector
< NLMISC::CBGRA
>& pixels
)
27 QImage img
= pixmap
.toImage();
28 if( img
.format() != QImage::Format_ARGB32
)
29 img
= img
.convertToFormat( QImage::Format_ARGB32
);
31 if( img
.format() != QImage::Format_ARGB32
)
34 int c
= img
.width() * img
.height();
36 const unsigned char *data
= img
.bits();
37 const unsigned int *idata
= reinterpret_cast< const unsigned int* >( data
);
45 bgra
.A
= ( idata
[ i
] & 0xFF000000 ) >> 24;
46 bgra
.R
= ( idata
[ i
] & 0x00FF0000 ) >> 16;
47 bgra
.G
= ( idata
[ i
] & 0x0000FF00 ) >> 8;
48 bgra
.B
= ( idata
[ i
] & 0x000000FF );
49 pixels
.push_back( bgra
);
58 NL3D::CTile::TBitmap
channelToTBitmap( TileConstants::TTileChannel channel
)
60 return NL3D::CTile::TBitmap( int( channel
) );
66 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 bool checkSize( TileConstants::TNodeTileType type
, TileConstants::TTileChannel channel
, int w
, int h
)
79 case TileConstants::Tile128
:
83 case TileConstants::Tile256
:
87 case TileConstants::TileTransition
:
89 if( channel
== TileConstants::TileAlpha
)
97 case TileConstants::TileDisplacement
:
108 NL3D::CTileSet::TError
checkTile( NL3D::CTileSet
*set
, int tile
, TileConstants::TNodeTileType type
, NL3D::CTileBorder
&border
, NL3D::CTile::TBitmap bitmap
, QString
&msg
)
110 NL3D::CTileSet::TError error
;
112 if( bitmap
== NL3D::CTile::additive
)
113 return NL3D::CTileSet::ok
;
115 if( type
== TileConstants::TileDisplacement
)
116 return NL3D::CTileSet::ok
;
124 case TileConstants::Tile128
:
125 error
= set
->checkTile128( bitmap
, border
, pixel
, component
);
128 case TileConstants::Tile256
:
129 error
= set
->checkTile256( bitmap
, border
, pixel
, component
);
132 case TileConstants::TileTransition
:
134 if( bitmap
!= NL3D::CTile::alpha
)
135 error
= set
->checkTile128( bitmap
, border
, pixel
, component
);
137 error
= set
->checkTileTransition( NL3D::CTileSet::TTransition( tile
), bitmap
, border
, idx
, pixel
, component
);
143 if( ( error
!= NL3D::CTileSet::ok
) && ( error
!= NL3D::CTileSet::addFirstA128128
) )
145 static const char* comp
[]={"Red", "Green", "Blue", "Alpha", ""};
147 msg
= NL3D::CTileSet::getErrorMessage( error
);
149 msg
+= " pixel %1 component %2";
150 msg
= msg
.arg( pixel
);
151 msg
= msg
.arg( comp
[ component
] );
157 void setTile( NL3D::CTileSet
*set
, int tile
, int rotation
, const QString
&name
, NL3D::CTile::TBitmap bm
, TileConstants::TNodeTileType type
, NL3D::CTileBorder
&border
)
161 case TileConstants::Tile128
:
162 set
->setTile128( tile
, name
.toUtf8().constData(), bm
, m_bank
);
165 case TileConstants::Tile256
:
166 set
->setTile256( tile
, name
.toUtf8().constData(), bm
, m_bank
);
169 case TileConstants::TileTransition
:
170 if( bm
!= NL3D::CTile::alpha
)
171 set
->setTileTransition( NL3D::CTileSet::TTransition( tile
), name
.toUtf8().constData(), bm
, m_bank
, border
);
173 set
->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile
), name
.toUtf8().constData(), m_bank
, border
, rotation
);
176 case TileConstants::TileDisplacement
:
177 set
->setDisplacement( NL3D::CTileSet::TDisplacement( tile
), name
.toUtf8().constData(), m_bank
);
183 void buildBorder( QPixmap
&pm
, NL3D::CTileBorder
&border
)
185 std::vector
< NLMISC::CBGRA
> pixels
;
186 pixmapToCBGRA( pm
, pixels
);
187 border
.set( pm
.width(), pm
.height(), pixels
);
190 NL3D::CTileBank m_bank
;
195 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
199 m_pvt
= new TileBankPvt();
204 TileBank::~TileBank()
209 void TileBank::addTileSet( const QString
&name
)
211 m_pvt
->m_bank
.addTileSet( name
.toUtf8().constData() );
212 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( 0 );
215 void TileBank::removeTileSet( int idx
)
217 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( idx
);
221 int c
= m_pvt
->m_bank
.getLandCount();
222 for( int i
= 0; i
< c
; i
++ )
224 NL3D::CTileLand
*land
= m_pvt
->m_bank
.getLand( i
);
225 land
->removeTileSet( set
->getName() );
228 m_pvt
->m_bank
.removeTileSet( idx
);
231 void TileBank::renameTileSet( int idx
, const QString
&newName
)
233 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( idx
);
237 std::string oldName
= set
->getName();
238 set
->setName( newName
.toUtf8().constData() );
240 int c
= m_pvt
->m_bank
.getLandCount();
241 for( int i
= 0; i
< c
; i
++ )
243 NL3D::CTileLand
*land
= m_pvt
->m_bank
.getLand( i
);
244 land
->removeTileSet( oldName
);
245 land
->addTileSet( newName
.toUtf8().constData() );
250 void TileBank::getTileSets( QStringList
&l
)
252 int c
= m_pvt
->m_bank
.getTileSetCount();
253 for( int i
= 0; i
< c
; i
++ )
255 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( i
);
256 l
.push_back( set
->getName().c_str() );
260 void TileBank::addLand( const QString
&name
)
262 m_pvt
->m_bank
.addLand( name
.toUtf8().constData() );
265 void TileBank::removeLand( int idx
)
267 m_pvt
->m_bank
.removeLand( idx
);
270 void TileBank::getLands( QStringList
&l
)
274 int c
= m_pvt
->m_bank
.getLandCount();
275 for( int i
= 0; i
< c
; i
++ )
277 NL3D::CTileLand
*land
= m_pvt
->m_bank
.getLand( i
);
278 l
.push_back( land
->getName().c_str() );
282 void TileBank::setLandSets( int idx
, const QStringList
&l
)
284 NL3D::CTileLand
*land
= m_pvt
->m_bank
.getLand( idx
);
287 QStringListIterator
itr( l
);
288 while( itr
.hasNext() )
290 land
->addTileSet( itr
.next().toUtf8().constData() );
294 void TileBank::getLandSets( int idx
, QStringList
&l
)
296 NL3D::CTileLand
*land
= m_pvt
->m_bank
.getLand( idx
);
302 std::set
< std::string
> sets
= land
->getTileSets();
303 std::set
< std::string
>::const_iterator itr
= sets
.begin();
304 while( itr
!= sets
.end() )
306 l
.push_back( itr
->c_str() );
311 bool TileBank::addTile( int setIdx
, const QString
&name
, const QVariant
&pixmap
, TileConstants::TTileChannel channel
, TileConstants::TNodeTileType type
)
315 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( setIdx
);
320 case TileConstants::Tile128
: set
->addTile128( tile
, m_pvt
->m_bank
); break;
321 case TileConstants::Tile256
: set
->addTile256( tile
, m_pvt
->m_bank
); break;
324 bool b
= setTile( setIdx
, tile
, name
, pixmap
, channel
, type
);
328 // There was an error, roll back
331 case TileConstants::Tile128
: set
->removeTile128( tile
, m_pvt
->m_bank
); break;
332 case TileConstants::Tile256
: set
->removeTile256( tile
, m_pvt
->m_bank
); break;
338 void TileBank::removeTile( int ts
, int type
, int tile
)
340 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( ts
);
344 case TileConstants::Tile128
: set
->removeTile128( tile
, m_pvt
->m_bank
); break;
345 case TileConstants::Tile256
: set
->removeTile256( tile
, m_pvt
->m_bank
); break;
349 bool TileBank::setTile( int tileset
, int tile
, const QString
&name
, const QVariant
&pixmap
, TileConstants::TTileChannel channel
, TileConstants::TNodeTileType type
)
353 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileset
);
357 QPixmap pm
= pixmap
.value
< QPixmap
>();
361 m_lastError
= "Failed to load image.";
365 if( pm
.width() != pm
.height() )
368 m_lastError
= "Image isn't square.";
372 if( !m_pvt
->checkSize( type
, channel
, pm
.width(), pm
.height() ) )
375 m_lastError
= "Invalid image size.";
379 NL3D::CTileBorder border
;
380 m_pvt
->buildBorder( pm
, border
);
382 if( ( type
== TileConstants::TileTransition
) && ( channel
== TileConstants::TileAlpha
) )
384 int rotBits
= m_rotation
;
393 NL3D::CTileSet::TError error
= m_pvt
->checkTile( set
, tile
, type
, border
, channelToTBitmap( channel
), msg
);
395 // Tile checks out fine, set it
396 if( ( error
== NL3D::CTileSet::ok
) || ( error
== NL3D::CTileSet::addFirstA128128
) )
398 if( error
== NL3D::CTileSet::addFirstA128128
)
399 set
->setBorder( channelToTBitmap( channel
), border
);
401 m_pvt
->setTile( set
, tile
, m_rotation
, name
, channelToTBitmap( channel
), type
, border
);
411 void TileBank::replaceImage( int ts
, int type
, int tile
, TileConstants::TTileChannel channel
, const QString
&name
, const QVariant
&pixmap
)
413 setTile( ts
, tile
, name
, pixmap
, channel
, TileConstants::TNodeTileType( type
) );
416 void TileBank::clearImage( int ts
, int type
, int tile
, TileConstants::TTileChannel channel
)
418 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( ts
);
422 NL3D::CTile::TBitmap bm
= channelToTBitmap( channel
);
426 case TileConstants::Tile128
:
427 set
->clearTile128( tile
, bm
, m_pvt
->m_bank
);
430 case TileConstants::Tile256
:
431 set
->clearTile256( tile
, bm
, m_pvt
->m_bank
);
434 case TileConstants::TileTransition
:
435 set
->clearTransition( NL3D::CTileSet::TTransition( tile
), bm
, m_pvt
->m_bank
);
438 case TileConstants::TileDisplacement
:
439 set
->clearDisplacement( NL3D::CTileSet::TDisplacement( tile
), m_pvt
->m_bank
);
445 int TileBank::getTileCount( int tileSet
, TileConstants::TNodeTileType type
)
447 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
455 case TileConstants::Tile128
:
456 c
= set
->getNumTile128();
459 case TileConstants::Tile256
:
460 c
= set
->getNumTile256();
463 case TileConstants::TileTransition
:
464 c
= NL3D::CTileSet::count
;
467 case TileConstants::TileDisplacement
:
468 c
= NL3D::CTileSet::CountDisplace
;
475 int TileBank::getRealTileId( int tileSet
, TileConstants::TNodeTileType type
, int tileIdInSet
)
477 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
485 case TileConstants::Tile128
:
486 tile
= set
->getTile128( tileIdInSet
);
489 case TileConstants::Tile256
:
490 tile
= set
->getTile256( tileIdInSet
);
493 case TileConstants::TileTransition
:
494 tile
= set
->getTransition( tileIdInSet
)->getTile();
497 case TileConstants::TileDisplacement
:
498 tile
= set
->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet
) );
505 void TileBank::getTileImages( int tileSet
, TileConstants::TNodeTileType type
, int tileId
, TileImages
&images
)
507 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
513 case TileConstants::Tile128
:
514 case TileConstants::Tile256
:
515 case TileConstants::TileTransition
:
517 NL3D::CTile
*t
= m_pvt
->m_bank
.getTile( tileId
);
521 images
.diffuse
= t
->getFileName( channelToTBitmap( TileConstants::TileDiffuse
) ).c_str();
522 images
.additive
= t
->getFileName( channelToTBitmap( TileConstants::TileAdditive
) ).c_str();
523 images
.alpha
= t
->getFileName( channelToTBitmap( TileConstants::TileAlpha
) ).c_str();
527 case TileConstants::TileDisplacement
:
529 images
.diffuse
= m_pvt
->m_bank
.getDisplacementMap( tileId
);
536 void TileBank::getTileImages( int tileSet
, TileConstants::TNodeTileType type
, QList
< TileImages
> &l
)
540 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
544 int c
= getTileCount( tileSet
, type
);
548 for( int i
= 0; i
< c
; i
++ )
552 int id
= getRealTileId( tileSet
, type
, i
);
555 l
.push_back( images
);
559 getTileImages( tileSet
, type
, id
, images
);
561 l
.push_back( images
);
566 void TileBank::setVegetation( int tileSet
, const QString
&vegetation
)
568 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
572 set
->setTileVegetableDescFileName( vegetation
.toUtf8().constData() );
576 QString
TileBank::getVegetation( int tileSet
) const
578 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
582 return set
->getTileVegetableDescFileName().c_str();
585 void TileBank::setOriented( int tileSet
, bool b
)
587 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
591 set
->setOriented( b
);
594 bool TileBank::getOriented( int tileSet
) const
596 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
600 return set
->getOriented();
604 void TileBank::setSurfaceData( int tileSet
, unsigned long data
)
606 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
610 set
->SurfaceData
= data
;
613 unsigned long TileBank::getSurfaceData( int tileSet
) const
615 NL3D::CTileSet
*set
= m_pvt
->m_bank
.getTileSet( tileSet
);
619 return set
->SurfaceData
;
622 void TileBank::setTexturePath( const QString
&path
)
624 m_pvt
->m_bank
.setAbsPath( path
.toUtf8().constData() );
627 QString
TileBank::getTexturePath() const
629 return m_pvt
->m_bank
.getAbsPath().c_str();
632 void TileBank::setRotation( int rotation
)
634 m_rotation
= rotation
;
637 void TileBank::serial( NLMISC::IStream
&f
)
639 m_pvt
->m_bank
.serial( f
);