Radium Engine  1.5.0
TimelineScrollArea.cpp
1 #include <Gui/Timeline/TimelineScrollArea.hpp>
2 
3 #include <cmath>
4 
5 #include <QScrollBar>
6 #include <QWheelEvent>
7 
8 #include <Gui/Timeline/Timeline.hpp>
9 #include <Gui/Timeline/TimelineFrameSelector.hpp>
10 
11 namespace Ra::Gui {
12 
13 TimelineScrollArea::TimelineScrollArea( QWidget* parent ) : QScrollArea( parent ) {
14  horizontalScrollBar()->setStyleSheet( "\
15  QScrollBar:horizontal {\
16  background: transparent;\
17  }\
18  \
19  QScrollBar::handle:horizontal {\
20  background: white;\
21  }\
22  \
23  QScrollBar::add-line:horizontal {\
24  border: none;\
25  background: transparent;\
26  }\
27  \
28  QScrollBar::sub-line:horizontal {\
29  border: none;\
30  background: transparent;\
31  }" );
32 }
33 
34 int TimelineScrollArea::getNbInterval() {
35  return m_nbInterval;
36 }
37 
38 Scalar TimelineScrollArea::getMaxDuration() {
39  return m_maxDuration;
40 }
41 
42 void TimelineScrollArea::setMaxDuration( Scalar duration ) {
43  m_maxDuration = duration;
44 }
45 
46 int TimelineScrollArea::getZero() {
47  return m_zero;
48 }
49 
50 Scalar TimelineScrollArea::getPixPerSec() {
51  return m_pixPerSec;
52 }
53 
54 Scalar TimelineScrollArea::getStep() {
55  return m_step;
56 }
57 
58 void TimelineScrollArea::onDrawRuler( int width ) {
59  int iStep = 0;
60  while ( iStep < s_nbSteps && width * s_steps[iStep] < 50 * m_maxDuration )
61  iStep++;
62 
63  if ( iStep == s_nbSteps ) { return; }
64 
65  m_step = s_steps[iStep];
66  emit stepChanged( m_step );
67 
68  m_nbInterval = int( std::ceil( m_maxDuration / m_step ) ) + 2;
69  m_pixPerSec = ( Scalar( width ) / m_nbInterval ) / m_step;
70  m_zero = int( m_pixPerSec * m_step );
71  widget()->setMinimumWidth( width );
72 
73  update();
74 }
75 
76 void TimelineScrollArea::keyPressEvent( QKeyEvent* event ) {
77  switch ( event->key() ) {
78  case Qt::Key_Space:
79  emit togglePlayPause();
80  break;
81 
82  case Qt::Key_Delete:
83  emit removeKeyFrame();
84  break;
85 
86  case Qt::Key_I:
87  if ( event->modifiers() & Qt::Modifier::SHIFT ) { emit removeKeyFrame(); }
88  else { emit addKeyFrame(); }
89  break;
90 
91  case Qt::Key_Left:
92  emit previousKeyFrame();
93  break;
94 
95  case Qt::Key_Right:
96  emit nextKeyFrame();
97  break;
98 
99  case Qt::Key_Up:
100  emit durationIncrement();
101  break;
102 
103  case Qt::Key_Down:
104  emit durationDecrement();
105  break;
106 
107  case Qt::Key_Z:
108  if ( event->modifiers() & Qt::Modifier::CTRL ) {
109  if ( event->modifiers() & Qt::Modifier::SHIFT ) { emit redo(); }
110  else { emit undo(); }
111  }
112  break;
113 
114  case Qt::Key_U:
115  emit undo();
116  break;
117 
118  case Qt::Key_R:
119  emit redo();
120  break;
121  default:
122  break;
123  }
124 }
125 
126 void TimelineScrollArea::wheelEvent( QWheelEvent* event ) {
127  int ry = event->angleDelta().ry();
128  bool ctrlDown = event->modifiers() & Qt::Modifier::CTRL;
129  bool shiftDown = event->modifiers() & Qt::Modifier::SHIFT;
130  // next/previous KeyFrame
131  if ( shiftDown ) {
132  if ( ry > 0 ) { emit nextKeyFrame(); }
133  else { emit previousKeyFrame(); }
134  }
135  // scroll left/right bar
136  else if ( ctrlDown ) {
137  horizontalScrollBar()->setValue(
138  int( horizontalScrollBar()->value() + ry * TIMELINE_SLIDE_SPEED ) );
139  }
140  // zoom in/out
141  else {
142  int newRulerWidth = int( widget()->minimumWidth() +
143  ry * TIMELINE_ZOOM_SPEED * widget()->minimumWidth() / width() );
144  if ( newRulerWidth <= width() - 2 ) {
145  if ( widget()->minimumWidth() == width() - 2 ) { return; }
146  else { newRulerWidth = width() - 2; }
147  }
148 
149  double hScroll = horizontalScrollBar()->value();
150 #if QT_VERSION < QT_VERSION_CHECK( 5, 15, 0 )
151  double x = event->x();
152 #else
153  double x = event->position().x();
154 #endif
155  double time = ( hScroll + x - double( m_zero ) ) / double( m_pixPerSec );
156 
157  onDrawRuler( newRulerWidth );
158 
159  // ruler values may have changed
160  double a = time * double( m_pixPerSec ) + double( m_zero );
161  double hScrollAfterProjection = a - x;
162  horizontalScrollBar()->setValue( static_cast<int>( hScrollAfterProjection ) );
163  }
164  event->accept(); // parent is animTimeline (root) with non event catching
165 }
166 
167 void TimelineScrollArea::mousePressEvent( QMouseEvent* event ) {
168  if ( event->button() == Qt::MiddleButton ) {
169  setCursor( Qt::SplitHCursor );
170  m_mousePosX = event->x();
171  m_sliderPos = horizontalScrollBar()->value();
172  }
173 }
174 
175 void TimelineScrollArea::mouseReleaseEvent( QMouseEvent* event ) {
176  if ( event->button() == Qt::MiddleButton ) { setCursor( Qt::ArrowCursor ); }
177 }
178 
179 void TimelineScrollArea::mouseMoveEvent( QMouseEvent* event ) {
180  if ( event->buttons() & Qt::MiddleButton ) {
181  horizontalScrollBar()->setValue( ( m_sliderPos + m_mousePosX - event->x() ) );
182  }
183 }
184 
185 } // namespace Ra::Gui