diff --git a/effects/video/glsl/waveeffect.frag b/effects/video/glsl/waveeffect.frag index c64f60d60..ec0384dad 100644 --- a/effects/video/glsl/waveeffect.frag +++ b/effects/video/glsl/waveeffect.frag @@ -4,19 +4,26 @@ uniform float frequency; uniform float intensity; uniform float evolution; +uniform bool vertical; uniform mediump float amount_val; uniform sampler2D myTexture; varying vec2 vTexCoord; void main(void) { - float offset = sin((vTexCoord.x-evolution)*frequency)*intensity; + float x = vTexCoord.x; + float y = vTexCoord.y; - float y = vTexCoord.y-offset; - if (y < 0.0 || y > 1.0) { + if (vertical) { + x -= sin((vTexCoord.y-evolution)*frequency)*intensity; + } else { + y -= sin((vTexCoord.x-evolution)*frequency)*intensity; + } + + if (y < 0.0 || y > 1.0 || x < 0.0 || x > 1.0) { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); } else { - vec4 textureColor = texture2D(myTexture, vec2(vTexCoord.x, y)); + vec4 textureColor = texture2D(myTexture, vec2(x, y)); gl_FragColor = vec4( textureColor.r, textureColor.g, diff --git a/effects/video/waveeffect.cpp b/effects/video/waveeffect.cpp index 8c97147c3..0e75f879f 100644 --- a/effects/video/waveeffect.cpp +++ b/effects/video/waveeffect.cpp @@ -13,9 +13,13 @@ WaveEffect::WaveEffect(Clip* c) : Effect(c, EFFECT_TYPE_VIDEO, VIDEO_WAVE_EFFECT evolution_val = add_row("Evolution:")->add_field(EFFECT_FIELD_DOUBLE); evolution_val->set_double_default_value(0); + vertical_val = add_row("Vertical:")->add_field(EFFECT_FIELD_BOOL); + vertical_val->set_bool_value(false); + connect(frequency_val, SIGNAL(changed()), this, SLOT(field_changed())); connect(intensity_val, SIGNAL(changed()), this, SLOT(field_changed())); connect(evolution_val, SIGNAL(changed()), this, SLOT(field_changed())); + connect(vertical_val, SIGNAL(changed()), this, SLOT(field_changed())); vertPath = ":/shaders/common.vert"; fragPath = ":/shaders/waveeffect.frag"; @@ -25,4 +29,5 @@ void WaveEffect::process_shader(double timecode) { glslProgram->setUniformValue("frequency", (GLfloat) (frequency_val->get_double_value(timecode))); glslProgram->setUniformValue("intensity", (GLfloat) (intensity_val->get_double_value(timecode)*0.01)); glslProgram->setUniformValue("evolution", (GLfloat) (evolution_val->get_double_value(timecode)*0.01)); + glslProgram->setUniformValue("vertical", vertical_val->get_bool_value(timecode)); } diff --git a/effects/video/waveeffect.h b/effects/video/waveeffect.h index 78e973585..a924be988 100644 --- a/effects/video/waveeffect.h +++ b/effects/video/waveeffect.h @@ -12,6 +12,8 @@ private: EffectField* frequency_val; EffectField* intensity_val; EffectField* evolution_val; + + EffectField* vertical_val; }; #endif // WAVEEFFECT_H diff --git a/io/exportthread.cpp b/io/exportthread.cpp index a961486e2..71e4485a8 100644 --- a/io/exportthread.cpp +++ b/io/exportthread.cpp @@ -109,7 +109,7 @@ bool ExportThread::setupVideo() { vcodec_ctx->codec_id = static_cast(video_codec); vcodec_ctx->width = video_width; vcodec_ctx->height = video_height; - vcodec_ctx->sample_aspect_ratio = av_d2q(video_width/video_height, INT_MAX); + vcodec_ctx->sample_aspect_ratio = {1, 1}; vcodec_ctx->pix_fmt = vcodec->pix_fmts[0]; // maybe be breakable code vcodec_ctx->framerate = av_d2q(video_frame_rate, INT_MAX); if (video_compression_type == COMPRESSION_TYPE_CBR) vcodec_ctx->bit_rate = video_bitrate * 1000000; diff --git a/panels/project.cpp b/panels/project.cpp index f46a729c2..3b7e0113d 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -1060,7 +1060,8 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int int len = root ? ui->treeWidget->topLevelItemCount() : parent->childCount(); for (int i=0;itreeWidget->topLevelItem(i) : parent->child(i); - int item_type = get_type_from_tree(item); + int item_type = get_type_from_tree(item); + if (type == item_type) { if (item_type == MEDIA_TYPE_FOLDER) { if (set_ids_only) { @@ -1078,7 +1079,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int } stream.writeEndElement(); } - save_folder(stream, item, type, set_ids_only); + // save_folder(stream, item, type, set_ids_only); } else { int folder = root ? 0 : parent->data(0, Qt::UserRole + 3).toInt(); if (type == MEDIA_TYPE_FOOTAGE) { @@ -1202,6 +1203,10 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int } } } + + if (item_type == MEDIA_TYPE_FOLDER) { + save_folder(stream, item, type, set_ids_only); + } } } diff --git a/panels/viewer.cpp b/panels/viewer.cpp index ff13285f8..e3f3b4eb0 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -24,6 +24,7 @@ extern "C" { #include #include #include +#include Viewer::Viewer(QWidget *parent) : QDockWidget(parent), @@ -87,6 +88,48 @@ void Viewer::reset_all_audio() { clear_audio_ibuffer(); } +long timecode_to_frame(const QString& s, int view, double frame_rate) { + QList list = s.split(QRegExp("[:;]")); + + for (int i=0;i 0) ? list.at(0).toInt() : 0) * frRound * 3600; + int minutes = ((list.size() > 1) ? list.at(1).toInt() : 0) * frRound * 60; + int seconds = ((list.size() > 2) ? list.at(2).toInt() : 0) * frRound; + int frames = (list.size() > 3) ? list.at(3).toInt() : 0; + + int f = (frames + seconds + minutes + hours); + + if (view == TIMECODE_DROP && frame_rate_is_droppable(frame_rate)) { + // return drop + int d; + int m; + + int dropFrames = round(frame_rate * .066666); //Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate + int framesPer10Minutes = round(frame_rate * 60 * 10); //Number of frames per ten minutes + int framesPerMinute = (round(frame_rate)*60)- dropFrames; //Number of frames per minute is the round of the framerate * 60 minus the number of dropped frames + + d = f / framesPer10Minutes; + f -= dropFrames*9*d; + + m = f % framesPer10Minutes; + + if (m > dropFrames) { + f -= (dropFrames * ((m - dropFrames) / framesPerMinute)); + } + } + + // return non-drop + return f; +} + QString frame_to_timecode(long f, int view, double frame_rate) { if (view == TIMECODE_FRAMES) { return QString::number(f); diff --git a/panels/viewer.h b/panels/viewer.h index 54806764b..a06342612 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -13,6 +13,7 @@ class Viewer; } bool frame_rate_is_droppable(float rate); +long timecode_to_frame(const QString& s, int view, double frame_rate); QString frame_to_timecode(long f, int view, double frame_rate); class Viewer : public QDockWidget diff --git a/project/undo.cpp b/project/undo.cpp index 435635166..ffec52dcf 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -1210,6 +1210,8 @@ void MediaMove::undo() { } else { to->removeChild(items.at(i)); } + } + for (int i=0;iaddTopLevelItem(items.at(i)); } else { @@ -1220,9 +1222,10 @@ void MediaMove::undo() { } void MediaMove::redo() { + froms.resize(items.size()); for (int i=0;iparent(); - froms.append(parent); + froms[i] = parent; if (parent == NULL) { table->takeTopLevelItem(table->indexOfTopLevelItem(items.at(i))); } else { @@ -1233,6 +1236,13 @@ void MediaMove::redo() { } else { to->addChild(items.at(i)); } + } + for (int i=0;iaddTopLevelItem(items.at(i)); + } else { + to->addChild(items.at(i)); + } } mainWindow->setWindowModified(true); } diff --git a/ui/labelslider.cpp b/ui/labelslider.cpp index 471227e2a..9833f7b33 100644 --- a/ui/labelslider.cpp +++ b/ui/labelslider.cpp @@ -136,21 +136,33 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) { drag_proc = false; previous_value = drag_start_value; emit valueChanged(); - } else { - double d = QInputDialog::getDouble( - this, - "Set Value", - "New value:", - (display_type == LABELSLIDER_PERCENT) ? internal_value * 100 : internal_value, - (min_enabled) ? min_value : INT_MIN, - (max_enabled) ? max_value : INT_MAX, - decimal_places - ); - if (display_type == LABELSLIDER_PERCENT) d *= 0.01; - if (d != internal_value) { + } else { + double d = internal_value; + if (display_type == LABELSLIDER_FRAMENUMBER) { + QString s = QInputDialog::getText( + this, + "Set Value", + "New value:", + QLineEdit::Normal, + valueToString(internal_value) + ); + d = timecode_to_frame(s, config.timecode_view, frame_rate); // string to frame number + } else { + d = QInputDialog::getDouble( + this, + "Set Value", + "New value:", + (display_type == LABELSLIDER_PERCENT) ? internal_value * 100 : internal_value, + (min_enabled) ? min_value : INT_MIN, + (max_enabled) ? max_value : INT_MAX, + decimal_places + ); + if (display_type == LABELSLIDER_PERCENT) d *= 0.01; + } + if (d != internal_value) { previous_value = internal_value; set_value(d, true); - } - } + } + } } } diff --git a/ui/sourcetable.cpp b/ui/sourcetable.cpp index c9c2ac33b..235188ad7 100644 --- a/ui/sourcetable.cpp +++ b/ui/sourcetable.cpp @@ -112,7 +112,7 @@ void SourceTable::rename_interval() { } } void SourceTable::item_click(QTreeWidgetItem* item, int column) { - if (column == 0) { + if (column == 0 && selectedItems().size() == 1) { editing_item = item; rename_timer.start(); } @@ -186,30 +186,34 @@ void SourceTable::dropEvent(QDropEvent* event) { } event->acceptProposedAction(); } else { + event->ignore(); + // dragging files within project - QVector move_items; // if we dragged to the root OR dragged to a folder if (drop_item == NULL || (drop_item != NULL && get_type_from_tree(drop_item) == MEDIA_TYPE_FOLDER)) { + QVector move_items; QList selected_items = selectedItems(); for (int i=0;iparent() != NULL) { - // if child belongs to a selected parent, assume the user is just moving the parent and ignore the child - QTreeWidgetItem* par = s->parent(); - while (par != NULL) { - for (int j=0;jparent(); - } - } - if (!ignore) { - move_items.append(s); - } + if (s->parent() != drop_item && s != drop_item) { + bool ignore = false; + if (s->parent() != NULL) { + // if child belongs to a selected parent, assume the user is just moving the parent and ignore the child + QTreeWidgetItem* par = s->parent(); + while (par != NULL && !ignore) { + for (int j=0;jparent(); + } + } + if (!ignore) { + move_items.append(s); + } + } } if (move_items.size() > 0) { MediaMove* mm = new MediaMove(this); @@ -217,6 +221,6 @@ void SourceTable::dropEvent(QDropEvent* event) { mm->items = move_items; undo_stack.push(mm); } - } + } } } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index d58f3c2e3..ea96fa794 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -13,6 +13,7 @@ #include "project/undo.h" #include "ui_timeline.h" #include "mainwindow.h" +#include "ui/viewerwidget.h" #include "effects/effect.h" #include "effects/transition.h" @@ -191,13 +192,59 @@ bool same_sign(int a, int b) { } void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { - if (event->source() == panel_project->source_table) { + qDebug() << "DRAG ENTER CALLED"; + + bool import_init = false; + + QVector media_list; + QVector type_list; + + if (event->source() == panel_project->source_table) { + QList items = panel_project->source_table->selectedItems(); + media_list.resize(items.size()); + type_list.resize(items.size()); + for (int i=0;isource() == panel_footage_viewer->viewer_widget) { + Sequence* proposed_seq = panel_footage_viewer->seq; + if (proposed_seq != sequence) { // don't allow nesting the same sequence + if (proposed_seq->wrapper_sequence) { + type_list.append(MEDIA_TYPE_FOOTAGE); + media_list.append(proposed_seq->clips.at(0)->media); + } else { + type_list.append(MEDIA_TYPE_SEQUENCE); + media_list.append(proposed_seq); + } + import_init = true; + } + } + + /*if (config.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) { + // TODO for this to work, we need a way to abort PreviewGenerator + + + qDebug() << "TODO get data for:"; + QList urls = event->mimeData()->urls(); + if (!urls.isEmpty()) { + for (int i=0;iaccept(); panel_timeline->video_ghosts = false; panel_timeline->audio_ghosts = false; - QPoint pos = event->pos(); - QList items = panel_project->source_table->selectedItems(); + QPoint pos = event->pos(); long entry_point; if (sequence == NULL) { // if no sequence, we're going to create a new one using the clips as a reference @@ -212,12 +259,11 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { bool got_video_values = false; bool got_audio_values = false; - for (int i=0;i(media_list.at(i)); if (m->ready) { if (!got_video_values) { for (int j=0;jvideo_tracks.size();j++) { @@ -246,7 +292,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { break; case MEDIA_TYPE_SEQUENCE: { - Sequence* s = get_sequence_from_tree(item); + Sequence* s = static_cast(media_list.at(i)); predicted_video_width = s->width; predicted_video_height = s->height; predicted_new_frame_rate = s->frame_rate; @@ -266,9 +312,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; predicted_new_frame_rate = sequence->frame_rate; } - for (int i=0;i(media_list.at(i)); media = m; can_import = m->ready; if (m->using_inout) { @@ -291,7 +335,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { } break; case MEDIA_TYPE_SEQUENCE: - s = get_sequence_from_tree(item); + s = static_cast(media_list.at(i)); sequence_length = s->getEndFrame(); if (sequence != NULL) sequence_length = refactor_frame_number(sequence_length, s->frame_rate, predicted_new_frame_rate); media = s; @@ -308,14 +352,14 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { if (can_import) { Ghost g; g.clip = -1; - g.media_type = item_type; + g.media_type = type_list.at(i); g.trimming = false; g.old_clip_in = g.clip_in = default_clip_in; g.media = media; g.in = entry_point; g.transition = NULL; - switch (item_type) { + switch (type_list.at(i)) { case MEDIA_TYPE_FOOTAGE: // is video source a still image? if (m->video_tracks.size() > 0 && m->video_tracks[0]->infinite_length && m->audio_tracks.size() == 0) { @@ -367,18 +411,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { g.old_track = g.track; } panel_timeline->importing = true; - } else if (config.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) { - // TODO for this to work, we need a way to abort PreviewGenerator - - /*event->accept(); - qDebug() << "TODO get data for:"; - QList urls = event->mimeData()->urls(); - if (!urls.isEmpty()) { - for (int i=0;iimporting) { QToolTip::showText(mapToGlobal(mouse_pos), frame_to_timecode(earliest_in_point, config.timecode_view, sequence->frame_rate)); } else { - QToolTip::showText(mapToGlobal(mouse_pos), ((frame_diff < 0) ? "-" : "+") + frame_to_timecode(qAbs(frame_diff), config.timecode_view, sequence->frame_rate)); + QToolTip::showText(mapToGlobal(mouse_pos), + ((frame_diff < 0) ? "-" : "+") + + frame_to_timecode(qAbs(frame_diff), config.timecode_view, sequence->frame_rate) + + " Duration: " + + frame_to_timecode((panel_timeline->ghosts.at(0).old_out-panel_timeline->ghosts.at(0).old_in)+frame_diff, config.timecode_view, sequence->frame_rate) + ); } } @@ -1666,71 +1704,77 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { bool found = false; bool cursor_contains_clip = false; int closeness = INT_MAX; + int min_track = INT_MAX; + int max_track = INT_MIN; panel_timeline->transition_select = TA_NO_TRANSITION; for (int i=0;iclips.size();i++) { Clip* c = sequence->clips.at(i); - if (c != NULL && c->track == mouse_track) { - if (panel_timeline->cursor_frame >= c->timeline_in && - panel_timeline->cursor_frame <= c->timeline_out) { - cursor_contains_clip = true; + if (c != NULL) { + min_track = qMin(min_track, c->track); + max_track = qMax(max_track, c->track); + if (c->track == mouse_track) { + if (panel_timeline->cursor_frame >= c->timeline_in && + panel_timeline->cursor_frame <= c->timeline_out) { + cursor_contains_clip = true; - tooltip_timer.start(); - tooltip_clip = i; + tooltip_timer.start(); + tooltip_clip = i; - if (c->opening_transition != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->opening_transition->length) { - panel_timeline->transition_select = TA_OPENING_TRANSITION; - } else if (c->closing_transition != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->closing_transition->length) { - panel_timeline->transition_select = TA_CLOSING_TRANSITION; - } - } - if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) { - int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = true; - closeness = nc; - found = true; - } - } - if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) { - int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = false; - closeness = nc; - found = true; - } - } - if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { - if (c->opening_transition != NULL) { - long transition_point = c->timeline_in + c->opening_transition->length; - - if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { - int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = false; - panel_timeline->transition_select = TA_OPENING_TRANSITION; - closeness = nc; - found = true; - } + if (c->opening_transition != NULL && panel_timeline->cursor_frame <= c->timeline_in + c->opening_transition->length) { + panel_timeline->transition_select = TA_OPENING_TRANSITION; + } else if (c->closing_transition != NULL && panel_timeline->cursor_frame >= c->timeline_out - c->closing_transition->length) { + panel_timeline->transition_select = TA_CLOSING_TRANSITION; } } - if (c->closing_transition != NULL) { - long transition_point = c->timeline_out - c->closing_transition->length; - if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { - int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame); - if (nc < closeness) { - panel_timeline->trim_target = i; - panel_timeline->trim_in_point = true; - panel_timeline->transition_select = TA_CLOSING_TRANSITION; - closeness = nc; - found = true; + if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) { + int nc = qAbs(c->timeline_in + 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = true; + closeness = nc; + found = true; + } + } + if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) { + int nc = qAbs(c->timeline_out - 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = false; + closeness = nc; + found = true; + } + } + if (panel_timeline->tool == TIMELINE_TOOL_POINTER) { + if (c->opening_transition != NULL) { + long transition_point = c->timeline_in + c->opening_transition->length; + + if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + int nc = qAbs(transition_point - 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = false; + panel_timeline->transition_select = TA_OPENING_TRANSITION; + closeness = nc; + found = true; + } + } + } + if (c->closing_transition != NULL) { + long transition_point = c->timeline_out - c->closing_transition->length; + if (transition_point > mouse_frame_lower && transition_point < mouse_frame_upper) { + int nc = qAbs(transition_point + 1 - panel_timeline->cursor_frame); + if (nc < closeness) { + panel_timeline->trim_target = i; + panel_timeline->trim_in_point = true; + panel_timeline->transition_select = TA_CLOSING_TRANSITION; + closeness = nc; + found = true; + } } } } } - } + } } /*if (cursor_contains_clip) { QToolTip::showText(mapToGlobal(event->pos()), "HOVER OVER CLIP"); @@ -1744,21 +1788,23 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) { int track_y = 0; for (int i=0;iget_track_height_size(bottom_align);i++) { int track = (bottom_align) ? -1-i : i; - int track_height = panel_timeline->calculate_track_height(track, -1); - track_y += track_height; - int y_test_value = (bottom_align) ? rect().bottom() - track_y : track_y; - int test_range = 5; - int mouse_pos = pos.y() + scroll; - if (mouse_pos > y_test_value-test_range && mouse_pos < y_test_value+test_range) { - // if track lines are hidden, only resize track if a clip is already there - if (config.show_track_lines || cursor_contains_clip) { - found = true; - track_resizing = true; - track_target = track; - track_resize_old_value = track_height; - } - break; - } + if (track >= min_track && track <= max_track) { + int track_height = panel_timeline->calculate_track_height(track, -1); + track_y += track_height; + int y_test_value = (bottom_align) ? rect().bottom() - track_y : track_y; + int test_range = 5; + int mouse_pos = pos.y() + scroll; + if (mouse_pos > y_test_value-test_range && mouse_pos < y_test_value+test_range) { + // if track lines are hidden, only resize track if a clip is already there + if (config.show_track_lines || cursor_contains_clip) { + found = true; + track_resizing = true; + track_target = track; + track_resize_old_value = track_height; + } + break; + } + } } if (found) { diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index e344b26cd..eb1e5310b 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include extern "C" { #include @@ -29,7 +32,8 @@ extern "C" { ViewerWidget::ViewerWidget(QWidget *parent) : QOpenGLWidget(parent), default_fbo(NULL), - waveform(false) + waveform(false), + dragging(false) { setFocusPolicy(Qt::ClickFocus); @@ -67,7 +71,34 @@ void ViewerWidget::paintEvent(QPaintEvent *e) { if (!rendering) { makeCurrent(); QOpenGLWidget::paintEvent(e); - } + } +} + +void ViewerWidget::seek_from_click(int x) { + viewer->seek(getFrameFromScreenPoint((double) width() / (double) waveform_clip->timeline_out, x)); +} + +void ViewerWidget::mousePressEvent(QMouseEvent* event) { + if (waveform) seek_from_click(event->x()); + dragging = true; +} + +void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { + if (dragging) { + if (waveform) { + seek_from_click(event->x()); + } else { + QDrag* drag = new QDrag(this); + QMimeData* mimeData = new QMimeData; + mimeData->setText("h"); + drag->setMimeData(mimeData); + Qt::DropAction dropAction = drag->exec(); + } + } +} + +void ViewerWidget::mouseReleaseEvent(QMouseEvent *) { + dragging = false; } void ViewerWidget::drawTitleSafeArea() { @@ -238,7 +269,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) { } } - if (viewer->playing && s->playhead == endFrame) { + if (viewer->playing && (s->playhead == endFrame || (s->using_workarea && s->playhead == s->workarea_out))) { viewer->pause(); } @@ -470,10 +501,16 @@ void ViewerWidget::paintGL() { double timeline_zoom = (double) width() / (double) waveform_clip->timeline_out; QPainter p(this); - p.setPen(QColor(0, 255, 0)); if (viewer->seq->using_workarea) { - p.fillRect(QRect(getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_in), 0, getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_out-viewer->seq->workarea_in), height()), QColor(255, 255, 255, 64)); + int in_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_in); + int out_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->workarea_out); + + p.fillRect(QRect(in_x, 0, out_x - in_x, height()), QColor(255, 255, 255, 64)); + p.setPen(Qt::white); + p.drawLine(in_x, 0, in_x, height()); + p.drawLine(out_x, 0, out_x, height()); } + p.setPen(Qt::green); draw_waveform(waveform_clip, waveform_ms, waveform_clip->timeline_out, &p, rect(), 0, width(), waveform_zoom); p.setPen(Qt::red); int playhead_x = getScreenPointFromFrame(timeline_zoom, viewer->seq->playhead); diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index de19a7e10..4d0b6e1fc 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -32,14 +32,19 @@ public: protected: void paintEvent(QPaintEvent *e); // void resizeGL(int w, int h); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); private: QTimer retry_timer; void drawTitleSafeArea(); + bool dragging; + void seek_from_click(int x); + GLuint compose_sequence(Clip *nest, bool render_audio); + GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture); private slots: void retry(); void deleteFunction(); - GLuint compose_sequence(Clip *nest, bool render_audio); - GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture); }; #endif // VIEWERWIDGET_H