All Classes Namespaces Functions Variables Enumerations Properties Pages
layervector.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 */
17 #include "layervector.h"
18 
19 #include "vectorimage.h"
20 #include <QDir>
21 #include <QFile>
22 #include <QFileInfo>
23 
24 
25 LayerVector::LayerVector(Object* object) : Layer(object, Layer::VECTOR)
26 {
27  setName(tr("Vector Layer"));
28 }
29 
30 LayerVector::~LayerVector()
31 {
32 }
33 
34 bool LayerVector::usesColor(int colorIndex)
35 {
36  bool bUseColor = false;
37  foreachKeyFrame([&](KeyFrame* pKeyFrame)
38  {
39  auto pVecImage = static_cast<VectorImage*>(pKeyFrame);
40 
41  bUseColor = bUseColor || pVecImage->usesColor(colorIndex);
42  });
43 
44  return bUseColor;
45 }
46 
47 void LayerVector::removeColor(int colorIndex)
48 {
49  foreachKeyFrame([=](KeyFrame* pKeyFrame)
50  {
51  auto pVecImage = static_cast<VectorImage*>(pKeyFrame);
52  pVecImage->removeColor(colorIndex);
53  });
54 }
55 
56 void LayerVector::moveColor(int start, int end)
57 {
58  foreachKeyFrame( [=] (KeyFrame* pKeyFrame)
59  {
60  auto pVecImage = static_cast<VectorImage*>(pKeyFrame);
61  pVecImage->moveColor(start, end);
62  });
63 }
64 
65 void LayerVector::loadImageAtFrame(QString path, int frameNumber)
66 {
67  if (keyExists(frameNumber))
68  {
69  removeKeyFrame(frameNumber);
70  }
71  VectorImage* vecImg = new VectorImage;
72  vecImg->setPos(frameNumber);
73  vecImg->setObject(object());
74  vecImg->read(path);
75  addKeyFrame(frameNumber, vecImg);
76 }
77 
78 Status LayerVector::saveKeyFrameFile(KeyFrame* keyFrame, QString path)
79 {
80  QString theFileName = fileName(keyFrame);
81  QString strFilePath = QDir(path).filePath(theFileName);
82 
83  VectorImage* vecImage = static_cast<VectorImage*>(keyFrame);
84 
85  if (needSaveFrame(keyFrame, strFilePath) == false)
86  {
87  return Status::SAFE;
88  }
89 
90  Status st = vecImage->write(strFilePath, "VEC");
91  if (!st.ok())
92  {
93  vecImage->setFileName("");
94 
95  DebugDetails dd;
96  dd << __FUNCTION__;
97  dd << QString("KeyFrame.pos() = %1").arg(keyFrame->pos());
98  dd << QString("FilePath = ").append(strFilePath);
99  dd << "- VectorImage failed to write";
100  dd.collect(st.details());
101  return Status(Status::FAIL, dd);
102  }
103 
104  vecImage->setFileName(strFilePath);
105  vecImage->setModified(false);
106  return Status::OK;
107 }
108 
109 KeyFrame* LayerVector::createKeyFrame(int position, Object* obj)
110 {
111  VectorImage* v = new VectorImage;
112  v->setPos(position);
113  v->setObject(obj);
114  return v;
115 }
116 
117 QString LayerVector::fileName(KeyFrame* key) const
118 {
119  return QString::asprintf("%03d.%03d.vec", id(), key->pos());
120 }
121 
122 bool LayerVector::needSaveFrame(KeyFrame* key, const QString& strSavePath)
123 {
124  if (key->isModified()) // keyframe was modified
125  return true;
126  if (QFile::exists(strSavePath) == false) // hasn't been saved before
127  return true;
128  if (strSavePath != key->fileName()) // key frame moved
129  return true;
130  return false;
131 }
132 
133 QDomElement LayerVector::createDomElement(QDomDocument& doc) const
134 {
135  QDomElement layerElem = createBaseDomElement(doc);
136 
137  foreachKeyFrame([&](KeyFrame* keyframe)
138  {
139  QDomElement imageTag = doc.createElement("image");
140  imageTag.setAttribute("frame", keyframe->pos());
141  imageTag.setAttribute("src", fileName(keyframe));
142  VectorImage* image = getVectorImageAtFrame(keyframe->pos());
143  imageTag.setAttribute("opacity", image->getOpacity());
144  layerElem.appendChild(imageTag);
145 
146  Q_ASSERT(QFileInfo(keyframe->fileName()).fileName() == fileName(keyframe));
147  });
148 
149  return layerElem;
150 }
151 
152 void LayerVector::loadDomElement(const QDomElement& element, QString dataDirPath, ProgressCallback progressStep)
153 {
154  this->loadBaseDomElement(element);
155 
156  QDomNode imageTag = element.firstChild();
157  while (!imageTag.isNull())
158  {
159  QDomElement imageElement = imageTag.toElement();
160  if (!imageElement.isNull())
161  {
162  if (imageElement.tagName() == "image")
163  {
164  int position;
165  if (!imageElement.attribute("src").isNull())
166  {
167  QString path = dataDirPath + "/" + imageElement.attribute("src"); // the file is supposed to be in the data directory
168  QFileInfo fi(path);
169  if (!fi.exists()) path = imageElement.attribute("src");
170  position = imageElement.attribute("frame").toInt();
171  loadImageAtFrame(path, position);
172  }
173  else
174  {
175  position = imageElement.attribute("frame").toInt();
176  addNewKeyFrameAt(position);
177  getVectorImageAtFrame(position)->loadDomElement(imageElement);
178  }
179  if (imageElement.hasAttribute("opacity"))
180  getVectorImageAtFrame(position)->setOpacity(imageElement.attribute("opacity").toDouble());
181  else
182  getVectorImageAtFrame(position)->setOpacity(1.0);
183  progressStep();
184  }
185  }
186  imageTag = imageTag.nextSibling();
187  }
188 }
189 
190 VectorImage* LayerVector::getVectorImageAtFrame(int frameNumber) const
191 {
192  return static_cast<VectorImage*>(getKeyFrameAt(frameNumber));
193 }
194 
195 VectorImage* LayerVector::getLastVectorImageAtFrame(int frameNumber, int increment) const
196 {
197  return static_cast<VectorImage*>(getLastKeyFrameAtPosition(frameNumber + increment));
198 }
QString & append(QChar ch)
QString asprintf(const char *cformat,...)
QDomNode appendChild(const QDomNode &newChild)
QString attribute(const QString &name, const QString &defValue) const const
bool read(QString filePath)
VectorImage::read.
Definition: vectorimage.cpp:74
void loadDomElement(QDomElement element)
VectorImage::loadDomElement.
QString filePath(const QString &fileName) const const
bool exists() const const
double toDouble(bool *ok) const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
QDomNode nextSibling() const const
QDomElement toElement() const const
bool hasAttribute(const QString &name) const const
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const const
bool usesColor(int index)
VectorImage::usesColor.
Definition: layer.h:38
bool isNull() const const
Status write(QString filePath, QString format)
VectorImage::write.
QDomNode firstChild() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
Definition: object.h:41
void removeColor(int index)
VectorImage::removeColor.
QString tagName() const const
QDomElement createElement(const QString &tagName)