From 747f520cc2e16a97d38c3caf28ecb1880ae1aa4c Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Fri, 30 Aug 2019 10:38:06 +0300 Subject: Timeline ruler and scaling enhancements - Make timeline scaling smoother and allow further scale values. - Implement non linear scaling strategy which improve UX. - Double clicking the scale head resets the scale to the default value - Optimize drawing by only drawing the visible part of the ruler. - Other assorted small tweaks Change-Id: I5fbf729f3b5e098a60e26978af6bc82bb5f307ae Reviewed-by: Miikka Heikkinen --- .../Palettes/Inspector/VariantsGroupModel.cpp | 2 +- .../Palettes/TimelineGraphicsView/RowManager.cpp | 8 +- .../TimelineGraphicsView/TimelineConstants.h | 6 +- .../TimelineGraphicsView/TimelineGraphicsScene.cpp | 14 +- .../TimelineGraphicsView/TimelineGraphicsScene.h | 1 - .../TimelineGraphicsView/TimelineWidget.cpp | 4 - .../Palettes/TimelineGraphicsView/ui/PlayHead.cpp | 17 +- .../Palettes/TimelineGraphicsView/ui/PlayHead.h | 3 +- .../TimelineGraphicsView/ui/RowTimeline.cpp | 8 +- .../ui/RowTimelinePropertyGraph.cpp | 4 +- .../Palettes/TimelineGraphicsView/ui/Ruler.cpp | 196 ++++++++++++--------- .../Palettes/TimelineGraphicsView/ui/Ruler.h | 8 +- .../TimelineGraphicsView/ui/TimelineToolbar.cpp | 57 +++--- 13 files changed, 170 insertions(+), 158 deletions(-) diff --git a/src/Authoring/Qt3DStudio/Palettes/Inspector/VariantsGroupModel.cpp b/src/Authoring/Qt3DStudio/Palettes/Inspector/VariantsGroupModel.cpp index 066f912a..0142b668 100644 --- a/src/Authoring/Qt3DStudio/Palettes/Inspector/VariantsGroupModel.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/Inspector/VariantsGroupModel.cpp @@ -152,7 +152,7 @@ void VariantsGroupModel::setTagState(const QString &group, const QString &tag, b } } - Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), QObject::tr("Set Property")) + Q3DStudio::SCOPED_DOCUMENT_EDITOR(*g_StudioApp.GetCore()->GetDoc(), tr("Set Tag State")) ->SetInstancePropertyValue(m_instance, m_property, QVariant(val)); } diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp index b250062c..70a18560 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp @@ -292,15 +292,13 @@ void RowManager::updateRulerDuration(bool updateMaxDuration) long maxDuration = 0; // for setting correct size for the view so scrollbars appear correctly if (m_layoutTree->count() > 1) { auto rootRow = static_cast(m_layoutTree->itemAt(1)->graphicsItem()); - bool isComponent = rootRow->objectType() == OBJTYPE_COMPONENT; - for (int i = 1; i < m_layoutTree->count(); ++i) { + bool insideComponent = rootRow->objectType() == OBJTYPE_COMPONENT; + for (int i = 2; i < m_layoutTree->count(); ++i) { RowTree *row_i = static_cast(m_layoutTree->itemAt(i)->graphicsItem()); long dur_i = row_i->rowTimeline()->getEndTime(); - if (((isComponent && i != 1) || row_i->objectType() == OBJTYPE_LAYER) - && dur_i > duration) { + if ((insideComponent || row_i->objectType() == OBJTYPE_LAYER) && dur_i > duration) duration = dur_i; - } if (dur_i > maxDuration) maxDuration = dur_i; diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h index c9036aba..02d08141 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h @@ -37,15 +37,13 @@ namespace TimelineConstants const int ROW_GRAPH_H_MAX = 300; // property row height when graph is shown maximized const int ROW_SPACING = 2; const int ROW_DEPTH_STEP = 15; // x-distance between 2 consecutive depths - const double RULER_SEC_W = 30; // width of 1 second section (at scale 1) + const double RULER_SEC_W = 60; // width of 1 second section (at scale 1) const double RULER_MILLI_W = RULER_SEC_W / 1000.0; // width of 1 millisecond section at scale 1 const int RULER_SEC_DIV = 10; // second divisions const int RULER_DIV_H1 = 5; // height of main divisions const int RULER_DIV_H2 = 3; // height of secondary divisions const int RULER_DIV_H3 = 1; // height of minor divisions const int RULER_BASE_Y = 18; // baseline Y - const int RULER_LABEL_W = 60; - const int RULER_LABEL_H = 10; const int RULER_TICK_SCALE1 = 2; const int RULER_TICK_SCALE2 = 3; const int RULER_TICK_SCALE3 = 6; @@ -75,8 +73,6 @@ namespace TimelineConstants const int TIMELINE_SCROLL_MAX_DELTA = 25; // Maximum amount of pixels to scroll per frame const int TIMELINE_SCROLL_DIVISOR = 6; // Divisor for timeline autoscroll distance - - // TODO: move the colors and dimensions to StudioPreferences. } #endif // TIMELINECONSTANTS_H diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp index 026a7a68..6aff79cb 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp @@ -285,7 +285,7 @@ TimelineGraphicsScene::TimelineGraphicsScene(TimelineWidget *timelineWidget) }); QTimer::singleShot(0, this, [this]() { - m_playHead->setPosition(0); + m_playHead->setTime(0); m_widgetTimeline->viewTreeContent()->horizontalScrollBar()->setValue(0); }); @@ -370,22 +370,12 @@ void TimelineGraphicsScene::setControllerText(const QString &controller) void TimelineGraphicsScene::updateTimelineLayoutWidth() { double timelineWidth = TimelineConstants::RULER_EDGE_OFFSET * 2 - + m_ruler->maxDuration() * TimelineConstants::RULER_MILLI_W - * m_ruler->timelineScale(); + + m_ruler->timeToDistance(m_ruler->maxDuration()); m_layoutTimeline->setMinimumWidth(timelineWidth); m_layoutTimeline->setMaximumWidth(timelineWidth); } -void TimelineGraphicsScene::updateControllerLayoutWidth() -{ - if (m_layoutTimeline->count() < 2) - return; - auto root = m_layoutTimeline->itemAt(1); - - static_cast(root->graphicsItem())->setEndTime(ruler()->duration()); -} - void TimelineGraphicsScene::updateController() { setControllerText(m_widgetTimeline->toolbar()->getCurrentController()); diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h index d39b57aa..fbdecefd 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h @@ -69,7 +69,6 @@ public: void setTimelineScale(int scale); void setControllerText(const QString &controller); void updateTimelineLayoutWidth(); - void updateControllerLayoutWidth(); void updateController(); Ruler *ruler() const; PlayHead *playHead() const; diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp index 9b7bb09d..12bd415b 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp @@ -290,10 +290,6 @@ TimelineWidget::TimelineWidget(const QSize &preferredSize, QWidget *parent) m_graphicsScene->updateTimelineLayoutWidth(); }); - connect(m_graphicsScene->ruler(), &Ruler::durationChanged, this, [this]() { - m_graphicsScene->updateControllerLayoutWidth(); - }); - // data model listeners g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this); g_StudioApp.GetCore()->GetDispatch()->AddClientPlayChangeListener(this); diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.cpp index 3ddfdcad..1a847112 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.cpp @@ -54,7 +54,8 @@ void PlayHead::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, static const QPixmap pixHead2x = QPixmap(":/images/PlaybackHead@2x.png"); static const int PLAY_HEAD_H = 999999; // theoretically big enough height - painter->drawPixmap(-TimelineConstants::PLAYHEAD_W * .5, 0, hiResIcons ? pixHead2x : pixHead); + painter->drawPixmap(int(-TimelineConstants::PLAYHEAD_W * .5f), 0, hiResIcons ? pixHead2x + : pixHead); painter->setPen(CStudioPreferences::timelinePlayheadLineColor()); painter->drawLine(0, 0, 0, PLAY_HEAD_H); } @@ -75,21 +76,9 @@ void PlayHead::setTime(long time) updatePosition(); } -void PlayHead::setPosition(double posX) -{ - posX = qBound(TimelineConstants::RULER_EDGE_OFFSET, posX, m_ruler->duration() - * TimelineConstants::RULER_MILLI_W * m_ruler->timelineScale() - + TimelineConstants::RULER_EDGE_OFFSET); - - setX(m_ruler->x() + posX); - m_time = (posX - TimelineConstants::RULER_EDGE_OFFSET) - / (TimelineConstants::RULER_MILLI_W * m_ruler->timelineScale()); -} - void PlayHead::updatePosition() { - setX(m_ruler->x() + TimelineConstants::RULER_EDGE_OFFSET - + m_time * TimelineConstants::RULER_MILLI_W * m_ruler->timelineScale()); + setX(m_ruler->x() + TimelineConstants::RULER_EDGE_OFFSET + m_ruler->timeToDistance(m_time)); } long PlayHead::time() const diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.h index 395e6317..852e6aff 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.h @@ -42,7 +42,6 @@ public: explicit PlayHead(Ruler *m_ruler); void setHeight(int height); - void setPosition(double posX); // set x poisiotn void updatePosition(); // sync x poisiotn based on time value void setTime(long time); // set time (sets x based on time (ms) input) void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, @@ -52,7 +51,7 @@ public: private: long m_time = 0; - Ruler *m_ruler; + Ruler *m_ruler = nullptr; }; #endif // PLAYHEAD_H diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp index 9fb338ea..bca36b7a 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp @@ -154,12 +154,10 @@ void RowTimeline::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio painter->setPen(Qt::NoPen); - if (m_controllerDataInput.size()) { - painter->fillRect(QRect(x, 0, w, currHeight), - CStudioPreferences::dataInputColor()); - } else if (m_rowTree->indexInLayout() != 1) { + if (m_controllerDataInput.size()) + painter->fillRect(QRect(x, 0, w, currHeight), CStudioPreferences::dataInputColor()); + else if (m_rowTree->indexInLayout() != 1) painter->fillRect(QRect(x, 0, w, currHeight), m_barColor); - } if (m_state == Selected) { // draw selection overlay on bar diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp index fbc92377..eefe6282 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp @@ -70,7 +70,6 @@ void RowTimelinePropertyGraph::paintGraphs(QPainter *painter, const QRectF &rect painter->setClipRect(rect); static const QPointF edgeOffset(RULER_EDGE_OFFSET, 0); - double timelineScale = m_rowTimeline->rowTree()->m_scene->ruler()->timelineScale(); // draw graph base line (graph_Y) painter->setPen(QPen(CStudioPreferences::studioColor3())); @@ -121,7 +120,8 @@ void RowTimelinePropertyGraph::paintGraphs(QPainter *painter, const QRectF &rect QPainterPath path; int start_j = qMax(rect.x(), edgeOffset.x()); for (int j = start_j; j < rect.right(); j += 5) { // 5 = sampling step in pixels - long time = (j - edgeOffset.x()) / (RULER_MILLI_W * timelineScale); // millis + long time = m_rowTimeline->rowTree()->m_scene->ruler() + ->distanceToTime(j - edgeOffset.x()); float value = m_propBinding->GetChannelValueAtTime(m_activeChannelsIndex[i], time); adjustColorProperty(value); diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.cpp index 9b883552..a72509df 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.cpp @@ -33,6 +33,8 @@ #include #include +using namespace TimelineConstants; + Ruler::Ruler(TimelineItem *parent) : TimelineItem(parent) { setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); @@ -42,95 +44,141 @@ void Ruler::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWi { Q_UNUSED(option) - double xStep = TimelineConstants::RULER_SEC_W / TimelineConstants::RULER_SEC_DIV * m_timeScale; - double activeSegmentsWidth = TimelineConstants::RULER_EDGE_OFFSET - + m_duration / 1000.0 * xStep * TimelineConstants::RULER_SEC_DIV; - double totalSegmentsWidth = TimelineConstants::RULER_EDGE_OFFSET - + m_maxDuration / 1000.0 * xStep * TimelineConstants::RULER_SEC_DIV; - - // Ruler painted width to be at least widget width - double minRulerWidth = widget->width(); - double rowXMax = std::max(minRulerWidth, totalSegmentsWidth); + painter->translate(RULER_EDGE_OFFSET, RULER_BASE_Y); - painter->save(); + // draw inactive base line + int startX = qMax(m_viewportX - int(RULER_EDGE_OFFSET), 0); + int endX = m_viewportX + widget->width(); painter->setPen(CStudioPreferences::timelineRulerColorDisabled()); - painter->drawLine(TimelineConstants::RULER_EDGE_OFFSET, - TimelineConstants::RULER_BASE_Y, - rowXMax + TimelineConstants::RULER_EDGE_OFFSET, - TimelineConstants::RULER_BASE_Y); - painter->setPen(CStudioPreferences::timelineRulerColor()); - painter->drawLine(TimelineConstants::RULER_EDGE_OFFSET, - TimelineConstants::RULER_BASE_Y, - activeSegmentsWidth, - TimelineConstants::RULER_BASE_Y); + painter->drawLine(startX, 0, endX, 0); + + // draw active base line + int durEndX = qMin(endX, int(timeToDistance(m_duration))); + if (durEndX > startX) { + painter->setPen(CStudioPreferences::timelineRulerColor()); + painter->drawLine(startX, 0, durEndX, 0); + } + // draw ruler steps and text QFont font = painter->font(); font.setPointSize(8); painter->setFont(font); - const int margin = 50; - const int secDiv = TimelineConstants::RULER_SEC_DIV; - double rowX = 0; bool useDisabledColor = false; - for (int i = 0; rowX < rowXMax; i++) { - rowX = TimelineConstants::RULER_EDGE_OFFSET + xStep * i; - - // Optimization to skip painting outside the visible area - if (rowX < (m_viewportX - margin) || rowX > (m_viewportX + minRulerWidth + margin)) + int startSecond = int(distanceToTime(startX) / 1000); + int endSecond = int(distanceToTime(endX) / 1000) + 1; + + static const int LABEL_W = 40; + static const int LABEL_H = 10; + static const int MIN_SEC_STEP_DIVISION = 20; + static const int MIN_SEC_STEP_LABEL = 60; + static const int MIN_HALF_SEC_STEP_DIVISION = 10; + static const int MIN_HALF_SEC_STEP_LABEL = 70; + static const int MIN_ONE_TENTH_STEP_DIVISION = 4; + static const int MIN_ONE_TENTH_STEP_LABEL = 30; + + QRectF labelRect(0, 0, LABEL_W, LABEL_H); + double secStep = timeToDistance(1000); + double halfSecStep = timeToDistance(500); + double oneTenthStep = timeToDistance(100); + + int skipperSecLabel = qMax(int(MIN_SEC_STEP_LABEL / secStep), 1); + if (skipperSecLabel > 5) + skipperSecLabel = lroundf(skipperSecLabel / 5.f) * 5; + + int skipperSecDivision = qMax(int(MIN_SEC_STEP_DIVISION / secStep), 1); + + // keep skipperSecLabel and skipperSecDivision in sync + if (skipperSecLabel > 5 && skipperSecDivision % 5) + skipperSecDivision = lroundf(skipperSecLabel / 10.f) * 5; + + bool drawHalfSecDiv = halfSecStep > MIN_HALF_SEC_STEP_DIVISION; + bool drawHalfSecLabel = halfSecStep > MIN_HALF_SEC_STEP_LABEL; + bool drawOneTenthDiv = oneTenthStep > MIN_ONE_TENTH_STEP_DIVISION; + bool drawOneTenthLabel = oneTenthStep > MIN_ONE_TENTH_STEP_LABEL; + + for (int i = startSecond; i <= endSecond; ++i) { // draw seconds + if (i % skipperSecDivision) continue; - const int h = i % secDiv == 0 ? TimelineConstants::RULER_DIV_H1 - : i % secDiv == secDiv * 0.5 ? TimelineConstants::RULER_DIV_H2 - : TimelineConstants::RULER_DIV_H3; - - if (!useDisabledColor && rowX > activeSegmentsWidth) { + int x = int(timeToDistance(i * 1000)); + if (!useDisabledColor && x > durEndX) { painter->setPen(CStudioPreferences::timelineRulerColorDisabled()); useDisabledColor = true; } - painter->drawLine(QPointF(rowX, TimelineConstants::RULER_BASE_Y - h), - QPointF(rowX, TimelineConstants::RULER_BASE_Y - 1)); - - // See if label should be shown at this tick at this zoom level - bool drawTimestamp = false; - if ((i % (secDiv * 4) == 0) - || (i % (secDiv * 2) == 0 && m_timeScale >= TimelineConstants::RULER_TICK_SCALE1) - || (i % secDiv == 0 && m_timeScale >= TimelineConstants::RULER_TICK_SCALE2) - || (i % secDiv == secDiv * 0.5 - && m_timeScale >= TimelineConstants::RULER_TICK_SCALE3) - || (m_timeScale >= TimelineConstants::RULER_TICK_SCALE4)) { - drawTimestamp = true; + + // draw second division + painter->drawLine(x, -RULER_DIV_H1, x, 0); + + if (i % skipperSecLabel == 0) { // draw label if not skipped + labelRect.moveTo(x - LABEL_W / 2, -LABEL_H - 7); + painter->drawText(labelRect, Qt::AlignCenter, formatTime(i)); } - if (drawTimestamp) { - QRectF timestampPos = QRectF(TimelineConstants::RULER_EDGE_OFFSET - + xStep * i - TimelineConstants::RULER_LABEL_W / 2, - 1, TimelineConstants::RULER_LABEL_W, - TimelineConstants::RULER_LABEL_H); - painter->drawText(timestampPos, Qt::AlignCenter, - timestampString(i * 1000 / TimelineConstants::RULER_SEC_DIV)); + // draw half seconds + if (!drawHalfSecDiv || i == endSecond) + continue; + + x = int(timeToDistance(i * 1000 + 500)); + if (!useDisabledColor && x > durEndX) { + painter->setPen(CStudioPreferences::timelineRulerColorDisabled()); + useDisabledColor = true; } + painter->drawLine(x, -RULER_DIV_H2, x, 0); - } + if (drawHalfSecLabel) { + labelRect.moveTo(x - LABEL_W / 2, -LABEL_H - 7); + painter->drawText(labelRect, Qt::AlignCenter, formatTime(i + .5)); + } + + // draw one tenth + if (!drawOneTenthDiv) + continue; - painter->restore(); + for (int j = 1; j <= 9; ++j) { + if (j != 5) { + x = int(timeToDistance(i * 1000 + j * 100)); + if (!useDisabledColor && x > durEndX) { + painter->setPen(CStudioPreferences::timelineRulerColorDisabled()); + useDisabledColor = true; + } + painter->drawLine(x, -RULER_DIV_H3, x, 0); + + if (drawOneTenthLabel) { + labelRect.moveTo(x - LABEL_W / 2, -LABEL_H - 7); + painter->drawText(labelRect, Qt::AlignCenter, formatTime(i + .1 * j)); + } + } + } + } } -void Ruler::setTimelineScale(double scl) +void Ruler::setTimelineScale(int scl) { - m_timeScale = scl; + // scl is in the range 0..100, project it to an exponential value + bool isScaleDown = scl < 50; + const double normVal = abs(scl - 50) / 10.; // normalize to range 5..0..5 from scale down to up + double scaleVal = pow(normVal, 1.3); + + // For scaling down normalize to range -1..0. 5^1.3 is max scaleVal but 5.1 is used to make + // sure scaleVal doesn't reach -1 in which case m_timeScale would become 0. + if (isScaleDown) + scaleVal /= -pow(5.1, 1.3); + + m_timeScale = 1 + scaleVal; update(); } // convert distance values to time (milliseconds) long Ruler::distanceToTime(double distance) const { - return distance / (TimelineConstants::RULER_MILLI_W * m_timeScale); + return long(distance / (RULER_MILLI_W * m_timeScale)); } // convert time (milliseconds) values to distance double Ruler::timeToDistance(long time) const { - return time * TimelineConstants::RULER_MILLI_W * m_timeScale; + return time * RULER_MILLI_W * m_timeScale; } double Ruler::timelineScale() const @@ -159,7 +207,6 @@ void Ruler::setDuration(long duration) if (m_duration != duration) { m_duration = duration; update(); - emit durationChanged(m_duration); } } @@ -187,30 +234,17 @@ int Ruler::viewportX() const return m_viewportX; } -// Returns timestamp in mm:ss.ttt or ss.ttt format -const QString Ruler::timestampString(int timeMs) +// Returns ruler time in m:s.t or s.t format +const QString Ruler::formatTime(double seconds) { - static const QString zeroString = tr("0"); - static const QChar fillChar = tr("0").at(0); - static const QString noMinutesTemplate = tr("%1.%2"); - static const QString minutesTemplate = tr("%1:%2.%3"); - - int ms = timeMs % 1000; - int s = timeMs % 60000 / 1000; - int m = timeMs % 3600000 / 60000; - const QString msString = QString::number(ms).rightJustified(3, fillChar); - const QString sString = QString::number(s); - - if (timeMs == 0) { - return zeroString; - } else if (m == 0) { - if (s < 10) - return noMinutesTemplate.arg(sString).arg(msString); - else - return noMinutesTemplate.arg(sString.rightJustified(2, fillChar)).arg(msString); - } else { - return minutesTemplate.arg(m).arg(sString.rightJustified(2, fillChar)).arg(msString); - } + if (seconds < 60) + return QString::number(seconds); + + int mins = int(seconds) / 60; + double secs = seconds - mins * 60; + + const QChar fillChar = tr("0").at(0); + return QStringLiteral("%1:%2").arg(mins).arg(QString::number(secs).rightJustified(2, fillChar)); } int Ruler::type() const diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.h b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.h index 005a23c3..355d3447 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.h +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.h @@ -41,7 +41,7 @@ signals: public: explicit Ruler(TimelineItem *parent = nullptr); - void setTimelineScale(double scl); + void setTimelineScale(int scl); long distanceToTime(double distance) const; double timeToDistance(long time) const; double timelineScale() const; @@ -59,12 +59,12 @@ protected: signals: void maxDurationChanged(long maxDuration); - void durationChanged(long duration); void viewportXChanged(int viewportX); private: - const QString timestampString(int timeMs); - double m_timeScale = 2; + const QString formatTime(double seconds); + + double m_timeScale = 1.; long m_duration = 0; // milliseconds long m_maxDuration = 0; // milliseconds int m_viewportX = 0; diff --git a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineToolbar.cpp b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineToolbar.cpp index a4f41026..b587cf51 100644 --- a/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineToolbar.cpp +++ b/src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineToolbar.cpp @@ -46,6 +46,24 @@ #include #include +class TimelineScaleEventfilter : public QObject +{ +public: + TimelineScaleEventfilter(QObject *parent) : QObject(parent) {} + + bool eventFilter(QObject *obj, QEvent *event) override + { + // reset scale upon double clicking the scale slider's head + if (event->type() == QEvent::MouseButtonDblClick) { + static_cast(obj)->setValue(50); + event->accept(); + return true; + } + + return QObject::eventFilter(obj, event); + } +}; + TimelineToolbar::TimelineToolbar() : QToolBar() { setContentsMargins(0, 0, 0, 0); @@ -85,16 +103,17 @@ TimelineToolbar::TimelineToolbar() : QToolBar() m_scaleSlider = new QSlider(); m_scaleSlider->setOrientation(Qt::Horizontal); m_scaleSlider->setFixedWidth(100); - m_scaleSlider->setMinimum(1); - m_scaleSlider->setMaximum(22); - m_scaleSlider->setValue(2); + m_scaleSlider->setMinimum(0); + m_scaleSlider->setMaximum(100); + m_scaleSlider->setValue(50); + m_scaleSlider->installEventFilter(new TimelineScaleEventfilter(this)); m_timeLabel->setObjectName(QLatin1String("timelineButton")); m_timeLabel->setFlat(true); m_timeLabel->setMinimumWidth(80); m_timeLabel->setToolTip(tr("Go To Time (%1%2T)").arg(ctrlKey).arg(altKey)); - m_diLabel->setText(""); + m_diLabel->clear(); m_diLabel->setMinimumWidth(100); m_diLabel->setAlignment(Qt::AlignCenter); QString styleString = "QLabel { background: transparent; color: " @@ -256,12 +275,12 @@ void TimelineToolbar::onZoomLevelChanged(int scale) void TimelineToolbar::onZoomInButtonClicked() { - m_scaleSlider->setValue(m_scaleSlider->value() + 1); + m_scaleSlider->setValue(m_scaleSlider->value() + 5); } void TimelineToolbar::onZoomOutButtonClicked() { - m_scaleSlider->setValue(m_scaleSlider->value() - 1); + m_scaleSlider->setValue(m_scaleSlider->value() - 5); } void TimelineToolbar::onDiButtonClicked() @@ -393,29 +412,29 @@ void TimelineToolbar::onDataInputChange(int handle, int instance, const QString timeCtxRoot, ctrldPropertyHandle, controlledPropertyVal); auto existingCtrl = qt3dsdm::get(controlledPropertyVal); - int slideStrPos = existingCtrl.indexOf("@timeline"); + int slideStrPos = existingCtrl.indexOf(QLatin1String("@timeline")); if (slideStrPos != -1) { // find the controlling datainput name and build the string to replace - int ctrStrPos = existingCtrl.lastIndexOf("$", slideStrPos - 2); + int ctrStrPos = existingCtrl.lastIndexOf(QLatin1Char('$'), slideStrPos - 2); QString prevCtrler = existingCtrl.mid(ctrStrPos, slideStrPos - ctrStrPos); existingCtrl.replace(prevCtrler + "@timeline", fullTimeControlStr); } else { if (!existingCtrl.isEmpty() && m_currController.size()) - existingCtrl.append(" "); + existingCtrl.append(QLatin1Char(' ')); existingCtrl.append(fullTimeControlStr); } - if (existingCtrl.endsWith(" ")) + if (existingCtrl.endsWith(QLatin1Char(' '))) existingCtrl.chop(1); - if (existingCtrl.startsWith(" ")) + if (existingCtrl.startsWith(QLatin1Char(' '))) existingCtrl.remove(0, 1); m_diLabel->setText(m_currController); qt3dsdm::SValue fullCtrlPropVal = std::make_shared( Q3DStudio::CString::fromQString(existingCtrl)); - Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, QObject::tr("Set Timeline control")) + Q3DStudio::SCOPED_DOCUMENT_EDITOR(*doc, tr("Set Timeline control")) ->SetInstancePropertyValue(timeCtxRoot, ctrldPropertyHandle, fullCtrlPropVal); } @@ -440,18 +459,12 @@ void TimelineToolbar::OnImmediateRefreshInstanceMultiple(qt3dsdm::Qt3DSDMInstanc Q_UNUSED(inInstanceCount) } -// Notify the user about control state change also with timeline dock -// title color change. +// Notify the user about control state change also with timeline dock title color change. void TimelineToolbar::updateTimelineTitleColor(bool controlled) { - QString styleString; - if (controlled) { - styleString = "QDockWidget#timeline { color: " - + QString(CStudioPreferences::dataInputColor().name()) + "; }"; - } else { - styleString = "QDockWidget#timeline { color: " - + QString(CStudioPreferences::textColor().name()) + "; }"; - } + QString styleString = QStringLiteral("QDockWidget#timeline { color: %1; }") + .arg(controlled ? CStudioPreferences::dataInputColor().name() + : CStudioPreferences::textColor().name()); QWidget *timelineDock = parentWidget()->parentWidget()->parentWidget(); timelineDock->setStyleSheet(styleString); -- cgit v1.2.3