Linux multi-monitor fullscreen support
[ryzomcore.git] / studio / src / plugins / tile_editor / tile_bank.cpp
blob8e3578eeb2805e7c40314f8ab107aa42e48165cf
1 // Ryzom Core Studio - Tile Editor plugin
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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"
21 #include <QPixmap>
23 namespace{
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 )
32 return false;
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 );
39 NLMISC::CBGRA bgra;
40 pixels.clear();
42 int i = 0;
43 while( i < c )
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 );
51 i++;
54 return true;
58 NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel )
60 return NL3D::CTile::TBitmap( int( channel ) );
66 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69 class TileBankPvt
71 public:
73 bool checkSize( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel, int w, int h )
75 int width = -1;
77 switch( type )
79 case TileConstants::Tile128:
80 width = 128;
81 break;
83 case TileConstants::Tile256:
84 width = 256;
85 break;
87 case TileConstants::TileTransition:
89 if( channel == TileConstants::TileAlpha )
90 width = 64;
91 else
92 width = 128;
95 break;
97 case TileConstants::TileDisplacement:
98 width = 32;
99 break;
102 if( width == w )
103 return true;
105 return false;
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;
118 int component;
119 int pixel;
120 int idx;
122 switch( type )
124 case TileConstants::Tile128:
125 error = set->checkTile128( bitmap, border, pixel, component );
126 break;
128 case TileConstants::Tile256:
129 error = set->checkTile256( bitmap, border, pixel, component );
130 break;
132 case TileConstants::TileTransition:
134 if( bitmap != NL3D::CTile::alpha )
135 error = set->checkTile128( bitmap, border, pixel, component );
136 else
137 error = set->checkTileTransition( NL3D::CTileSet::TTransition( tile ), bitmap, border, idx, pixel, component );
139 break;
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 );
148 msg += "\n";
149 msg += " pixel %1 component %2";
150 msg = msg.arg( pixel );
151 msg = msg.arg( comp[ component ] );
154 return error;
157 void setTile( NL3D::CTileSet *set, int tile, int rotation, const QString &name, NL3D::CTile::TBitmap bm, TileConstants::TNodeTileType type, NL3D::CTileBorder &border )
159 switch( type )
161 case TileConstants::Tile128:
162 set->setTile128( tile, name.toUtf8().constData(), bm, m_bank );
163 break;
165 case TileConstants::Tile256:
166 set->setTile256( tile, name.toUtf8().constData(), bm, m_bank );
167 break;
169 case TileConstants::TileTransition:
170 if( bm != NL3D::CTile::alpha )
171 set->setTileTransition( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), bm, m_bank, border );
172 else
173 set->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), m_bank, border, rotation );
174 break;
176 case TileConstants::TileDisplacement:
177 set->setDisplacement( NL3D::CTileSet::TDisplacement( tile ), name.toUtf8().constData(), m_bank );
178 break;
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 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
197 TileBank::TileBank()
199 m_pvt = new TileBankPvt();
200 resetError();
201 m_rotation = 0;
204 TileBank::~TileBank()
206 delete m_pvt;
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 );
218 if( set == NULL )
219 return;
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 );
234 if( set == NULL )
235 return;
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 )
272 l.clear();
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 );
285 land->clear();
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 );
297 if( land == NULL )
298 return;
300 l.clear();
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() );
307 ++itr;
311 bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type )
313 resetError();
315 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( setIdx );
317 int tile;
318 switch( type )
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 );
325 if( b )
326 return true;
328 // There was an error, roll back
329 switch( type )
331 case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break;
332 case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break;
335 return false;
338 void TileBank::removeTile( int ts, int type, int tile )
340 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts );
342 switch( type )
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 )
351 resetError();
353 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileset );
354 if( set == NULL )
355 return false;
357 QPixmap pm = pixmap.value< QPixmap >();
358 if( pm.isNull() )
360 m_hasError = true;
361 m_lastError = "Failed to load image.";
362 return false;
365 if( pm.width() != pm.height() )
367 m_hasError = true;
368 m_lastError = "Image isn't square.";
369 return false;
372 if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) )
374 m_hasError = true;
375 m_lastError = "Invalid image size.";
376 return false;
379 NL3D::CTileBorder border;
380 m_pvt->buildBorder( pm, border );
382 if( ( type == TileConstants::TileTransition ) && ( channel == TileConstants::TileAlpha ) )
384 int rotBits = m_rotation;
385 while( rotBits > 0 )
387 border.rotate();
388 rotBits--;
392 QString msg;
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 );
403 return true;
406 setError( msg );
408 return false;
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 );
420 int tileId;
422 NL3D::CTile::TBitmap bm = channelToTBitmap( channel );
424 switch( type )
426 case TileConstants::Tile128:
427 set->clearTile128( tile, bm, m_pvt->m_bank );
428 break;
430 case TileConstants::Tile256:
431 set->clearTile256( tile, bm, m_pvt->m_bank );
432 break;
434 case TileConstants::TileTransition:
435 set->clearTransition( NL3D::CTileSet::TTransition( tile ), bm, m_pvt->m_bank );
436 break;
438 case TileConstants::TileDisplacement:
439 set->clearDisplacement( NL3D::CTileSet::TDisplacement( tile ), m_pvt->m_bank );
440 break;
445 int TileBank::getTileCount( int tileSet, TileConstants::TNodeTileType type )
447 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
448 if( set == NULL )
449 return -1;
451 int c = 0;
453 switch( type )
455 case TileConstants::Tile128:
456 c = set->getNumTile128();
457 break;
459 case TileConstants::Tile256:
460 c = set->getNumTile256();
461 break;
463 case TileConstants::TileTransition:
464 c = NL3D::CTileSet::count;
465 break;
467 case TileConstants::TileDisplacement:
468 c = NL3D::CTileSet::CountDisplace;
469 break;
472 return c;
475 int TileBank::getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet )
477 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
478 if( set == NULL )
479 return -1;
481 int tile = -1;
483 switch( type )
485 case TileConstants::Tile128:
486 tile = set->getTile128( tileIdInSet );
487 break;
489 case TileConstants::Tile256:
490 tile = set->getTile256( tileIdInSet );
491 break;
493 case TileConstants::TileTransition:
494 tile = set->getTransition( tileIdInSet )->getTile();
495 break;
497 case TileConstants::TileDisplacement:
498 tile = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet ) );
499 break;
502 return tile;
505 void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images )
507 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
508 if( set == NULL )
509 return;
511 switch( type )
513 case TileConstants::Tile128:
514 case TileConstants::Tile256:
515 case TileConstants::TileTransition:
517 NL3D::CTile *t = m_pvt->m_bank.getTile( tileId );
518 if( t == NULL )
519 return;
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();
525 break;
527 case TileConstants::TileDisplacement:
529 images.diffuse = m_pvt->m_bank.getDisplacementMap( tileId );
531 break;
536 void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l )
538 l.clear();
540 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
541 if( set == NULL )
542 return;
544 int c = getTileCount( tileSet, type );
546 TileImages images;
548 for( int i = 0; i < c; i++ )
550 images.clear();
552 int id = getRealTileId( tileSet, type, i );
553 if( id < 0 )
555 l.push_back( images );
556 continue;
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 );
569 if( set == NULL )
570 return;
572 set->setTileVegetableDescFileName( vegetation.toUtf8().constData() );
576 QString TileBank::getVegetation( int tileSet ) const
578 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
579 if( set == NULL )
580 return "";
582 return set->getTileVegetableDescFileName().c_str();
585 void TileBank::setOriented( int tileSet, bool b )
587 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
588 if( set == NULL )
589 return;
591 set->setOriented( b );
594 bool TileBank::getOriented( int tileSet ) const
596 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
597 if( set == NULL )
598 return false;
600 return set->getOriented();
604 void TileBank::setSurfaceData( int tileSet, unsigned long data )
606 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
607 if( set == NULL )
608 return;
610 set->SurfaceData = data;
613 unsigned long TileBank::getSurfaceData( int tileSet ) const
615 NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet );
616 if( set == NULL )
617 return 0;
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 );