rect select for graph editor

This commit is contained in:
itsmattkc
2019-01-04 16:33:07 +11:00
parent 6c8ec756d8
commit 28fbab2d78
9 changed files with 161 additions and 75 deletions
+4 -2
View File
@@ -110,7 +110,8 @@ SOURCES += \
ui/graphview.cpp \
ui/keyframedrawing.cpp \
ui/clickablelabel.cpp \
project/keyframe.cpp
project/keyframe.cpp \
ui/rectangleselect.cpp
HEADERS += \
mainwindow.h \
@@ -195,7 +196,8 @@ HEADERS += \
ui/graphview.h \
ui/keyframedrawing.h \
ui/clickablelabel.h \
project/keyframe.h
project/keyframe.h \
ui/rectangleselect.h
FORMS +=
+14 -20
View File
@@ -43,12 +43,6 @@ long refactor_frame_number(long framenumber, double source_frame_rate, double ta
return qRound(((double)framenumber/source_frame_rate)*target_frame_rate);
}
void draw_selection_rectangle(QPainter& painter, const QRect& rect) {
painter.setPen(QColor(204, 204, 204));
painter.setBrush(QColor(0, 0, 0, 32));
painter.drawRect(rect);
}
Timeline::Timeline(QWidget *parent) :
QDockWidget(parent),
cursor_frame(0),
@@ -184,7 +178,7 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
can_import = m->ready;
if (m->using_inout) {
double source_fr = 30;
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate;
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate;
default_clip_in = refactor_frame_number(m->in, source_fr, seq->frame_rate);
default_clip_out = refactor_frame_number(m->out, source_fr, seq->frame_rate);
}
@@ -216,7 +210,7 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
switch (medium->get_type()) {
case MEDIA_TYPE_FOOTAGE:
// is video source a still image?
if (m->video_tracks.size() > 0 && m->video_tracks.at(0).infinite_length && m->audio_tracks.size() == 0) {
if (m->video_tracks.size() > 0 && m->video_tracks.at(0).infinite_length && m->audio_tracks.size() == 0) {
g.out = g.in + 100;
} else {
long length = m->get_length_in_frames(seq->frame_rate);
@@ -227,20 +221,20 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
}
for (int j=0;j<m->audio_tracks.size();j++) {
if (m->audio_tracks.at(j).enabled) {
g.track = j;
g.media_stream = m->audio_tracks.at(j).file_index;
ghosts.append(g);
audio_ghosts = true;
}
if (m->audio_tracks.at(j).enabled) {
g.track = j;
g.media_stream = m->audio_tracks.at(j).file_index;
ghosts.append(g);
audio_ghosts = true;
}
}
for (int j=0;j<m->video_tracks.size();j++) {
if (m->video_tracks.at(j).enabled) {
g.track = -1-j;
g.media_stream = m->video_tracks.at(j).file_index;
ghosts.append(g);
video_ghosts = true;
}
if (m->video_tracks.at(j).enabled) {
g.track = -1-j;
g.media_stream = m->video_tracks.at(j).file_index;
ghosts.append(g);
video_ghosts = true;
}
}
break;
case MEDIA_TYPE_SEQUENCE:
-1
View File
@@ -38,7 +38,6 @@ struct FootageStream;
long refactor_frame_number(long framenumber, double source_frame_rate, double target_frame_rate);
int getScreenPointFromFrame(double zoom, long frame);
long getFrameFromScreenPoint(double zoom, int x);
void draw_selection_rectangle(QPainter& painter, const QRect& rect);
bool selection_contains_transition(const Selection& s, Clip* c, int type);
void move_clip(ComboAction *ca, Clip *c, long iin, long iout, long iclip_in, int itrack, bool verify_transitions = true, bool relative = false);
void ripple_clips(ComboAction *ca, Sequence* s, long point, long length, const QVector<int>& ignore = QVector<int>());
+115 -50
View File
@@ -14,12 +14,14 @@
#include "ui/keyframedrawing.h"
#include "project/undo.h"
#include "project/effect.h"
#include "ui/rectangleselect.h"
#include "debug.h"
#define GRAPH_ZOOM_SPEED 0.05
#define GRAPH_SIZE 100
#define BEZIER_HANDLE_SIZE 3
#define BEZIER_LINE_SIZE 2
#define BEZIER_HANDLE_NONE 1
#define BEZIER_HANDLE_PRE 2
@@ -40,7 +42,8 @@ GraphView::GraphView(QWidget* parent) :
zoom(1.0),
row(NULL),
moved_keys(false),
current_handle(BEZIER_HANDLE_NONE)
current_handle(BEZIER_HANDLE_NONE),
rect_select(false)
{
setMouseTracking(true);
setFocusPolicy(Qt::ClickFocus);
@@ -114,7 +117,7 @@ void GraphView::paintEvent(QPaintEvent *event) {
// draw keyframes
if (row != NULL) {
QPen line_pen;
line_pen.setWidth(2);
line_pen.setWidth(BEZIER_LINE_SIZE);
for (int i=row->fieldCount()-1;i>=0;i--) {
EffectField* field = row->field(i);
@@ -209,7 +212,15 @@ void GraphView::paintEvent(QPaintEvent *event) {
p.drawEllipse(post_point, BEZIER_HANDLE_SIZE, BEZIER_HANDLE_SIZE);
}
draw_keyframe(p, key.type, key_x, key_y, (selected_keys.contains(sorted_keys.at(j)) && selected_keys_fields.contains(i)));
bool selected = false;
for (int k=0;k<selected_keys.size();k++) {
if (selected_keys.at(k) == sorted_keys.at(j) && selected_keys_fields.at(k) == i) {
selected = true;
break;
}
}
draw_keyframe(p, key.type, key_x, key_y, selected);
}
}
}
@@ -219,6 +230,11 @@ void GraphView::paintEvent(QPaintEvent *event) {
p.setPen(Qt::red);
int playhead_x = get_screen_x(panel_sequence_viewer->seq->playhead);
p.drawLine(playhead_x, 0, playhead_x, height());
if (rect_select) {
draw_selection_rectangle(p, QRect(rect_select_x, rect_select_y, rect_select_w, rect_select_h));
p.setBrush(Qt::NoBrush);
}
}
p.setPen(Qt::white);
@@ -230,15 +246,16 @@ void GraphView::paintEvent(QPaintEvent *event) {
}
void GraphView::mousePressEvent(QMouseEvent *event) {
mousedown = true;
start_x = event->pos().x();
start_y = event->pos().y();
// selecting
int sel_key = -1;
int sel_key_field = -1;
current_handle = BEZIER_HANDLE_NONE;
if (row != NULL) {
mousedown = true;
start_x = event->pos().x();
start_y = event->pos().y();
// selecting
int sel_key = -1;
int sel_key_field = -1;
current_handle = BEZIER_HANDLE_NONE;
for (int i=0;i<row->fieldCount();i++) {
EffectField* field = row->field(i);
if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
@@ -285,49 +302,40 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
}
if (sel_key > -1) break;
}
}
bool already_selected = false;
for (int i=0;i<selected_keys.size();i++) {
if (selected_keys.at(i) == sel_key && selected_keys_fields.at(i) == sel_key_field) {
if ((event->modifiers() & Qt::ShiftModifier)) {
selected_keys.removeAt(i);
selected_keys_fields.removeAt(i);
}
already_selected = true;
break;
}
}
if (!already_selected) {
if (!(event->modifiers() & Qt::ShiftModifier)) {
selected_keys.clear();
selected_keys_fields.clear();
}
bool already_selected = false;
if (sel_key > -1) {
selected_keys.append(sel_key);
selected_keys_fields.append(sel_key_field);
for (int i=0;i<selected_keys.size();i++) {
if (selected_keys.at(i) == sel_key && selected_keys_fields.at(i) == sel_key_field) {
if ((event->modifiers() & Qt::ShiftModifier)) {
selected_keys.removeAt(i);
selected_keys_fields.removeAt(i);
}
already_selected = true;
break;
}
}
}
}
selected_keys_old_vals.clear();
selected_keys_old_doubles.clear();
int selected_key_type = -1;
for (int i=0;i<selected_keys.size();i++) {
const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
selected_keys_old_vals.append(key.time);
selected_keys_old_doubles.append(key.data.toDouble());
if (selected_key_type == -1) {
selected_key_type = key.type;
} else if (selected_key_type != key.type) {
selected_key_type = -2;
if (!already_selected) {
if (!(event->modifiers() & Qt::ShiftModifier)) {
selected_keys.clear();
selected_keys_fields.clear();
}
if (sel_key > -1) {
selected_keys.append(sel_key);
selected_keys_fields.append(sel_key_field);
} else {
rect_select = true;
rect_select_x = event->pos().x();
rect_select_y = event->pos().y();
rect_select_w = 0;
rect_select_h = 0;
rect_select_offset = selected_keys.size();
}
}
selection_update();
}
update();
emit selection_changed(selected_keys.size() > 0, selected_key_type);
}
void GraphView::mouseMoveEvent(QMouseEvent *event) {
@@ -338,6 +346,35 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
start_x = event->pos().x();
start_y = event->pos().y();
update();
} else if (rect_select) {
rect_select_w = event->pos().x() - rect_select_x;
rect_select_h = event->pos().y() - rect_select_y;
selected_keys.resize(rect_select_offset);
selected_keys_fields.resize(rect_select_offset);
for (int i=0;i<row->fieldCount();i++) {
EffectField* f = row->field(i);
for (int j=0;j<f->keyframes.size();j++) {
bool already_selected = false;
for (int k=0;k<selected_keys.size();k++) {
if (selected_keys.at(k) == j && selected_keys_fields.at(k) == i) {
already_selected = true;
break;
}
}
if (!already_selected) {
QPoint key_screen_point(get_screen_x(f->keyframes.at(j).time), get_screen_y(f->keyframes.at(j).data.toDouble()));
QRect select_rect(rect_select_x, rect_select_y, rect_select_w, rect_select_h);
if (select_rect.contains(key_screen_point)) {
selected_keys.append(j);
selected_keys_fields.append(i);
}
}
}
}
update();
} else {
bool shift = (event->modifiers() & Qt::ShiftModifier);
switch (current_handle) {
@@ -409,6 +446,11 @@ void GraphView::mouseReleaseEvent(QMouseEvent *event) {
}
moved_keys = false;
mousedown = false;
if (rect_select) {
rect_select = false;
selection_update();
update();
}
}
void GraphView::wheelEvent(QWheelEvent *event) {
@@ -496,3 +538,26 @@ int GraphView::get_screen_x(double d) {
int GraphView::get_screen_y(double d) {
return height() + y_scroll - d*zoom;
}
void GraphView::selection_update() {
selected_keys_old_vals.clear();
selected_keys_old_doubles.clear();
int selected_key_type = -1;
for (int i=0;i<selected_keys.size();i++) {
const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
selected_keys_old_vals.append(key.time);
selected_keys_old_doubles.append(key.data.toDouble());
if (selected_key_type == -1) {
selected_key_type = key.type;
} else if (selected_key_type != key.type) {
selected_key_type = -2;
}
}
update();
emit selection_changed(selected_keys.size() > 0, selected_key_type);
}
+9
View File
@@ -43,6 +43,8 @@ private:
int get_screen_x(double);
int get_screen_y(double);
void selection_update();
QVector<bool> field_visibility;
QVector<int> selected_keys;
@@ -61,6 +63,13 @@ private:
void draw_line_text(QPainter &p, bool vert, int line_no, int line_pos, int next_line_pos);
EffectRow* row;
bool rect_select;
int rect_select_x;
int rect_select_y;
int rect_select_w;
int rect_select_h;
int rect_select_offset;
private slots:
void show_context_menu(const QPoint& pos);
void reset_view();
+1
View File
@@ -15,6 +15,7 @@
#include "ui/keyframedrawing.h"
#include "ui/clickablelabel.h"
#include "ui/resizablescrollbar.h"
#include "ui/rectangleselect.h"
#include <QMouseEvent>
#include <QtMath>
+7
View File
@@ -0,0 +1,7 @@
#include "rectangleselect.h"
void draw_selection_rectangle(QPainter& painter, const QRect& rect) {
painter.setPen(QColor(204, 204, 204));
painter.setBrush(QColor(0, 0, 0, 32));
painter.drawRect(rect);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef RECTANGLESELECT_H
#define RECTANGLESELECT_H
#include <QPainter>
void draw_selection_rectangle(QPainter& painter, const QRect& rect);
#endif // RECTANGLESELECT_H
+3 -2
View File
@@ -21,6 +21,7 @@
#include "ui/resizablescrollbar.h"
#include "dialogs/newsequencedialog.h"
#include "mainwindow.h"
#include "ui/rectangleselect.h"
#include "debug.h"
#include "project/effect.h"
@@ -1272,9 +1273,9 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
Clip* c = NULL;
if (g.clip != -1) c = sequence->clips.at(g.clip);
const FootageStream* ms = NULL;
const FootageStream* ms = NULL;
if (g.clip != -1 && c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) {
ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream);
ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream);
}
// validate ghosts for trimming