timeline: vastly improve behavior when scrolling and zooming
This commit is contained in:
@@ -274,6 +274,10 @@ void TimelineWidget::ScaleChangedEvent(const double &scale)
|
||||
foreach (TimelineAndTrackView* view, views_) {
|
||||
view->view()->SetScale(scale);
|
||||
}
|
||||
|
||||
if (rubberband_.isVisible()) {
|
||||
QMetaObject::invokeMethod(this, &TimelineWidget::ForceUpdateRubberBand, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
@@ -339,6 +343,15 @@ void TimelineWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::SendCatchUpScrollEvent()
|
||||
{
|
||||
super::SendCatchUpScrollEvent();
|
||||
|
||||
if (rubberband_.isVisible()) {
|
||||
this->ForceUpdateRubberBand();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::SelectAll()
|
||||
{
|
||||
QVector<Block*> newly_selected_blocks;
|
||||
@@ -1564,6 +1577,13 @@ void TimelineWidget::MulticamEnabledTriggered(bool e)
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void TimelineWidget::ForceUpdateRubberBand()
|
||||
{
|
||||
if (rubberband_.isVisible()) {
|
||||
this->MoveRubberBandSelect(rubberband_enable_selecting_, rubberband_select_links_);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost)
|
||||
{
|
||||
ghost_items_.append(ghost);
|
||||
@@ -1912,46 +1932,6 @@ void TimelineWidget::UpdateViewports(const Track::Type &type)
|
||||
}
|
||||
}
|
||||
|
||||
QVector<Block *> TimelineWidget::GetBlocksInGlobalRect(const QPoint &p1, const QPoint& p2)
|
||||
{
|
||||
QVector<Block*> blocks_in_rect;
|
||||
|
||||
// Determine which tracks are in the rect
|
||||
for (int i=0; i<views_.size(); i++) {
|
||||
TimelineView* view = views_.at(i)->view();
|
||||
|
||||
// Map global mouse coordinates to viewport
|
||||
QRectF mapped_rect(view->mapToScene(view->viewport()->mapFromGlobal(p1)),
|
||||
view->mapToScene(view->viewport()->mapFromGlobal(p2)));
|
||||
|
||||
// Normalize
|
||||
mapped_rect = mapped_rect.normalized();
|
||||
|
||||
// Get tracks
|
||||
TrackList* track_list = sequence()->track_list(static_cast<Track::Type>(i));
|
||||
|
||||
for (int j=0; j<track_list->GetTrackCount(); j++) {
|
||||
int track_top = view->GetTrackY(j);
|
||||
int track_bottom = track_top + view->GetTrackHeight(j);
|
||||
|
||||
if (!(track_bottom < mapped_rect.top() || track_top > mapped_rect.bottom())) {
|
||||
// This track is in the rect, so we'll iterate through its blocks and see where they start
|
||||
rational left_time = SceneToTime(mapped_rect.left());
|
||||
rational right_time = SceneToTime(mapped_rect.right(), true);
|
||||
|
||||
Track* track = track_list->GetTrackAt(j);
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
if (!(b->out() < left_time || b->in() > right_time)) {
|
||||
blocks_in_rect.append(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blocks_in_rect;
|
||||
}
|
||||
|
||||
bool TimelineWidget::PasteInternal(bool insert)
|
||||
{
|
||||
if (!GetConnectedNode()) {
|
||||
@@ -2039,11 +2019,12 @@ void TimelineWidget::RestoreSplitterState(const QByteArray &state)
|
||||
|
||||
void TimelineWidget::StartRubberBandSelect(const QPoint &global_cursor_start)
|
||||
{
|
||||
drag_origin_ = global_cursor_start;
|
||||
|
||||
// Start rubberband at origin
|
||||
QPoint local_origin = mapFromGlobal(drag_origin_);
|
||||
rubberband_.setGeometry(QRect(local_origin.x(), local_origin.y(), 0, 0));
|
||||
// Store scene positions for each view
|
||||
rubberband_scene_pos_.resize(views_.size());
|
||||
for (int i = 0; i < rubberband_scene_pos_.size(); i++) {
|
||||
TimelineView *v = views_.at(i)->view();
|
||||
rubberband_scene_pos_[i] = v->UnscalePoint(v->mapToScene(v->mapFromGlobal(global_cursor_start)));
|
||||
}
|
||||
|
||||
rubberband_.show();
|
||||
|
||||
@@ -2056,14 +2037,30 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
{
|
||||
QPoint rubberband_now = QCursor::pos();
|
||||
|
||||
rubberband_.setGeometry(QRect(mapFromGlobal(drag_origin_), mapFromGlobal(rubberband_now)).normalized());
|
||||
TimelineView *fv = views_.first()->view();
|
||||
const QPointF &rubberband_scene_start = rubberband_scene_pos_.at(0);
|
||||
QPointF rubberband_now_scaled = fv->UnscalePoint(fv->mapToScene(fv->mapFromGlobal(rubberband_now)));
|
||||
|
||||
QPoint rubberband_local_start = fv->mapTo(this, fv->mapFromScene(fv->ScalePoint(rubberband_scene_start)));
|
||||
QPoint rubberband_local_now = fv->mapTo(this, fv->mapFromScene(fv->ScalePoint(rubberband_now_scaled)));
|
||||
|
||||
rubberband_.setGeometry(QRect(rubberband_local_start, rubberband_local_now).normalized());
|
||||
|
||||
rubberband_enable_selecting_ = enable_selecting;
|
||||
rubberband_select_links_ = select_links;
|
||||
|
||||
if (!enable_selecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current items in rubberband
|
||||
QVector<Block*> items_in_rubberband = GetBlocksInGlobalRect(drag_origin_, rubberband_now);
|
||||
QVector<Block*> items_in_rubberband;
|
||||
|
||||
for (int i = 0; i < views_.size(); i++) {
|
||||
TimelineView *v = views_.at(i)->view();
|
||||
QRectF r = QRectF(v->ScalePoint(rubberband_scene_pos_.at(i)), v->mapToScene(v->mapFromGlobal(rubberband_now))).normalized();
|
||||
items_in_rubberband.append(v->GetItemsAtSceneRect(r));
|
||||
}
|
||||
|
||||
// Reset selection to whatever it was before
|
||||
SetSelections(rubberband_old_selections_, false);
|
||||
|
||||
Reference in New Issue
Block a user