All Classes Namespaces Functions Variables Enumerations Properties Pages
viewmanager.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 
18 #include <QPainterPath>
19 #include "viewmanager.h"
20 #include "editor.h"
21 #include "object.h"
22 #include "camera.h"
23 #include "layercamera.h"
24 #include <QDebug>
25 
26 const static qreal mMinScale = 0.01;
27 const static qreal mMaxScale = 100.0;
28 
29 const std::vector<qreal> gZoomLevels
30 {
31  0.01, 0.02, 0.04, 0.06, 0.08, 0.12,
32  0.16, 0.25, 0.33, 0.5, 0.75, 1.0,
33  1.5, 2.0, 3.0, 4.0, 5.0, 6.0,
34  8.0, 16.0, 32.0, 48.0, 64.0, 96.0
35 };
36 
37 
38 ViewManager::ViewManager(Editor* editor) : BaseManager(editor, __FUNCTION__)
39 {
40  mDefaultEditorCamera = new Camera;
41  mCurrentCamera = mDefaultEditorCamera;
42 }
43 
44 ViewManager::~ViewManager()
45 {
46  delete mDefaultEditorCamera;
47 }
48 
49 bool ViewManager::init()
50 {
51  connect(editor(), &Editor::scrubbed, this, &ViewManager::onCurrentFrameChanged);
52  return true;
53 }
54 
55 Status ViewManager::load(Object*)
56 {
57  mCameraLayer = nullptr;
58  mCurrentCamera = mDefaultEditorCamera;
59  mCurrentCamera->reset();
60  updateViewTransforms();
61 
62  return Status::OK;
63 }
64 
65 Status ViewManager::save(Object* o)
66 {
67  o->data()->setCurrentView(mView);
68  return Status::OK;
69 }
70 
71 void ViewManager::workingLayerChanged(Layer* layer)
72 {
73  if (layer->type() == Layer::CAMERA)
74  {
75  setCameraLayer(layer);
76  }
77  else
78  {
79  setCameraLayer(nullptr);
80  }
81 }
82 
83 QPointF ViewManager::mapCanvasToScreen(QPointF p) const
84 {
85  return mViewCanvas.map(p);
86 }
87 
88 QPointF ViewManager::mapScreenToCanvas(QPointF p) const
89 {
90  return mViewCanvasInverse.map(p);
91 }
92 
93 QPainterPath ViewManager::mapCanvasToScreen(const QPainterPath& path) const
94 {
95  return mViewCanvas.map(path);
96 }
97 
98 QRectF ViewManager::mapCanvasToScreen(const QRectF& rect) const
99 {
100  return mViewCanvas.mapRect(rect);
101 }
102 
103 QRectF ViewManager::mapScreenToCanvas(const QRectF& rect) const
104 {
105  return mViewCanvasInverse.mapRect(rect);
106 }
107 
108 QPolygonF ViewManager::mapPolygonToScreen(const QPolygonF &polygon) const
109 {
110  return mViewCanvas.map(polygon);
111 }
112 
113 QPolygonF ViewManager::mapPolygonToCanvas(const QPolygonF &polygon) const
114 {
115  return mViewCanvasInverse.map(polygon);
116 }
117 
118 QPainterPath ViewManager::mapScreenToCanvas(const QPainterPath& path) const
119 {
120  return mViewCanvasInverse.map(path);
121 }
122 
123 QTransform ViewManager::getView() const
124 {
125  return mViewCanvas;
126 }
127 
128 QTransform ViewManager::getViewInverse() const
129 {
130  return mViewCanvasInverse;
131 }
132 
133 qreal ViewManager::getViewScaleInverse() const
134 {
135  return mViewCanvasInverse.m11();
136 }
137 
138 void ViewManager::updateViewTransforms()
139 {
140  if (mCameraLayer)
141  {
142  int frame = editor()->currentFrame();
143  mCurrentCamera = mCameraLayer->getCameraAtFrame(frame);
144  if (mCurrentCamera)
145  {
146  mCurrentCamera->updateViewTransform();
147  }
148  mView = mCameraLayer->getViewAtFrame(frame);
149  }
150  else
151  {
152  mCurrentCamera = mDefaultEditorCamera;
153  mCurrentCamera->updateViewTransform();
154 
155  mView = mCurrentCamera->getView();
156  }
157 
158  mViewInverse = mView.inverted();
159 
160  float flipX = mIsFlipHorizontal ? -1.f : 1.f;
161  float flipY = mIsFlipVertical ? -1.f : 1.f;
162  QTransform f = QTransform::fromScale(static_cast<qreal>(flipX), static_cast<qreal>(flipY));
163 
164  mViewCanvas = mView * f * mCentre;
165  mViewCanvasInverse = mViewCanvas.inverted();
166 }
167 
168 QPointF ViewManager::translation() const
169 {
170  if (mCurrentCamera)
171  {
172  return mCurrentCamera->translation();
173  }
174  return QPointF(0, 0);
175 }
176 
177 void ViewManager::translate(float dx, float dy)
178 {
179  if (mCurrentCamera)
180  {
181  mCurrentCamera->translate(static_cast<qreal>(dx), static_cast<qreal>(dy));
182  updateViewTransforms();
183 
184  emit viewChanged();
185  }
186 }
187 
188 void ViewManager::translate(QPointF offset)
189 {
190  translate(static_cast<float>(offset.x()), static_cast<float>(offset.y()));
191 }
192 
193 void ViewManager::centerView()
194 {
195  translate(0, 0);
196 }
197 
198 float ViewManager::rotation()
199 {
200  if (mCurrentCamera)
201  {
202  return static_cast<float>(mCurrentCamera->rotation());
203  }
204  return 0.0f;
205 }
206 
207 void ViewManager::rotate(float degree)
208 {
209  if (mCurrentCamera)
210  {
211  mCurrentCamera->rotate(static_cast<qreal>(degree));
212  updateViewTransforms();
213 
214  emit viewChanged();
215  }
216 }
217 
218 void ViewManager::resetRotation()
219 {
220  rotate(0);
221 }
222 
223 qreal ViewManager::scaling()
224 {
225  if (mCurrentCamera)
226  {
227  return mCurrentCamera->scaling();
228  }
229  return 0.0;
230 }
231 
232 void ViewManager::scaleUp()
233 {
234  for (size_t i = 0; i < gZoomLevels.size(); i++)
235  {
236  if (gZoomLevels[i] > scaling())
237  {
238  scale(gZoomLevels[i]);
239  return;
240  }
241  }
242 
243  // out of pre-defined zoom levels
244  scale(scaling() * 1.18);
245 }
246 
247 void ViewManager::scaleDown()
248 {
249  for (int i = static_cast<int>(gZoomLevels.size()) - 1; i >= 0; --i)
250  {
251  if (gZoomLevels[static_cast<unsigned>(i)] < scaling())
252  {
253  scale(gZoomLevels[static_cast<unsigned>(i)]);
254  return;
255  }
256  }
257  scale(scaling() * 0.8333);
258 }
259 
260 void ViewManager::scale100()
261 {
262  scale(1.0);
263 }
264 
265 void ViewManager::scale400()
266 {
267  scale(4.0);
268 }
269 
270 void ViewManager::scale300()
271 {
272  scale(3.0);
273 }
274 
275 void ViewManager::scale200()
276 {
277  scale(2.0);
278 }
279 
280 void ViewManager::scale50()
281 {
282  scale(0.5);
283 }
284 
285 void ViewManager::scale33()
286 {
287  scale(0.33);
288 }
289 
290 void ViewManager::scale25()
291 {
292  scale(0.25);
293 }
294 
295 void ViewManager::scale(qreal scaleValue)
296 {
297  if (scaleValue < mMinScale)
298  {
299  scaleValue = mMinScale;
300  }
301  else if (scaleValue > mMaxScale)
302  {
303  scaleValue = mMaxScale;
304  }
305 
306  if (mCurrentCamera)
307  {
308  mCurrentCamera->scale(scaleValue);
309  updateViewTransforms();
310 
311  emit viewChanged();
312  }
313 }
314 
315 void ViewManager::scaleWithOffset(qreal scaleValue, QPointF offset)
316 {
317  if (scaleValue < mMinScale)
318  {
319  scaleValue = mMinScale;
320  }
321  else if (scaleValue > mMaxScale)
322  {
323  scaleValue = mMaxScale;
324  }
325 
326  if (mCurrentCamera)
327  {
328  mCurrentCamera->scaleWithOffset(scaleValue, offset);
329  updateViewTransforms();
330 
331  emit viewChanged();
332  }
333 }
334 
335 void ViewManager::flipHorizontal(bool b)
336 {
337  if (b != mIsFlipHorizontal)
338  {
339  mIsFlipHorizontal = b;
340  updateViewTransforms();
341 
342  emit viewChanged();
343  emit viewFlipped();
344  }
345 }
346 
347 void ViewManager::flipVertical(bool b)
348 {
349  if (b != mIsFlipVertical)
350  {
351  mIsFlipVertical = b;
352  updateViewTransforms();
353 
354  emit viewChanged();
355  emit viewFlipped();
356  }
357 }
358 
359 void ViewManager::setOverlayCenter(bool b)
360 {
361  if (b != mOverlayCenter)
362  {
363  mOverlayCenter = b;
364  updateViewTransforms();
365  emit viewChanged();
366  }
367 }
368 
369 void ViewManager::setOverlayThirds(bool b)
370 {
371  if (b != mOverlayThirds)
372  {
373  mOverlayThirds = b;
374  updateViewTransforms();
375  emit viewChanged();
376  }
377 }
378 
379 void ViewManager::setOverlayGoldenRatio(bool b)
380 {
381  if (b != mOverlayGoldenRatio)
382  {
383  mOverlayGoldenRatio = b;
384  updateViewTransforms();
385  emit viewChanged();
386  }
387 }
388 
389 void ViewManager::setOverlaySafeAreas(bool b)
390 {
391  if (b != mOverlaySafeAreas)
392  {
393  mOverlaySafeAreas = b;
394  updateViewTransforms();
395  emit viewChanged();
396  }
397 }
398 
399 void ViewManager::setCanvasSize(QSize size)
400 {
401  mCanvasSize = size;
402  mCentre = QTransform::fromTranslate(mCanvasSize.width() / 2., mCanvasSize.height() / 2.);
403 
404  updateViewTransforms();
405  emit viewChanged();
406 }
407 
408 void ViewManager::setCameraLayer(Layer* layer)
409 {
410  if (layer != nullptr)
411  {
412  if (layer->type() != Layer::CAMERA)
413  {
414  Q_ASSERT(false && "Only camera layers allowed pls");
415  return;
416  }
417  mCameraLayer = static_cast<LayerCamera*>(layer);
418  }
419  else
420  {
421  mCameraLayer = nullptr;
422  }
423 
424  updateViewTransforms();
425 }
426 
427 void ViewManager::forceUpdateViewTransform()
428 {
429  updateViewTransforms();
430  emit viewChanged();
431 }
432 
433 void ViewManager::onCurrentFrameChanged()
434 {
435  if (mCameraLayer)
436  {
437  updateViewTransforms();
438  }
439 
440  // emit changes either way because of potential camera interpolation changes
441  emit viewChanged();
442 }
443 
444 void ViewManager::resetView()
445 {
446  if (mCurrentCamera)
447  {
448  mCurrentCamera->reset();
449  updateViewTransforms();
450  emit viewChanged();
451  emit viewFlipped();
452  }
453 }
QTransform fromTranslate(qreal dx, qreal dy)
QTransform fromScale(qreal sx, qreal sy)
int width() const const
QPoint map(const QPoint &point) const const
void scrubbed(int frameNumber)
This should be emitted after scrubbing.
Definition: camera.h:24
QTransform inverted(bool *invertible) const const
qreal x() const const
qreal y() const const
qreal m11() const const
Definition: layer.h:38
int height() const const
Definition: object.h:41
Definition: editor.h:55
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QRect mapRect(const QRect &rectangle) const const