From ba0401ff060e4b67aa62f88a17ea0c521bf04d99 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:06:53 -0700 Subject: [PATCH] timeline: add optional showing clip while dragging --- app/config/config.cpp | 1 + .../timelinewidget/view/timelineview.cpp | 258 ++++++++++-------- app/widget/timelinewidget/view/timelineview.h | 10 + 3 files changed, 156 insertions(+), 113 deletions(-) diff --git a/app/config/config.cpp b/app/config/config.cpp index edf70db0b..d6ccf94f9 100644 --- a/app/config/config.cpp +++ b/app/config/config.cpp @@ -96,6 +96,7 @@ void Config::SetDefaults() SetEntryInternal(QStringLiteral("AutoMergeTracks"), NodeValue::kBoolean, true); SetEntryInternal(QStringLiteral("UseSliderLadders"), NodeValue::kBoolean, true); SetEntryInternal(QStringLiteral("ShowWelcomeDialog"), NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("ShowClipWhileDragging"), NodeValue::kBoolean, true); SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000); diff --git a/app/widget/timelinewidget/view/timelineview.cpp b/app/widget/timelinewidget/view/timelineview.cpp index df0386016..415427334 100644 --- a/app/widget/timelinewidget/view/timelineview.cpp +++ b/app/widget/timelinewidget/view/timelineview.cpp @@ -281,14 +281,31 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect) // Draw ghosts if (ghosts_ && !ghosts_->isEmpty()) { - painter->setPen(QPen(Qt::yellow, 2)); - painter->setBrush(Qt::NoBrush); - foreach (TimelineViewGhostItem* ghost, (*ghosts_)) { if (ghost->GetTrack().type() == connected_track_list_->type() && !ghost->IsInvisible()) { int track_index = ghost->GetAdjustedTrack().index(); + Block *attached = Node::ValueToPtr(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)); + + if (attached && Config::Current()[QStringLiteral("ShowClipWhileDragging")].toBool()) { + int adj_track = ghost->GetAdjustedTrack().index(); + qreal track_top = GetTrackY(adj_track); + qreal track_height = GetTrackHeight(adj_track); + + qreal old_opacity = painter->opacity(); + painter->setOpacity(0.5); + + rational in = ghost->GetAdjustedIn(), out = ghost->GetAdjustedOut(); + DrawBlock(painter, false, attached, track_top, track_height, in, out); + DrawBlock(painter, true, attached, track_top, track_height, in, out); + + painter->setOpacity(old_opacity); + } + + painter->setPen(QPen(Qt::yellow, 2)); + painter->setBrush(Qt::NoBrush); + painter->drawRect(TimeToScene(ghost->GetAdjustedIn()), GetTrackY(track_index), TimeToScene(ghost->GetAdjustedLength()), @@ -390,123 +407,20 @@ TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::Mou void TimelineView::DrawBlocks(QPainter *painter, bool foreground) { - qreal left_bound = horizontalScrollBar()->value(); - qreal right_bound = viewport()->width() + horizontalScrollBar()->value(); - rational start_time = SceneToTime(left_bound); - rational end_time = SceneToTime(right_bound); + + rational start_time = SceneToTime(GetTimelineLeftBound()); + rational end_time = SceneToTime(GetTimelineRightBound()); foreach (Track* track, connected_track_list_->GetTracks()) { // Get first visible block in this track Block* block = track->NearestBlockBeforeOrAt(start_time); + qreal track_top = GetTrackY(track->Index()); + qreal track_height = GetTrackHeight(track->Index()); + while (block) { - if (dynamic_cast(block) || dynamic_cast(block)) { - - qreal block_in = TimeToScene(block->in()); - - qreal block_left = qMax(left_bound, block_in); - qreal block_right = qMin(right_bound, TimeToScene(block->out())) - 1; - qreal block_top = GetTrackY(track->Index()); - qreal block_height = GetTrackHeight(track->Index()); - - QRectF r(block_left, - block_top, - block_right - block_left, - block_height); - - QColor shadow_color = block->color().toQColor().darker(); - - QFontMetrics fm = fontMetrics(); - int text_height = fm.height(); - int text_padding = text_height/4; // This ties into the track minimum height being 1.5 - int text_total_height = text_height + text_padding + text_padding; - - if (foreground) { - painter->setBrush(Qt::NoBrush); - - QString using_label = block->GetLabel().isEmpty() ? block->Name() : block->GetLabel(); - - QRectF text_rect = r.adjusted(text_padding, text_padding, -text_padding, -text_padding); - painter->setPen(block->is_enabled() ? ColorCoding::GetUISelectorColor(block->color()) : Qt::lightGray); - painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignTop, using_label); - - if (block->HasLinks()) { - int text_width = qMin(qRound(text_rect.width()), - QtUtils::QFontMetricsWidth(fm, using_label)); - - int underline_y = text_rect.y() + text_height; - - painter->drawLine(text_rect.x(), underline_y, text_width + text_rect.x(), underline_y); - } - - qreal line_bottom = block_top+block_height-1; - - painter->setPen(Qt::white); - painter->drawLine(block_left, block_top, block_right, block_top); - painter->drawLine(block_left, block_top, block_left, line_bottom); - - painter->setPen(shadow_color); - painter->drawLine(block_left, line_bottom, block_right, line_bottom); - painter->drawLine(block_right, line_bottom, block_right, block_top); - } else { - painter->setPen(Qt::NoPen); - painter->setBrush(block->is_enabled() ? block->brush(block_top, block_top + block_height) : Qt::gray); - painter->drawRect(r); - - // Draw waveform - if (show_waveforms_) { - if (ClipBlock *clip = dynamic_cast(block)) { - QRect waveform_rect = r.adjusted(0, text_total_height, 0, 0).toRect(); - painter->setPen(shadow_color); - AudioVisualWaveform::DrawWaveform(painter, waveform_rect, this->GetScale(), clip->waveform(), - SceneToTime(block_left - block_in, GetScale(), connected_track_list_->parent()->GetAudioParams().sample_rate_as_time_base())); - } - } - - // For transitions, show lines representing a transition - if (TransitionBlock* transition = dynamic_cast(block)) { - QVector lines; - - if (transition->connected_in_block()) { - lines.append(QLineF(r.bottomLeft(), r.topRight())); - } - - if (transition->connected_out_block()) { - lines.append(QLineF(r.topLeft(), r.bottomRight())); - } - - painter->setPen(shadow_color); - painter->drawLines(lines); - } - - if (transition_overlay_out_ == block || transition_overlay_in_ == block) { - QRectF transition_overlay_rect = r; - - qreal transition_overlay_width = TimeToScene(block->length()) * 0.5; - if (transition_overlay_out_ && transition_overlay_in_) { - // This is a dual transition, use the smallest width - Block *other_block = (transition_overlay_out_ == block) ? transition_overlay_in_ : transition_overlay_out_; - - qreal other_width = TimeToScene(other_block->length()) * 0.5; - - transition_overlay_width = qMin(transition_overlay_width, other_width); - } - - if (transition_overlay_out_ == block) { - transition_overlay_rect.setLeft(transition_overlay_rect.right() - transition_overlay_width); - } else { - transition_overlay_rect.setRight(transition_overlay_rect.left() + transition_overlay_width); - } - - painter->setPen(Qt::NoPen); - painter->setBrush(QColor(0, 0, 0, 64)); - - painter->drawRect(transition_overlay_rect); - } - } - - } + DrawBlock(painter, foreground, block, track_top, track_height); if (block->out() >= end_time) { // Rest of the clips are offscreen, can break loop now @@ -518,6 +432,114 @@ void TimelineView::DrawBlocks(QPainter *painter, bool foreground) } } +void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, qreal block_top, qreal block_height, const rational &in, const rational &out) +{ + if (dynamic_cast(block) || dynamic_cast(block)) { + + qreal block_in = TimeToScene(in); + + qreal block_left = qMax(GetTimelineLeftBound(), block_in); + qreal block_right = qMin(GetTimelineRightBound(), TimeToScene(out)) - 1; + + QRectF r(block_left, + block_top, + block_right - block_left, + block_height); + + QColor shadow_color = block->color().toQColor().darker(); + + QFontMetrics fm = fontMetrics(); + int text_height = fm.height(); + int text_padding = text_height/4; // This ties into the track minimum height being 1.5 + int text_total_height = text_height + text_padding + text_padding; + + if (foreground) { + painter->setBrush(Qt::NoBrush); + + QString using_label = block->GetLabel().isEmpty() ? block->Name() : block->GetLabel(); + + QRectF text_rect = r.adjusted(text_padding, text_padding, -text_padding, -text_padding); + painter->setPen(block->is_enabled() ? ColorCoding::GetUISelectorColor(block->color()) : Qt::lightGray); + painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignTop, using_label); + + if (block->HasLinks()) { + int text_width = qMin(qRound(text_rect.width()), + QtUtils::QFontMetricsWidth(fm, using_label)); + + int underline_y = text_rect.y() + text_height; + + painter->drawLine(text_rect.x(), underline_y, text_width + text_rect.x(), underline_y); + } + + qreal line_bottom = block_top+block_height-1; + + painter->setPen(Qt::white); + painter->drawLine(block_left, block_top, block_right, block_top); + painter->drawLine(block_left, block_top, block_left, line_bottom); + + painter->setPen(shadow_color); + painter->drawLine(block_left, line_bottom, block_right, line_bottom); + painter->drawLine(block_right, line_bottom, block_right, block_top); + } else { + painter->setPen(Qt::NoPen); + painter->setBrush(block->is_enabled() ? block->brush(block_top, block_top + block_height) : Qt::gray); + painter->drawRect(r); + + // Draw waveform + if (show_waveforms_) { + if (ClipBlock *clip = dynamic_cast(block)) { + QRect waveform_rect = r.adjusted(0, text_total_height, 0, 0).toRect(); + painter->setPen(shadow_color); + AudioVisualWaveform::DrawWaveform(painter, waveform_rect, this->GetScale(), clip->waveform(), + SceneToTime(block_left - block_in, GetScale(), connected_track_list_->parent()->GetAudioParams().sample_rate_as_time_base())); + } + } + + // For transitions, show lines representing a transition + if (TransitionBlock* transition = dynamic_cast(block)) { + QVector lines; + + if (transition->connected_in_block()) { + lines.append(QLineF(r.bottomLeft(), r.topRight())); + } + + if (transition->connected_out_block()) { + lines.append(QLineF(r.topLeft(), r.bottomRight())); + } + + painter->setPen(shadow_color); + painter->drawLines(lines); + } + + if (transition_overlay_out_ == block || transition_overlay_in_ == block) { + QRectF transition_overlay_rect = r; + + qreal transition_overlay_width = TimeToScene(block->length()) * 0.5; + if (transition_overlay_out_ && transition_overlay_in_) { + // This is a dual transition, use the smallest width + Block *other_block = (transition_overlay_out_ == block) ? transition_overlay_in_ : transition_overlay_out_; + + qreal other_width = TimeToScene(other_block->length()) * 0.5; + + transition_overlay_width = qMin(transition_overlay_width, other_width); + } + + if (transition_overlay_out_ == block) { + transition_overlay_rect.setLeft(transition_overlay_rect.right() - transition_overlay_width); + } else { + transition_overlay_rect.setRight(transition_overlay_rect.left() + transition_overlay_width); + } + + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + + painter->drawRect(transition_overlay_rect); + } + } + + } +} + int TimelineView::GetHeightOfAllTracks() const { if (connected_track_list_) { @@ -531,6 +553,16 @@ int TimelineView::GetHeightOfAllTracks() const } } +qreal TimelineView::GetTimelineLeftBound() const +{ + return horizontalScrollBar()->value(); +} + +qreal TimelineView::GetTimelineRightBound() const +{ + return GetTimelineLeftBound() + viewport()->width(); +} + int TimelineView::GetTrackY(int track_index) const { if (!connected_track_list_ || !connected_track_list_->GetTrackCount()) { diff --git a/app/widget/timelinewidget/view/timelineview.h b/app/widget/timelinewidget/view/timelineview.h index 5a9f01282..7770f8418 100644 --- a/app/widget/timelinewidget/view/timelineview.h +++ b/app/widget/timelinewidget/view/timelineview.h @@ -124,10 +124,20 @@ private: void DrawBlocks(QPainter* painter, bool foreground); + void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top, qreal height, const rational &in, const rational &out); + void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top, qreal height) + { + DrawBlock(painter, foreground, block, top, height, block->in(), block->out()); + } + int GetHeightOfAllTracks() const; void UpdatePlayheadRect(); + qreal GetTimelineLeftBound() const; + + qreal GetTimelineRightBound() const; + QHash* selections_; QVector* ghosts_;