All Classes Namespaces Functions Variables Enumerations Properties Pages
layercamera.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 "layercamera.h"
18 
19 #include <QSettings>
20 #include "camera.h"
21 #include "pencildef.h"
22 
23 LayerCamera::LayerCamera(Object* object) : Layer(object, Layer::CAMERA)
24 {
25  setName(tr("Camera Layer"));
26 
27  QSettings settings(PENCIL2D, PENCIL2D);
28  mFieldW = settings.value("FieldW").toInt();
29  mFieldH = settings.value("FieldH").toInt();
30  if (mFieldW < 2 || mFieldH < 2)
31  {
32  mFieldW = 800;
33  mFieldH = 600;
34  }
35  viewRect = QRect(QPoint(-mFieldW / 2, -mFieldH / 2), QSize(mFieldW, mFieldH));
36 }
37 
38 LayerCamera::~LayerCamera()
39 {
40 }
41 
42 Camera* LayerCamera::getCameraAtFrame(int frameNumber)
43 {
44  return static_cast<Camera*>(getKeyFrameAt(frameNumber));
45 }
46 
47 Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment)
48 {
49  return static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber + increment));
50 }
51 
52 QTransform LayerCamera::getViewAtFrame(int frameNumber) const
53 {
54  if (keyFrameCount() == 0)
55  {
56  return QTransform();
57  }
58 
59  Camera* camera1 = static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber));
60 
61  int nextFrame = getNextKeyFramePosition(frameNumber);
62  Camera* camera2 = static_cast<Camera*>(getLastKeyFrameAtPosition(nextFrame));
63 
64  if (camera1 == nullptr && camera2 == nullptr)
65  {
66  return QTransform();
67  }
68  else if (camera1 == nullptr && camera2 != nullptr)
69  {
70  return camera2->view;
71  }
72  else if (camera2 == nullptr && camera1 != nullptr)
73  {
74  return camera1->view;
75  }
76 
77  if (camera1 == camera2)
78  {
79  return camera1->view;
80  }
81 
82  double frame1 = camera1->pos();
83  double frame2 = camera2->pos();
84 
85  // linear interpolation
86  qreal c2 = (frameNumber - frame1) / (frame2 - frame1);
87  qreal c1 = 1.0 - c2;
88 
89  auto interpolation = [=](double f1, double f2) -> double
90  {
91  return f1 * c1 + f2 * c2;
92  };
93 
94  return QTransform(interpolation(camera1->view.m11(), camera2->view.m11()),
95  interpolation(camera1->view.m12(), camera2->view.m12()),
96  interpolation(camera1->view.m21(), camera2->view.m21()),
97  interpolation(camera1->view.m22(), camera2->view.m22()),
98  interpolation(camera1->view.dx(), camera2->view.dx()),
99  interpolation(camera1->view.dy(), camera2->view.dy()));
100 
101 }
102 
103 void LayerCamera::linearInterpolateTransform(Camera* cam)
104 {
105  if (keyFrameCount() == 0)
106  return;
107 
108  int frameNumber = cam->pos();
109  Camera* camera1 = static_cast<Camera*>(getLastKeyFrameAtPosition(frameNumber - 1));
110 
111  int nextFrame = getNextKeyFramePosition(frameNumber);
112  Camera* camera2 = static_cast<Camera*>(getLastKeyFrameAtPosition(nextFrame));
113 
114  if (camera1 == nullptr && camera2 == nullptr)
115  {
116  return; // do nothing
117  }
118  else if (camera1 == nullptr && camera2 != nullptr)
119  {
120  return cam->assign(*camera2);
121  }
122  else if (camera2 == nullptr && camera1 != nullptr)
123  {
124  return cam->assign(*camera1);
125  }
126 
127  if (camera1 == camera2)
128  {
129  return cam->assign(*camera1);
130  }
131 
132  double frame1 = camera1->pos();
133  double frame2 = camera2->pos();
134 
135  // linear interpolation
136  double c2 = (frameNumber - frame1) / (frame2 - frame1);
137 
138  auto lerp = [](double f1, double f2, double ratio) -> double
139  {
140  return f1 * (1.0 - ratio) + f2 * ratio;
141  };
142 
143  double dx = lerp(camera1->translation().x(), camera2->translation().x(), c2);
144  double dy = lerp(camera1->translation().y(), camera2->translation().y(), c2);
145  double r = lerp(camera1->rotation(), camera2->rotation(), c2);
146  double s = lerp(camera1->scaling(), camera2->scaling(), c2);
147 
148  cam->translate(dx, dy);
149  cam->rotate(r);
150  cam->scale(s);
151 }
152 
153 QRect LayerCamera::getViewRect()
154 {
155  return viewRect;
156 }
157 
158 QSize LayerCamera::getViewSize() const
159 {
160  return viewRect.size();
161 }
162 
163 void LayerCamera::setViewRect(QRect newViewRect)
164 {
165  viewRect = newViewRect;
166  emit resolutionChanged();
167 }
168 
169 void LayerCamera::loadImageAtFrame(int frameNumber, qreal dx, qreal dy, qreal rotate, qreal scale)
170 {
171  if (keyExists(frameNumber))
172  {
173  removeKeyFrame(frameNumber);
174  }
175  Camera* camera = new Camera(QPointF(dx, dy), rotate, scale);
176  camera->setPos(frameNumber);
177  loadKey(camera);
178 }
179 
180 Status LayerCamera::saveKeyFrameFile(KeyFrame*, QString)
181 {
182  return Status::OK;
183 }
184 
185 KeyFrame* LayerCamera::createKeyFrame(int position, Object*)
186 {
187  Camera* c = new Camera;
188  c->setPos(position);
189  linearInterpolateTransform(c);
190  return c;
191 }
192 
193 QDomElement LayerCamera::createDomElement(QDomDocument& doc) const
194 {
195  QDomElement layerElem = createBaseDomElement(doc);
196  layerElem.setAttribute("width", viewRect.width());
197  layerElem.setAttribute("height", viewRect.height());
198 
199  foreachKeyFrame([&](KeyFrame* pKeyFrame)
200  {
201  Camera* camera = static_cast<Camera*>(pKeyFrame);
202  QDomElement keyTag = doc.createElement("camera");
203  keyTag.setAttribute("frame", camera->pos());
204 
205  keyTag.setAttribute("r", camera->rotation());
206  keyTag.setAttribute("s", camera->scaling());
207  keyTag.setAttribute("dx", camera->translation().x());
208  keyTag.setAttribute("dy", camera->translation().y());
209  layerElem.appendChild(keyTag);
210  });
211 
212  return layerElem;
213 }
214 
215 void LayerCamera::loadDomElement(const QDomElement& element, QString dataDirPath, ProgressCallback progressStep)
216 {
217  Q_UNUSED(dataDirPath);
218  Q_UNUSED(progressStep);
219 
220  this->loadBaseDomElement(element);
221 
222  int width = element.attribute("width").toInt();
223  int height = element.attribute("height").toInt();
224  viewRect = QRect(-width / 2, -height / 2, width, height);
225 
226  QDomNode imageTag = element.firstChild();
227  while (!imageTag.isNull())
228  {
229  QDomElement imageElement = imageTag.toElement();
230  if (!imageElement.isNull())
231  {
232  if (imageElement.tagName() == "camera")
233  {
234  int frame = imageElement.attribute("frame").toInt();
235 
236  qreal rotate = imageElement.attribute("r", "0").toDouble();
237  qreal scale = imageElement.attribute("s", "1").toDouble();
238  qreal dx = imageElement.attribute("dx", "0").toDouble();
239  qreal dy = imageElement.attribute("dy", "0").toDouble();
240 
241  loadImageAtFrame(frame, dx, dy, rotate, scale);
242  }
243  }
244  imageTag = imageTag.nextSibling();
245  }
246 }
QSize size() const const
QDomNode appendChild(const QDomNode &newChild)
qreal dx() const const
qreal dy() const const
QString attribute(const QString &name, const QString &defValue) const const
int height() const const
double toDouble(bool *ok) const const
Definition: camera.h:24
QString tr(const char *sourceText, const char *disambiguation, int n)
QDomNode nextSibling() const const
QDomElement toElement() const const
qreal x() const const
qreal y() const const
void setAttribute(const QString &name, const QString &value)
qreal m11() const const
qreal m12() const const
qreal m21() const const
qreal m22() const const
int toInt(bool *ok, int base) const const
Definition: layer.h:39
bool isNull() const const
QDomNode firstChild() const const
int width() const const
Definition: object.h:54
QString tagName() const const
QDomElement createElement(const QString &tagName)