summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahmoud Badri <mahmoud.badri@qt.io>2019-08-30 10:38:06 +0300
committerMahmoud Badri <mahmoud.badri@qt.io>2019-09-02 10:45:49 +0300
commit747f520cc2e16a97d38c3caf28ecb1880ae1aa4c (patch)
tree67ef832b1557e1999fc2e79590bf8ab0189c1d0c
parentcd88fefac16b842d938f154d574330fcc0ed2432 (diff)
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 <miikka.heikkinen@qt.io>
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Inspector/VariantsGroupModel.cpp2
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/RowManager.cpp8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineConstants.h6
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.cpp14
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineGraphicsScene.h1
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/TimelineWidget.cpp4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.cpp17
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/PlayHead.h3
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimeline.cpp8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/RowTimelinePropertyGraph.cpp4
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.cpp196
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/Ruler.h8
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/TimelineGraphicsView/ui/TimelineToolbar.cpp57
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<RowTree *>(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<RowTree *>(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<RowTimeline *>(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 <QtGui/qpainter.h>
#include <QtWidgets/qwidget.h>
+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 <QtWidgets/qpushbutton.h>
#include <QtWidgets/qshortcut.h>
+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<QSlider *>(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<QString>(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<qt3dsdm::CDataStr>(
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);