big progress on graph editor

This commit is contained in:
itsmattkc
2018-12-28 22:06:38 +11:00
parent c3ea55faf4
commit e101739214
25 changed files with 607 additions and 84 deletions
+13
View File
@@ -0,0 +1,13 @@
#include "clickablelabel.h"
ClickableLabel::ClickableLabel(QWidget *parent, Qt::WindowFlags f) :
QLabel(parent, f)
{}
ClickableLabel::ClickableLabel(const QString &text, QWidget *parent, Qt::WindowFlags f) :
QLabel(text, parent, f)
{}
void ClickableLabel::mousePressEvent(QMouseEvent *) {
emit clicked();
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef CLICKABLELABEL_H
#define CLICKABLELABEL_H
#include <QLabel>
class ClickableLabel : public QLabel {
Q_OBJECT
public:
ClickableLabel(QWidget * parent = 0, Qt::WindowFlags f = 0);
ClickableLabel(const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0);
void mousePressEvent(QMouseEvent *ev);
signals:
void clicked();
};
#endif // CLICKABLELABEL_H
+200 -7
View File
@@ -1,16 +1,209 @@
#include "graphview.h"
#include <QPainter>
#include <QMouseEvent>
GraphView::GraphView(QWidget* parent) {}
#include "panels/panels.h"
#include "panels/timeline.h"
#include "panels/viewer.h"
#include "project/sequence.h"
#include "project/effectrow.h"
#include "project/effectfield.h"
#include "ui/keyframedrawing.h"
#include "debug.h"
#define GRAPH_ZOOM_SPEED 0.05
#define GRAPH_SIZE 100
QColor get_curve_color(int index, int length) {
QColor c;
int hue = (double(index)/double(length))*255;
c.setHsv(hue, 255, 255);
return c;
}
GraphView::GraphView(QWidget* parent) :
QWidget(parent),
x_scroll(0),
y_scroll(0),
mousedown(false),
zoom(1.0),
row(NULL)
{
setMouseTracking(true);
}
void GraphView::paintEvent(QPaintEvent *event) {
QPainter p(this);
QPainter p(this);
p.setPen(Qt::white);
if (panel_sequence_viewer->seq != NULL) {
// draw lines
//int graph_size = GRAPH_SIZE*zoom;
bool draw_text = true;//(fontMetrics().height() < graph_size && fontMetrics().width("0000") < graph_size);
QRect border = rect();
border.setWidth(border.width()-1);
border.setHeight(border.height()-1);
p.drawRect(border);
p.setPen(Qt::gray);
int i = 0;
while (true) {
int line_x = (i*GRAPH_SIZE*zoom) - x_scroll;
if (line_x >= width()) {
break;
}
if (line_x >= 0) {
if (line_x > 0) p.drawLine(line_x, 0, line_x, height());
if (draw_text) p.drawText(QRect(line_x, height()-50, 50, 50), Qt::AlignBottom | Qt::AlignLeft, QString::number(i*GRAPH_SIZE));
}
i++;
}
i = 0;
while (true) {
int line_y = height() - (i*GRAPH_SIZE*zoom) + y_scroll;
if (line_y <= 0) {
break;
}
if (line_y <= height()) {
if (line_y < height()) p.drawLine(0, line_y, width(), line_y);
if (draw_text) p.drawText(QRect(0, line_y-50, 50, 50), Qt::AlignBottom | Qt::AlignLeft, QString::number(i*GRAPH_SIZE));
}
i++;
}
// draw keyframes
if (row != NULL) {
QPen line_pen;
line_pen.setWidth(2);
// sort keyframes by time
QVector<int> sorted_keys;
for (int i=0;i<row->keyframe_times.size();i++) {
bool inserted = false;
for (int j=0;j<sorted_keys.size();j++) {
if (row->keyframe_times.at(sorted_keys.at(j)) > row->keyframe_times.at(i)) {
sorted_keys.insert(j, i);
inserted = true;
break;
}
}
if (!inserted) {
sorted_keys.append(i);
}
}
int last_key_x, last_key_y;
for (int i=0;i<row->fieldCount();i++) {
EffectField* field = row->field(i);
if (field->type == EFFECT_FIELD_DOUBLE) {
for (int j=0;j<sorted_keys.size();j++) {
int key_index = sorted_keys.at(j);
int key_x = get_screen_x(row->keyframe_times.at(key_index));
int key_y = get_screen_y(field->keyframe_data.at(key_index).toDouble());
line_pen.setColor(get_curve_color(i, row->fieldCount()));
p.setPen(line_pen);
if (key_index == 0) {
p.drawLine(0, key_y, key_x, key_y);
} else {
p.drawLine(last_key_x, last_key_y, key_x, key_y);
}
last_key_x = key_x;
last_key_y = key_y;
}
for (int j=0;j<sorted_keys.size();j++) {
int key_index = sorted_keys.at(j);
int key_x = get_screen_x(row->keyframe_times.at(key_index));
int key_y = get_screen_y(field->keyframe_data.at(key_index).toDouble());
draw_keyframe(p, row->keyframe_types.at(key_index), key_x, key_y, false);
}
p.setBrush(Qt::NoBrush);
}
}
}
// draw playhead
p.setPen(Qt::red);
int playhead_x = get_screen_x(panel_sequence_viewer->seq->playhead);
p.drawLine(playhead_x, 0, playhead_x, height());
}
p.setPen(Qt::white);
QRect border = rect();
border.setWidth(border.width()-1);
border.setHeight(border.height()-1);
p.drawRect(border);
}
void GraphView::mousePressEvent(QMouseEvent *event) {
mousedown = true;
start_x = event->pos().x();
start_y = event->pos().y();
}
void GraphView::mouseMoveEvent(QMouseEvent *event) {
if (mousedown) {
if (event->buttons() & Qt::MiddleButton || panel_timeline->tool == TIMELINE_TOOL_HAND) {
set_scroll_x(x_scroll + start_x - event->pos().x());
set_scroll_y(y_scroll + event->pos().y() - start_y);
start_x = event->pos().x();
start_y = event->pos().y();
update();
}
}
}
void GraphView::mouseReleaseEvent(QMouseEvent *event) {
mousedown = false;
}
void GraphView::wheelEvent(QWheelEvent *event) {
bool redraw = false;
bool shift = (event->modifiers() & Qt::ShiftModifier); // scroll instead of zoom
bool alt = (event->modifiers() & Qt::AltModifier); // horiz scroll instead of vert scroll
if (shift) {
// scroll
set_scroll_x(x_scroll + event->angleDelta().x()/10);
set_scroll_y(y_scroll + event->angleDelta().y()/10);
redraw = true;
} else {
// set zoom
if (event->angleDelta().y() != 0) {
double zoom_diff = (GRAPH_ZOOM_SPEED*zoom);
if (event->angleDelta().y() < 0) zoom_diff = -zoom_diff;
zoom += zoom_diff;
emit zoom_changed(zoom);
redraw = true;
}
}
if (redraw) {
update();
}
}
void GraphView::set_row(EffectRow *r) {
row = r;
update();
}
void GraphView::set_scroll_x(int s) {
x_scroll = s;//qMax(0, s);
dout << x_scroll;
emit x_scroll_changed(x_scroll);
}
void GraphView::set_scroll_y(int s) {
y_scroll = s;//qMax(0, s);
emit y_scroll_changed(y_scroll);
}
int GraphView::get_screen_x(double d) {
return (d*zoom) - x_scroll;
}
int GraphView::get_screen_y(double d) {
return height() + y_scroll - d*zoom;
}
+30
View File
@@ -3,11 +3,41 @@
#include <QWidget>
class EffectRow;
QColor get_curve_color(int index, int length);
class GraphView : public QWidget {
Q_OBJECT
public:
GraphView(QWidget* parent = 0);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void set_row(EffectRow* r);
signals:
void x_scroll_changed(int);
void y_scroll_changed(int);
void zoom_changed(double);
private:
int x_scroll;
int y_scroll;
bool mousedown;
int start_x;
int start_y;
double zoom;
void set_scroll_x(int s);
void set_scroll_y(int s);
int get_screen_x(double);
int get_screen_y(double);
EffectRow* row;
};
#endif // GRAPHVIEW_H
+26
View File
@@ -0,0 +1,26 @@
#include "keyframedrawing.h"
#include "project/effect.h"
#define KEYFRAME_POINT_COUNT 4
void draw_keyframe(QPainter &p, int type, int x, int y, bool darker) {
int color = (darker) ? 100 : 160;
p.setPen(QColor(0, 0, 0));
p.setBrush(QColor(color, color, color));
switch (type) {
case KEYFRAME_TYPE_LINEAR:
{
QPoint points[KEYFRAME_POINT_COUNT] = {QPoint(x-KEYFRAME_SIZE, y), QPoint(x, y-KEYFRAME_SIZE), QPoint(x+KEYFRAME_SIZE, y), QPoint(x, y+KEYFRAME_SIZE)};
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
}
break;
case KEYFRAME_TYPE_BEZIER:
p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE);
break;
case KEYFRAME_TYPE_HOLD:
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
break;
}
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef KEYFRAMEDRAWING_H
#define KEYFRAMEDRAWING_H
#include <QPainter>
#define KEYFRAME_SIZE 6
void draw_keyframe(QPainter &p, int type, int x, int y, bool darker);
#endif // KEYFRAMEDRAWING_H
+21 -6
View File
@@ -2,15 +2,22 @@
#include <QHBoxLayout>
#include <QPushButton>
#include <QApplication>
#include <QDesktopWidget>
KeyframeNavigator::KeyframeNavigator(QWidget *parent) : QWidget(parent) {
QSize icon_size(12, 12);
QSize button_size(20, 20);
int icon_size_val = 8*QApplication::desktop()->devicePixelRatio();
int clock_size_val = 12*QApplication::desktop()->devicePixelRatio();
int button_size_val = 20*QApplication::desktop()->devicePixelRatio();
QSize icon_size(icon_size_val, icon_size_val);
QSize clock_size(clock_size_val, clock_size_val);
QSize button_size(button_size_val, button_size_val);
key_controls = new QHBoxLayout();
key_controls->setSpacing(0);
key_controls->setMargin(0);
key_controls->addStretch();
//key_controls->addStretch();
setLayout(key_controls);
@@ -21,6 +28,7 @@ KeyframeNavigator::KeyframeNavigator(QWidget *parent) : QWidget(parent) {
left_key_nav->setVisible(false);
key_controls->addWidget(left_key_nav);
connect(left_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(goto_previous_key()));
connect(left_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
key_addremove = new QPushButton();
key_addremove->setIcon(QIcon(":/icons/diamond.png"));
@@ -29,6 +37,7 @@ KeyframeNavigator::KeyframeNavigator(QWidget *parent) : QWidget(parent) {
key_addremove->setVisible(false);
key_controls->addWidget(key_addremove);
connect(key_addremove, SIGNAL(clicked(bool)), this, SIGNAL(toggle_key()));
connect(key_addremove, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
right_key_nav = new QPushButton();
right_key_nav->setIcon(QIcon(":/icons/tri-right.png"));
@@ -37,20 +46,26 @@ KeyframeNavigator::KeyframeNavigator(QWidget *parent) : QWidget(parent) {
right_key_nav->setVisible(false);
key_controls->addWidget(right_key_nav);
connect(right_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(goto_next_key()));
connect(right_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
keyframe_enable = new QPushButton(QIcon(":/icons/clock.png"), "");
keyframe_enable->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
keyframe_enable->setMaximumSize(button_size);
keyframe_enable->setIconSize(icon_size);
keyframe_enable->setIconSize(clock_size);
keyframe_enable->setCheckable(true);
keyframe_enable->setToolTip("Enable Keyframes");
connect(keyframe_enable, SIGNAL(clicked(bool)), this, SIGNAL(set_keyframe_enabled(bool)));
connect(keyframe_enable, SIGNAL(clicked(bool)), this, SIGNAL(keyframe_enabled_changed(bool)));
connect(keyframe_enable, SIGNAL(toggled(bool)), this, SLOT(keyframe_ui_enabled(bool)));
connect(keyframe_enable, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
key_controls->addWidget(keyframe_enable);
}
void KeyframeNavigator::enable_keyframes(bool b) {
keyframe_enable->setChecked(b);
keyframe_enable->setChecked(b);
}
void KeyframeNavigator::enable_keyframe_toggle(bool b) {
keyframe_enable->setVisible(b);
}
void KeyframeNavigator::keyframe_ui_enabled(bool enabled) {
+3 -1
View File
@@ -12,11 +12,13 @@ class KeyframeNavigator : public QWidget
public:
KeyframeNavigator(QWidget* parent = 0);
void enable_keyframes(bool);
void enable_keyframe_toggle(bool);
signals:
void goto_previous_key();
void toggle_key();
void goto_next_key();
void set_keyframe_enabled(bool);
void keyframe_enabled_changed(bool);
void clicked();
private slots:
void keyframe_ui_enabled(bool);
private:
+19 -34
View File
@@ -12,16 +12,14 @@
#include "ui/viewerwidget.h"
#include "project/sequence.h"
#include "panels/grapheditor.h"
#include "ui/keyframedrawing.h"
#include "ui_effectcontrols.h"
#include "ui/clickablelabel.h"
#include <QLabel>
#include <QMouseEvent>
#include <QtMath>
#include <QMenu>
#define KEYFRAME_SIZE 6
#define KEYFRAME_POINT_COUNT 4
long KeyframeView::adjust_row_keyframe(EffectRow* row, long time) {
return time-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in);
}
@@ -36,7 +34,7 @@ KeyframeView::KeyframeView(QWidget *parent) :
select_rect(false),
x_scroll(0),
y_scroll(0),
scroll_drag(false)
scroll_drag(false)
{
setFocusPolicy(Qt::ClickFocus);
setMouseTracking(true);
@@ -73,7 +71,7 @@ void KeyframeView::menu_set_key_type(QAction* a) {
ca->append(new SetInt(&selected_rows.at(i)->keyframe_types[selected_keyframes.at(i)], a->data().toInt()));
}
undo_stack.push(ca);
update();
update_keys();
}
}
@@ -101,7 +99,7 @@ void KeyframeView::paintEvent(QPaintEvent*) {
for (int j=0;j<e->row_count();j++) {
EffectRow* row = e->row(j);
QLabel* label = row->label;
ClickableLabel* label = row->label;
QWidget* contents = e->container->contents;
int keyframe_y = label->y() + (label->height()>>1) + mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - e->container->title_bar->height()/* - y_scroll*/;
@@ -153,6 +151,11 @@ bool KeyframeView::keyframeIsSelected(EffectRow *row, int keyframe) {
return false;
}
void KeyframeView::update_keys() {
// panel_graph_editor->update_panel();
update();
}
void KeyframeView::delete_selected_keyframes() {
KeyframeDelete* kd = new KeyframeDelete();
bool del = false;
@@ -165,7 +168,7 @@ void KeyframeView::delete_selected_keyframes() {
selected_keyframes.clear();
selected_rows.clear();
update();
update_keys();
panel_sequence_viewer->viewer_widget->update();
} else {
delete kd;
@@ -174,33 +177,12 @@ void KeyframeView::delete_selected_keyframes() {
void KeyframeView::set_x_scroll(int s) {
x_scroll = s;
update();
update_keys();
}
void KeyframeView::set_y_scroll(int s) {
y_scroll = s;
update();
}
void KeyframeView::draw_keyframe(QPainter &p, int type, int x, int y, bool darker) {
int color = (darker) ? 100 : 160;
p.setPen(QColor(0, 0, 0));
p.setBrush(QColor(color, color, color));
switch (type) {
case KEYFRAME_TYPE_LINEAR:
{
QPoint points[KEYFRAME_POINT_COUNT] = {QPoint(x-KEYFRAME_SIZE, y), QPoint(x, y-KEYFRAME_SIZE), QPoint(x+KEYFRAME_SIZE, y), QPoint(x, y+KEYFRAME_SIZE)};
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
}
break;
case KEYFRAME_TYPE_BEZIER:
p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE);
break;
case KEYFRAME_TYPE_HOLD:
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
break;
}
update_keys();
}
void KeyframeView::resize_move(double d) {
@@ -227,6 +209,9 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
for (int i=0;i<rowY.size();i++) {
if (mouse_y > rowY.at(i)-KEYFRAME_SIZE-KEYFRAME_SIZE && mouse_y < rowY.at(i)+KEYFRAME_SIZE+KEYFRAME_SIZE) {
EffectRow* row = rows.at(i);
row->focus_row();
for (int j=0;j<row->keyframe_times.size();j++) {
long eval_keyframe_time = row->keyframe_times.at(j)-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in);
if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) {
@@ -259,7 +244,7 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
keys_selected = true;
}
update();
update_keys();
if (event->button() == Qt::LeftButton) {
mousedown = true;
@@ -345,7 +330,7 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
select_rect = true;
}
update();
update_keys();
}
}
@@ -363,5 +348,5 @@ void KeyframeView::mouseReleaseEvent(QMouseEvent*) {
mousedown = false;
scroll_drag = false;
panel_timeline->snapped = false;
update();
update_ui(false);
}
+3 -2
View File
@@ -23,7 +23,7 @@ public:
public slots:
void set_x_scroll(int);
void set_y_scroll(int);
void resize_move(double d);
void resize_move(double d);
private:
long adjust_row_keyframe(EffectRow* row, long time);
QVector<EffectRow*> selected_rows;
@@ -35,7 +35,6 @@ private:
void mouseMoveEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
void draw_keyframe(QPainter& p, int type, int x, int y, bool darker);
bool mousedown;
bool dragging;
bool keys_selected;
@@ -53,6 +52,8 @@ private:
int x_scroll;
int y_scroll;
void update_keys();
private slots:
void show_context_menu(const QPoint& pos);
void menu_set_key_type(QAction*);
+8 -2
View File
@@ -16,7 +16,7 @@ LabelSlider::LabelSlider(QWidget* parent) : QLabel(parent) {
drag_proc = false;
min_enabled = false;
max_enabled = false;
setStyleSheet("QLabel{color:#ffc000;text-decoration:underline;}QLabel:disabled{color:#808080;}");
set_color();
setCursor(Qt::SizeHorCursor);
internal_value = -1;
set = false;
@@ -75,7 +75,12 @@ double LabelSlider::getPreviousValue() {
}
void LabelSlider::set_previous_value() {
previous_value = internal_value;
previous_value = internal_value;
}
void LabelSlider::set_color(QString c) {
if (c.isEmpty()) c = "#ffc000";
setStyleSheet("QLabel{color:" + c + ";text-decoration:underline;}QLabel:disabled{color:#808080;}");
}
double LabelSlider::value() {
@@ -115,6 +120,7 @@ void LabelSlider::mousePressEvent(QMouseEvent *ev) {
drag_start_x = cursor().pos().x();
drag_start_y = cursor().pos().y();
}
emit clicked();
}
void LabelSlider::mouseMoveEvent(QMouseEvent* event) {
+2
View File
@@ -25,6 +25,7 @@ public:
QString valueToString(double v);
double getPreviousValue();
void set_previous_value();
void set_color(QString c = 0);
int decimal_places;
protected:
void mousePressEvent(QMouseEvent *ev);
@@ -53,6 +54,7 @@ private:
double frame_rate;
signals:
void valueChanged();
void clicked();
};
#endif // LABELSLIDER_H
+1 -1
View File
@@ -21,12 +21,12 @@ public:
bool snapping;
void show_text(bool enable);
void update_zoom(double z);
double get_zoom();
void delete_markers();
void set_scrollbar_max(QScrollBar* bar, long sequence_end_frame, int offset);
public slots:
void update_zoom(double z);
void set_scroll(int);
void set_visible_in(long i);
void show_context_menu(const QPoint &pos);