18 #include <QDomDocument>
19 #include <QTextStream>
20 #include <QMessageBox>
21 #include <QProgressDialog>
22 #include <QApplication>
26 #include "layerbitmap.h"
27 #include "layervector.h"
28 #include "layersound.h"
29 #include "layercamera.h"
34 #include "bitmapimage.h"
35 #include "fileformat.h"
41 Object::Object( QObject* parent ) : QObject( parent )
48 while ( !mLayers.empty() )
50 delete mLayers.takeLast();
54 if(!filePath().isEmpty())
75 QDomElement Object::saveXML( QDomDocument& doc )
77 qDebug() << dataDir();
78 qDebug() << workingDir();
79 qDebug() << mainXMLFile();
81 QDomElement tag = doc.createElement(
"object" );
83 for (
int i = 0; i < getLayerCount(); i++ )
85 Layer* layer = getLayer( i );
86 QDomElement layerTag = layer->createDomElement( doc );
87 tag.appendChild( layerTag );
92 bool Object::loadXML( QDomElement docElem, ProgressCallback progress )
94 if ( docElem.isNull() )
100 const QString dataDirPath = mDataDirPath;
102 int allNodesCount = docElem.childNodes().count();
103 int processedNodeCount = 0;
105 for ( QDomNode node = docElem.firstChild(); !node.isNull(); node = node.nextSibling() )
107 processedNodeCount += 1;
108 progress( (
float)processedNodeCount / allNodesCount );
110 QDomElement element = node.toElement();
111 if ( element.tagName() ==
"layer" )
113 if ( element.attribute(
"type" ).toInt() == Layer::BITMAP )
117 getLayer( layerNumber )->loadDomElement( element, dataDirPath );
119 else if ( element.attribute(
"type" ).toInt() == Layer::VECTOR )
123 getLayer( layerNumber )->loadDomElement( element, dataDirPath );
125 else if ( element.attribute(
"type" ).toInt() == Layer::SOUND )
129 getLayer( layerNumber )->loadDomElement( element, dataDirPath );
131 else if ( element.attribute(
"type" ).toInt() == Layer::CAMERA )
135 getLayer( layerNumber )->loadDomElement( element, dataDirPath );
145 mLayers.append( layerBitmap );
147 layerBitmap->addNewEmptyKeyAt( 1 );
155 mLayers.append( layerVector );
157 layerVector->addNewEmptyKeyAt( 1 );
165 mLayers.append( layerSound );
175 mLayers.append( layerCamera );
177 layerCamera->addNewEmptyKeyAt( 1 );
182 void Object::createWorkingDir()
184 QString strFolderName;
185 if ( mFilePath.isEmpty() )
187 strFolderName =
"Default";
191 QFileInfo fileInfo( mFilePath );
192 strFolderName = fileInfo.completeBaseName();
194 QString strWorkingDir = QDir::tempPath()
197 + PFF_TMP_DECOMPRESS_EXT
200 QDir dir( QDir::tempPath() );
201 dir.mkpath( strWorkingDir );
203 mWorkingDirPath = strWorkingDir;
205 QDir dataDir( strWorkingDir + PFF_DATA_DIR );
206 dataDir.mkpath(
"." );
208 mDataDirPath = dataDir.absolutePath();
211 void Object::deleteWorkingDir()
const
213 QDir dataDir(mWorkingDirPath);
214 dataDir.removeRecursively();
217 int Object::getMaxLayerID()
220 for (
Layer* iLayer : mLayers )
222 if ( iLayer->id() > maxId )
224 maxId = iLayer->id();
230 int Object::getUniqueLayerID()
232 return 1 + getMaxLayerID();
235 Layer* Object::getLayer(
int i )
const
237 if ( i < 0 || i >= getLayerCount() )
242 return mLayers.at( i );
245 Layer* Object::findLayerByName( QString strName, Layer::LAYER_TYPE type )
const
247 bool bCheckType = ( type != Layer::UNDEFINED );
249 for (
Layer* layer : mLayers )
251 bool bTypeMatch = ( bCheckType ) ? ( type == layer->type() ):
true ;
253 if ( layer->name() == strName && bTypeMatch )
261 bool Object::moveLayer(
int i,
int j )
263 if ( i< 0 || i >= mLayers.size() )
268 if ( j < 0 || j >= mLayers.size() )
275 Layer* tmp = mLayers.at( i );
276 mLayers[ i ] = mLayers.at( j );
282 void Object::deleteLayer(
int i )
284 if ( i > -1 && i < mLayers.size() )
286 disconnect( mLayers[ i ], 0, 0, 0 );
287 delete mLayers.takeAt( i );
291 void Object::deleteLayer(
Layer* layer )
293 auto it = std::find( mLayers.begin(), mLayers.end(), layer );
295 if ( it != mLayers.end() )
297 disconnect( layer, 0, 0, 0 );
306 if ( i > -1 && i < mPalette.size() )
308 result = mPalette.at( i );
313 void Object::addColour( QColor colour )
315 addColour(
ColourRef( colour,
"Colour " + QString::number( mPalette.size() ) ) );
318 bool Object::removeColour(
int index )
320 for (
int i = 0; i < getLayerCount(); i++ )
322 Layer* layer = getLayer( i );
323 if ( layer->type() == Layer::VECTOR )
326 if ( layerVector->usesColour( index ) )
return false;
329 for (
int i = 0; i < getLayerCount(); i++ )
331 Layer* layer = getLayer( i );
332 if ( layer->type() == Layer::VECTOR )
335 layerVector->removeColour( index );
338 mPalette.removeAt( index );
343 void Object::renameColour(
int i, QString text )
345 mPalette[ i ].name = text;
348 bool Object::savePalette( QString filePath )
350 return exportPalette( filePath +
"/palette.xml" );
353 bool Object::exportPalette( QString filePath )
355 QFile* file =
new QFile( filePath );
356 if ( !file->open( QFile::WriteOnly | QFile::Text ) )
361 QTextStream out( file );
363 QDomDocument doc(
"PencilPalette" );
364 QDomElement root = doc.createElement(
"palette" );
365 doc.appendChild( root );
366 for (
int i = 0; i < mPalette.size(); i++ )
368 QDomElement tag = doc.createElement(
"Colour" );
369 tag.setAttribute(
"name", mPalette.at( i ).name );
370 tag.setAttribute(
"red", mPalette.at( i ).colour.red() );
371 tag.setAttribute(
"green", mPalette.at( i ).colour.green() );
372 tag.setAttribute(
"blue", mPalette.at( i ).colour.blue() );
373 root.appendChild( tag );
380 doc.save( out, IndentSize );
384 bool Object::importPalette( QString filePath )
386 QFile* file =
new QFile( filePath );
387 if ( !file->open( QFile::ReadOnly ) )
394 doc.setContent( file );
397 QDomElement docElem = doc.documentElement();
398 QDomNode tag = docElem.firstChild();
399 while ( !tag.isNull() )
401 QDomElement e = tag.toElement();
404 QString name = e.attribute(
"name" );
405 int r = e.attribute(
"red" ).toInt();
406 int g = e.attribute(
"green" ).toInt();
407 int b = e.attribute(
"blue" ).toInt();
408 mPalette.append(
ColourRef( QColor( r, g, b ), name ) );
411 tag = tag.nextSibling();
417 void Object::loadDefaultPalette()
420 addColour(
ColourRef( QColor( Qt::black ), QString( tr(
"Black" ) ) ) );
421 addColour(
ColourRef( QColor( Qt::red ), QString( tr(
"Red" ) ) ) );
422 addColour(
ColourRef( QColor( Qt::darkRed ), QString( tr(
"Dark Red" ) ) ) );
423 addColour(
ColourRef( QColor( 255, 128, 0 ), QString( tr(
"Orange" ) ) ) );
424 addColour(
ColourRef( QColor( 128, 64, 0 ), QString( tr(
"Dark Orange" ) ) ) );
425 addColour(
ColourRef( QColor( Qt::yellow ), QString( tr(
"Yellow" ) ) ) );
426 addColour(
ColourRef( QColor( Qt::darkYellow ), QString( tr(
"Dark Yellow" ) ) ) );
427 addColour(
ColourRef( QColor( Qt::green ), QString( tr(
"Green" ) ) ) );
428 addColour(
ColourRef( QColor( Qt::darkGreen ), QString( tr(
"Dark Green" ) ) ) );
429 addColour(
ColourRef( QColor( Qt::cyan ), QString( tr(
"Cyan" ) ) ) );
430 addColour(
ColourRef( QColor( Qt::darkCyan ), QString( tr(
"Dark Cyan" ) ) ) );
431 addColour(
ColourRef( QColor( Qt::blue ), QString( tr(
"Blue" ) ) ) );
432 addColour(
ColourRef( QColor( Qt::darkBlue ), QString( tr(
"Dark Blue" ) ) ) );
433 addColour(
ColourRef( QColor( 255, 255, 255 ), QString( tr(
"White" ) ) ) );
434 addColour(
ColourRef( QColor( 220, 220, 229 ), QString( tr(
"Very Light Grey" ) ) ) );
435 addColour(
ColourRef( QColor( Qt::lightGray ), QString( tr(
"Light Grey" ) ) ) );
436 addColour(
ColourRef( QColor( Qt::gray ), QString( tr(
"Grey" ) ) ) );
437 addColour(
ColourRef( QColor( Qt::darkGray ), QString( tr(
"Dark Grey" ) ) ) );
438 addColour(
ColourRef( QColor( 255, 227, 187 ), QString( tr(
"Light Skin" ) ) ) );
439 addColour(
ColourRef( QColor( 221, 196, 161 ), QString( tr(
"Light Skin - shade" ) ) ) );
440 addColour(
ColourRef( QColor( 255, 214, 156 ), QString( tr(
"Skin" ) ) ) );
441 addColour(
ColourRef( QColor( 207, 174, 127 ), QString( tr(
"Skin - shade" ) ) ) );
442 addColour(
ColourRef( QColor( 255, 198, 116 ), QString( tr(
"Dark Skin" ) ) ) );
443 addColour(
ColourRef( QColor( 227, 177, 105 ), QString( tr(
"Dark Skin - shade" ) ) ) );
446 void Object::paintImage( QPainter& painter,
int frameNumber,
448 bool antialiasing )
const
450 painter.setRenderHint( QPainter::Antialiasing,
true );
451 painter.setRenderHint( QPainter::SmoothPixmapTransform,
true );
454 painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
459 painter.setPen( Qt::NoPen );
460 painter.setBrush( Qt::white );
461 painter.setWorldMatrixEnabled(
false );
462 painter.drawRect( QRect( 0, 0, painter.device()->width(), painter.device()->height() ) );
463 painter.setWorldMatrixEnabled(
true );
466 for (
int i = 0; i < getLayerCount(); i++ )
468 Layer* layer = getLayer( i );
469 if ( layer->mVisible )
471 painter.setOpacity( 1.0 );
474 if ( layer->type() == Layer::BITMAP )
477 layerBitmap->getLastBitmapImageAtFrame( frameNumber, 0 )->paintImage( painter );
480 if ( layer->type() == Layer::VECTOR )
483 layerVector->getLastVectorImageAtFrame( frameNumber, 0 )->paintImage( painter,
492 QString Object::copyFileToDataFolder( QString strFilePath )
494 if ( !QFile::exists( strFilePath ) )
496 qDebug() <<
"[Object] sound file doesn't exist: " << strFilePath;
500 QString sNewFileName =
"sound_";
501 sNewFileName += QDateTime::currentDateTime().toString(
"yyyyMMdd_HHmmss_zzz.");
502 sNewFileName += QFileInfo( strFilePath ).suffix();
504 QString srcFile = strFilePath;
505 QString destFile = QDir( mDataDirPath ).filePath( sNewFileName );
507 if ( QFile::exists( destFile ) )
509 QFile::remove( destFile );
512 bool bCopyOK = QFile::copy( srcFile, destFile );
515 qDebug() <<
"[Object] couldn't copy sound file to data folder: " << strFilePath;
522 bool Object::exportFrames(
int frameStart,
int frameEnd,
524 QSize exportSize, QString filePath,
529 QProgressDialog* progress = NULL,
530 int progressMax = 50 )
532 QSettings settings( PENCIL2D, PENCIL2D );
534 QString extension =
"";
535 QString formatStr = format;
536 if ( formatStr ==
"PNG" || formatStr ==
"png" )
541 if ( formatStr ==
"JPG" || formatStr ==
"jpg" || formatStr ==
"JPEG" || formatStr ==
"jpeg" )
545 transparency =
false;
547 if ( filePath.endsWith( extension, Qt::CaseInsensitive ) )
549 filePath.chop( extension.size() );
552 qDebug() <<
"Exporting frames from "
553 << frameStart <<
"to"
555 <<
"at size " << exportSize;
557 for (
int currentFrame = frameStart; currentFrame <= frameEnd; currentFrame++ )
559 if ( progress != NULL )
561 int totalFramesToExport = ( frameEnd - frameStart ) + 1;
562 if ( totalFramesToExport != 0 )
564 progress->setValue( ( currentFrame - frameStart + 1 )*progressMax / totalFramesToExport );
565 QApplication::processEvents();
568 if(progress->wasCanceled())
574 QImage imageToExport( exportSize, QImage::Format_ARGB32_Premultiplied );
575 QColor bgColor = Qt::white;
579 imageToExport.fill(bgColor);
581 QPainter painter( &imageToExport );
584 if(currentLayer !=
nullptr)
586 viewRect = ( (
LayerCamera* )currentLayer )->getViewRect();
592 viewRect = QRect( QPoint(-320,-240), QSize(640,480) );
595 QTransform mapView = RectMapTransform( viewRect, QRectF( QPointF( 0, 0 ), exportSize ) );
597 painter.setWorldTransform( mapView );
599 paintImage( painter, currentFrame,
false, antialiasing );
601 QString frameNumberString = QString::number( currentFrame );
602 while ( frameNumberString.length() < 4 )
604 frameNumberString.prepend(
"0" );
606 imageToExport.save( filePath + frameNumberString + extension, format, quality );
613 void convertNFrames(
int fps,
int exportFps,
int* frameRepeat,
int* frameReminder,
int* framePutEvery,
int* frameSkipEvery )
616 *frameRepeat = exportFps / fps;
617 *frameReminder = exportFps % fps;
620 if ( *frameReminder == 0 )
622 *framePutEvery = 0; *frameSkipEvery = 0;
624 else if ( *frameReminder > ( fps - *frameReminder ) )
626 *frameSkipEvery = fps / ( fps - *frameReminder ); *framePutEvery = 0;
630 *framePutEvery = fps / *frameReminder; *frameSkipEvery = 0;
632 qDebug() <<
"-->convertedNFrames";
636 bool Object::exportX(
int frameStart,
int frameEnd, QTransform view, QSize exportSize, QString filePath,
bool antialiasing )
638 QSettings settings( PENCIL2D, PENCIL2D );
642 for (
int j = frameStart; j <= frameEnd; j = j + 15 )
644 QImage xImg( QSize( 2300, 3400 ), QImage::Format_ARGB32_Premultiplied );
645 QPainter xPainter( &xImg );
646 xPainter.fillRect( 0, 0, 2300, 3400, Qt::white );
648 for (
int i = j; i < 15 + page * 15 && i <= frameEnd; i++ )
650 QRect source = QRect( QPoint( 0, 0 ), exportSize );
651 QRect target = QRect( QPoint( ( y % 3 ) * 800 + 30, ( y / 3 ) * 680 + 50 - page * 3400 ), QSize( 640, 480 ) );
652 QTransform thumbView = view * RectMapTransform( source, target );
653 xPainter.setWorldTransform( thumbView );
654 xPainter.setClipRegion( thumbView.inverted().map( QRegion( target ) ) );
655 paintImage( xPainter, i,
false, antialiasing );
656 xPainter.resetMatrix();
657 xPainter.setClipping(
false );
658 xPainter.setPen( Qt::black );
659 xPainter.setFont( QFont(
"helvetica", 50 ) );
660 xPainter.drawRect( target );
661 xPainter.drawText( QPoint( ( y % 3 ) * 800 + 35, ( y / 3 ) * 680 + 65 - page * 3400 ), QString::number( i ) );
665 if ( filePath.endsWith(
".jpg", Qt::CaseInsensitive ) )
669 if ( !xImg.save( filePath + QString::number( page ) +
".jpg",
"JPG", 60 ) ) {
678 bool Object::exportIm(
int frameStart,
int frameEnd, QTransform view, QSize exportSize, QString filePath, QString format,
bool antialiasing,
bool transparency )
680 Q_UNUSED( frameEnd );
681 QImage imageToExport( exportSize, QImage::Format_ARGB32_Premultiplied );
683 QColor bgColor = Qt::white;
687 imageToExport.fill(bgColor);
689 QPainter painter( &imageToExport );
690 painter.setWorldTransform( view );
691 paintImage( painter, frameStart,
false, antialiasing );
693 return imageToExport.save( filePath, format.toStdString().c_str() );
696 int Object::getLayerCount()
const
698 return mLayers.size();
703 Q_ASSERT( mEditorState !=
nullptr );
704 return mEditorState.get();
709 Q_ASSERT( d !=
nullptr );
710 mEditorState.reset( d );
713 void Object::setLayerUpdated(
int layerId)
715 emit layerChanged(layerId);