added some functionality for #97
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
CrossDissolveTransition::CrossDissolveTransition() {
|
||||
name = "Cross Dissolve";
|
||||
}
|
||||
|
||||
void CrossDissolveTransition::process_transition(float progress) {
|
||||
float color[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, color);
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#ifndef TRANSITION_H
|
||||
#define TRANSITION_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class Transition
|
||||
{
|
||||
public:
|
||||
Transition();
|
||||
int length;
|
||||
QString name;
|
||||
virtual void process_transition(float);
|
||||
};
|
||||
|
||||
class CrossDissolveTransition : public Transition {
|
||||
public:
|
||||
CrossDissolveTransition();
|
||||
void process_transition(float);
|
||||
};
|
||||
|
||||
|
||||
+5
-1
@@ -8,6 +8,10 @@
|
||||
#include <QMutex>
|
||||
#include <QPixmap>
|
||||
|
||||
#define MEDIA_TYPE_FOOTAGE 0
|
||||
#define MEDIA_TYPE_SEQUENCE 1
|
||||
#define MEDIA_TYPE_FOLDER 2
|
||||
|
||||
struct Sequence;
|
||||
|
||||
struct MediaStream {
|
||||
@@ -31,7 +35,7 @@ struct Media
|
||||
|
||||
QString url;
|
||||
QString name;
|
||||
bool is_sequence;
|
||||
char type;
|
||||
int64_t length;
|
||||
QVector<MediaStream*> video_tracks;
|
||||
QVector<MediaStream*> audio_tracks;
|
||||
|
||||
@@ -29,7 +29,7 @@ void PreviewGenerator::run() {
|
||||
if (media == NULL) {
|
||||
qDebug() << "[ERROR] No media was set for preview generation";
|
||||
} else {
|
||||
if (media->is_sequence) {
|
||||
if (media->type == MEDIA_TYPE_SEQUENCE) {
|
||||
qDebug() << "[ERROR] Cannot run preview generation on a sequence";
|
||||
} else {
|
||||
SwsContext* sws_ctx;
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowTitle("Olive (June 2018 | Pre-Alpha)");
|
||||
setWindowTitle("Olive (July 2018 | Pre-Alpha)");
|
||||
statusBar()->showMessage("Welcome to Olive");
|
||||
|
||||
ui->centralWidget->setMaximumSize(0, 0);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.2, 2018-07-03T01:22:47. -->
|
||||
<!-- Written by QtCreator 4.6.2, 2018-07-03T16:05:25. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
+16
-7
@@ -37,6 +37,8 @@ Project::Project(QWidget *parent) :
|
||||
ui(new Ui::Project)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(rename_media(QTreeWidgetItem*,int)));
|
||||
}
|
||||
|
||||
Project::~Project()
|
||||
@@ -66,13 +68,19 @@ QString Project::get_next_sequence_name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
void Project::rename_media(QTreeWidgetItem* item, int column) {
|
||||
Media* m = get_media_from_tree(item);
|
||||
m->name = item->text(column);
|
||||
}
|
||||
|
||||
void Project::new_sequence(Sequence *s) {
|
||||
Media* m = new Media();
|
||||
m->is_sequence = true;
|
||||
m->type = MEDIA_TYPE_SEQUENCE;
|
||||
m->sequence = s;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0, s->name);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
item->setText(0, s->name);
|
||||
set_media_of_tree(item, m);
|
||||
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
@@ -105,7 +113,7 @@ Media* Project::import_file(QString file) {
|
||||
av_dump_format(pFormatCtx, 0, filename, 0);
|
||||
|
||||
m = new Media();
|
||||
m->is_sequence = false;
|
||||
m->type = MEDIA_TYPE_FOOTAGE;
|
||||
m->url = file;
|
||||
|
||||
// detect video/audio streams in file
|
||||
@@ -144,6 +152,7 @@ Media* Project::import_file(QString file) {
|
||||
m->length = pFormatCtx->duration;
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
if (m->video_tracks.size() == 0) {
|
||||
item->setIcon(0, QIcon(":/icons/audiosource.png"));
|
||||
} else {
|
||||
@@ -181,7 +190,7 @@ void Project::delete_selected_media() {
|
||||
// check if media is in use
|
||||
for (int i=0;i<items.size();i++) {
|
||||
Media* m = get_media_from_tree(items.at(i));
|
||||
if (!m->is_sequence && sequence != NULL) {
|
||||
if (m->type == MEDIA_TYPE_FOOTAGE && sequence != NULL) {
|
||||
for (int j=0;j<sequence->clip_count();j++) {
|
||||
Clip* c = sequence->get_clip(j);
|
||||
if (c != NULL && c->media == m) {
|
||||
@@ -289,7 +298,7 @@ void Project::set_media_of_tree(QTreeWidgetItem* item, Media* media) {
|
||||
|
||||
void Project::delete_media(QTreeWidgetItem* item) {
|
||||
Media* m = get_media_from_tree(item);
|
||||
if (m->is_sequence) {
|
||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
||||
if (sequence == m->sequence) {
|
||||
set_sequence(NULL);
|
||||
}
|
||||
@@ -537,7 +546,7 @@ void Project::save_project() {
|
||||
stream.writeStartElement("media");
|
||||
for (int i=0;i<len;i++) {
|
||||
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
|
||||
if (!m->is_sequence) {
|
||||
if (m->type == MEDIA_TYPE_FOOTAGE) {
|
||||
m->save_id = i;
|
||||
stream.writeStartElement("footage");
|
||||
stream.writeAttribute("id", QString::number(m->save_id));
|
||||
@@ -551,7 +560,7 @@ void Project::save_project() {
|
||||
stream.writeStartElement("timeline");
|
||||
for (int i=0;i<len;i++) {
|
||||
Media* m = get_media_from_tree(ui->treeWidget->topLevelItem(i));
|
||||
if (m->is_sequence) {
|
||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
||||
Sequence* s = m->sequence;
|
||||
stream.writeStartElement("sequence");
|
||||
stream.writeTextElement("name", s->name);
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
SourceTable* source_table;
|
||||
private:
|
||||
Ui::Project *ui;
|
||||
private slots:
|
||||
void rename_media(QTreeWidgetItem* item, int column);
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@
|
||||
<item>
|
||||
<widget class="SourceTable" name="treeWidget">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::CurrentChanged|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>false</bool>
|
||||
|
||||
+1
-3
@@ -8,9 +8,7 @@
|
||||
|
||||
#include <QCheckBox>
|
||||
|
||||
Effect::Effect(Clip* c) : parent_clip(c)
|
||||
{
|
||||
name = "<unnamed effect>";
|
||||
Effect::Effect(Clip* c) : parent_clip(c) {
|
||||
type = EFFECT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "sequence.h"
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "effects/transition.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@@ -88,6 +89,20 @@ Clip* Sequence::split_clip(Clip* pre, long frame) {
|
||||
post->timeline_in = frame;
|
||||
post->clip_in = pre->clip_in + pre->getLength();
|
||||
|
||||
long pre_length = pre->getLength();
|
||||
|
||||
if (pre->closing_transition != NULL) {
|
||||
post->closing_transition = pre->closing_transition;
|
||||
pre->closing_transition = NULL;
|
||||
long post_length = post->getLength();
|
||||
if (post->closing_transition->length > post_length) {
|
||||
post->closing_transition->length = post_length;
|
||||
}
|
||||
}
|
||||
if (pre->opening_transition != NULL && pre->opening_transition->length > pre_length) {
|
||||
pre->opening_transition->length = pre_length;
|
||||
}
|
||||
|
||||
add_clip(post);
|
||||
|
||||
return post;
|
||||
|
||||
+29
-5
@@ -14,17 +14,41 @@
|
||||
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
sortByColumn(0, Qt::AscendingOrder);
|
||||
setAcceptDrops(true);
|
||||
editing_item = NULL;
|
||||
rename_timer.setInterval(500);
|
||||
connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval()));
|
||||
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(item_click(QTreeWidgetItem*,int)));
|
||||
|
||||
// connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, )
|
||||
}
|
||||
|
||||
void SourceTable::mouseDoubleClickEvent(QMouseEvent* )
|
||||
{
|
||||
void SourceTable::rename_interval() {
|
||||
rename_timer.stop();
|
||||
if (hasFocus() && editing_item != NULL) {
|
||||
editItem(editing_item, 0);
|
||||
}
|
||||
}
|
||||
void SourceTable::item_click(QTreeWidgetItem* item, int column) {
|
||||
if (column == 0) {
|
||||
editing_item = item;
|
||||
rename_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTable::mousePressEvent(QMouseEvent* event) {
|
||||
rename_timer.stop();
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) {
|
||||
if (selectedItems().count() == 0) {
|
||||
panel_project->import_dialog();
|
||||
} else if (selectedItems().count() == 1) {
|
||||
Media* m = reinterpret_cast<Media*>(selectedItems().at(0)->data(0, Qt::UserRole + 1).value<quintptr>());
|
||||
if (m->is_sequence) {
|
||||
QTreeWidgetItem* item = selectedItems().at(0);
|
||||
Media* m = reinterpret_cast<Media*>(item->data(0, Qt::UserRole + 1).value<quintptr>());
|
||||
if (m->type == MEDIA_TYPE_SEQUENCE) {
|
||||
set_sequence(m->sequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,27 @@
|
||||
#define SOURCETABLE_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include <QTimer>
|
||||
|
||||
class Project;
|
||||
|
||||
class SourceTable : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SourceTable(QWidget* parent = 0);
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
private:
|
||||
QTimer rename_timer;
|
||||
QTreeWidgetItem* editing_item;
|
||||
private slots:
|
||||
void rename_interval();
|
||||
void item_click(QTreeWidgetItem* item, int column);
|
||||
};
|
||||
|
||||
#endif // SOURCETABLE_H
|
||||
|
||||
+66
-41
@@ -23,8 +23,9 @@
|
||||
#include <QMenu>
|
||||
#include <QtMath>
|
||||
|
||||
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
#define MAX_TEXT_WIDTH 20
|
||||
|
||||
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent) {
|
||||
bottom_align = false;
|
||||
track_resizing = false;
|
||||
setMouseTracking(true);
|
||||
@@ -974,8 +975,8 @@ void TimelineWidget::redraw_clips() {
|
||||
clip_pixmap.fill(Qt::transparent);
|
||||
QPainter clip_painter(&clip_pixmap);
|
||||
int video_track_limit = 0;
|
||||
int audio_track_limit = 0;
|
||||
QColor transition_color(160, 128, 192);
|
||||
int audio_track_limit = 0;
|
||||
QColor transition_color(255, 0, 0, 16);
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* clip = sequence->get_clip(i);
|
||||
if (clip != NULL && is_track_visible(clip->track)) {
|
||||
@@ -988,17 +989,58 @@ void TimelineWidget::redraw_clips() {
|
||||
QRect clip_rect(panel_timeline->getScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), clip->getLength() * panel_timeline->zoom, panel_timeline->calculate_track_height(clip->track, -1));
|
||||
clip_painter.fillRect(clip_rect, QColor(clip->color_r, clip->color_g, clip->color_b));
|
||||
|
||||
int thumb_x = clip_rect.x() + 1;
|
||||
|
||||
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - 1, clip_rect.height() - CLIP_TEXT_PADDING - 1);
|
||||
|
||||
// draw clip transitions
|
||||
for (char i=0;i<2;i++) {
|
||||
Transition* t;
|
||||
if (i == 0) {
|
||||
t = clip->opening_transition;
|
||||
} else {
|
||||
t = clip->closing_transition;
|
||||
}
|
||||
if (t != NULL) {
|
||||
int transition_width = panel_timeline->getScreenPointFromFrame(t->length);
|
||||
QRect transition_rect;
|
||||
if (i == 0) {
|
||||
transition_rect = QRect(clip_rect.x(), clip_rect.y(), transition_width, clip_rect.height());
|
||||
text_rect.setX(text_rect.x()+transition_width);
|
||||
thumb_x += transition_width;
|
||||
} else {
|
||||
transition_rect = QRect(clip_rect.right()-transition_width, clip_rect.y(), transition_width, clip_rect.height());
|
||||
text_rect.setWidth(text_rect.width()-transition_width);
|
||||
}
|
||||
clip_painter.fillRect(transition_rect, transition_color);
|
||||
QRect transition_text_rect(transition_rect.x() + CLIP_TEXT_PADDING, transition_rect.y() + CLIP_TEXT_PADDING, transition_rect.width() - CLIP_TEXT_PADDING, transition_rect.height() - CLIP_TEXT_PADDING);
|
||||
if (transition_text_rect.width() > MAX_TEXT_WIDTH) {
|
||||
clip_painter.setPen(QColor(0, 0, 0, 96));
|
||||
if (i == 0) {
|
||||
clip_painter.drawLine(transition_rect.bottomLeft(), transition_rect.topRight());
|
||||
} else {
|
||||
clip_painter.drawLine(transition_rect.topLeft(), transition_rect.bottomRight());
|
||||
}
|
||||
|
||||
clip_painter.setPen(Qt::white);
|
||||
clip_painter.drawText(transition_text_rect, 0, t->name, &transition_text_rect);
|
||||
}
|
||||
clip_painter.setPen(Qt::black);
|
||||
clip_painter.drawRect(transition_rect);
|
||||
}
|
||||
}
|
||||
|
||||
// draw thumbnail/waveform
|
||||
if (clip->media_stream->preview_done) {
|
||||
if (clip->track < 0) {
|
||||
int thumb_y = clip_painter.fontMetrics().height()+CLIP_TEXT_PADDING+CLIP_TEXT_PADDING;
|
||||
int thumb_height = clip_rect.height()-thumb_y;
|
||||
int thumb_width = (thumb_height*((float)clip->media_stream->video_preview.width()/(float)clip->media_stream->video_preview.height()));
|
||||
if (thumb_height > thumb_y && clip_rect.width() > thumb_width) { // at small clip heights, don't even draw it
|
||||
QRect thumb_rect(clip_rect.x(), clip_rect.y()+thumb_y, thumb_width, thumb_height);
|
||||
if (thumb_height > thumb_y && text_rect.width() + CLIP_TEXT_PADDING > thumb_width) { // at small clip heights, don't even draw it
|
||||
QRect thumb_rect(thumb_x, clip_rect.y()+thumb_y, thumb_width, thumb_height);
|
||||
clip_painter.drawImage(thumb_rect, clip->media_stream->video_preview);
|
||||
}
|
||||
} else {
|
||||
} else if (clip_rect.height() > TRACK_MIN_HEIGHT) {
|
||||
int divider = clip->media_stream->audio_channels*2;
|
||||
|
||||
clip_painter.setPen(QColor(80, 80, 80));
|
||||
@@ -1018,46 +1060,29 @@ void TimelineWidget::redraw_clips() {
|
||||
}
|
||||
}
|
||||
|
||||
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING, clip_rect.height() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING);
|
||||
|
||||
if (clip->opening_transition != NULL) {
|
||||
int transition_width = panel_timeline->getScreenPointFromFrame(clip->opening_transition->length);
|
||||
QRect transition_rect(clip_rect.x(), clip_rect.y(), transition_width, clip_rect.height());
|
||||
text_rect.setX(text_rect.x()+transition_width);
|
||||
clip_painter.fillRect(transition_rect, transition_color);
|
||||
clip_painter.setPen(Qt::black);
|
||||
clip_painter.drawRect(transition_rect);
|
||||
}
|
||||
if (clip->closing_transition != NULL) {
|
||||
int transition_width = panel_timeline->getScreenPointFromFrame(clip->opening_transition->length);
|
||||
QRect transition_rect(clip_rect.right()-transition_width, clip_rect.y(), transition_width, clip_rect.height());
|
||||
text_rect.setWidth(text_rect.width()-transition_width);
|
||||
clip_painter.fillRect(transition_rect, transition_color);
|
||||
clip_painter.setPen(Qt::black);
|
||||
clip_painter.drawRect(transition_rect);
|
||||
}
|
||||
|
||||
// top left bevel
|
||||
clip_painter.setPen(Qt::white);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft());
|
||||
clip_painter.drawLine(clip_rect.topLeft(), clip_rect.topRight());
|
||||
|
||||
// draw text
|
||||
if (color_brightness(clip->color_r, clip->color_g, clip->color_b) > 160) {
|
||||
// set to black if color is bright
|
||||
clip_painter.setPen(Qt::black);
|
||||
}
|
||||
if (clip->linked.size() > 0) {
|
||||
int underline_y = CLIP_TEXT_PADDING + clip_painter.fontMetrics().height() + clip_rect.top();
|
||||
int underline_width = qMin(text_rect.width(), clip_painter.fontMetrics().width(clip->name));
|
||||
clip_painter.drawLine(text_rect.x(), underline_y, text_rect.x() + underline_width, underline_y);
|
||||
}
|
||||
clip_painter.drawText(text_rect, 0, clip->name, &text_rect);
|
||||
if (text_rect.width() > MAX_TEXT_WIDTH) {
|
||||
if (color_brightness(clip->color_r, clip->color_g, clip->color_b) > 160) {
|
||||
// set to black if color is bright
|
||||
clip_painter.setPen(Qt::black);
|
||||
}
|
||||
if (clip->linked.size() > 0) {
|
||||
int underline_y = CLIP_TEXT_PADDING + clip_painter.fontMetrics().height() + clip_rect.top();
|
||||
int underline_width = qMin(text_rect.width() - 1, clip_painter.fontMetrics().width(clip->name));
|
||||
clip_painter.drawLine(text_rect.x(), underline_y, text_rect.x() + underline_width, underline_y);
|
||||
}
|
||||
clip_painter.drawText(text_rect, 0, clip->name, &text_rect);
|
||||
|
||||
// bottom right gray
|
||||
clip_painter.setPen(Qt::gray);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.bottomRight());
|
||||
clip_painter.drawLine(clip_rect.bottomRight(), clip_rect.topRight());
|
||||
// bottom right gray
|
||||
clip_painter.setPen(Qt::gray);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.bottomRight());
|
||||
clip_painter.drawLine(clip_rect.bottomRight(), clip_rect.topRight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1140,7 +1165,7 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
p.drawLine(0, edge_y, rect().width(), edge_y);
|
||||
|
||||
// draw snap point
|
||||
if (panel_timeline->snapping && panel_timeline->snapped) {
|
||||
if (panel_timeline->snapped) {
|
||||
p.setPen(Qt::white);
|
||||
int snap_x = panel_timeline->getScreenPointFromFrame(panel_timeline->snap_point);
|
||||
p.drawLine(snap_x, 0, snap_x, height());
|
||||
|
||||
+3
-2
@@ -59,8 +59,6 @@ void ViewerWidget::paintGL()
|
||||
if (multithreaded) retry_timer.stop();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
current_clips.clear();
|
||||
|
||||
@@ -114,6 +112,9 @@ void ViewerWidget::paintGL()
|
||||
qDebug() << "[WARNING] Texture hasn't been created yet";
|
||||
texture_failed = true;
|
||||
} else if (panel_timeline->playhead >= c->timeline_in) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
glLoadIdentity();
|
||||
int half_width = c->sequence->width/2;
|
||||
int half_height = c->sequence->height/2;
|
||||
|
||||
Reference in New Issue
Block a user