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  layerElem.appendChild(imageTag);
143 
144  Q_ASSERT(QFileInfo(keyframe->fileName()).fileName() == fileName(keyframe));
145  });
146 
147  return layerElem;
148 }
149 
150 void LayerVector::loadDomElement(const QDomElement& element, QString dataDirPath, ProgressCallback progressStep)
151 {
152  this->loadBaseDomElement(element);
153 
154  QDomNode imageTag = element.firstChild();
155  while (!imageTag.isNull())
156  {
157  QDomElement imageElement = imageTag.toElement();
158  if (!imageElement.isNull())
159  {
160  if (imageElement.tagName() == "image")
161  {
162  if (!imageElement.attribute("src").isNull())
163  {
164  QString path = dataDirPath + "/" + imageElement.attribute("src"); // the file is supposed to be in the data directory
165  QFileInfo fi(path);
166  if (!fi.exists()) path = imageElement.attribute("src");
167  int position = imageElement.attribute("frame").toInt();
168  loadImageAtFrame(path, position);
169  }
170  else
171  {
172  int frame = imageElement.attribute("frame").toInt();
173  addNewKeyFrameAt(frame);
174  getVectorImageAtFrame(frame)->loadDomElement(imageElement);
175  }
176  progressStep();
177  }
178  }
179  imageTag = imageTag.nextSibling();
180  }
181 }
182 
183 VectorImage* LayerVector::getVectorImageAtFrame(int frameNumber) const
184 {
185  return static_cast<VectorImage*>(getKeyFrameAt(frameNumber));
186 }
187 
188 VectorImage* LayerVector::getLastVectorImageAtFrame(int frameNumber, int increment) const
189 {
190  return static_cast<VectorImage*>(getLastKeyFrameAtPosition(frameNumber + increment));
191 }
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:65
void loadDomElement(QDomElement element)
VectorImage::loadDomElement.
QString filePath(const QString &fileName) const const
bool exists() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
QDomNode nextSibling() const const
QDomElement toElement() 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:39
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:54
void removeColor(int index)
VectorImage::removeColor.
QString tagName() const const
QDomElement createElement(const QString &tagName)