diff --git a/effects/effect.cpp b/effects/effect.cpp index 774eb1678..c42ae81df 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -38,6 +38,7 @@ #include #include #include +#include QVector video_effects; QVector audio_effects; @@ -196,6 +197,8 @@ Effect::Effect(Clip* c, const EffectMeta *em) : ui->setLayout(ui_layout); container->setContents(ui); + connect(container->title_bar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&))); + // set up UI from effect file container->setText(em->name); @@ -422,6 +425,66 @@ void Effect::field_changed() { panel_sequence_viewer->viewer_widget->update(); } +void Effect::show_context_menu(const QPoint& pos) { + QMenu menu(mainWindow); + + int index = get_index_in_clip(); + + if (index > 0) { + QAction* move_up = menu.addAction("Move &Up"); + connect(move_up, SIGNAL(triggered(bool)), this, SLOT(move_up())); + } + + if (index < parent_clip->effects.size() - 1) { + QAction* move_down = menu.addAction("Move &Down"); + connect(move_down, SIGNAL(triggered(bool)), this, SLOT(move_down())); + } + + menu.addSeparator(); + + QAction* del_action = menu.addAction("D&elete"); + connect(del_action, SIGNAL(triggered(bool)), this, SLOT(delete_self())); + + menu.exec(container->title_bar->mapToGlobal(pos)); +} + +void Effect::delete_self() { + EffectDeleteCommand* command = new EffectDeleteCommand(); + command->clips.append(parent_clip); + command->fx.append(get_index_in_clip()); + undo_stack.push(command); + update_ui(true); +} + +void Effect::move_up() { + MoveEffectCommand* command = new MoveEffectCommand(); + command->clip = parent_clip; + command->from = get_index_in_clip(); + command->to = command->from - 1; + undo_stack.push(command); + update_ui(true); +} + +void Effect::move_down() { + MoveEffectCommand* command = new MoveEffectCommand(); + command->clip = parent_clip; + command->from = get_index_in_clip(); + command->to = command->from + 1; + undo_stack.push(command); + update_ui(true); +} + +int Effect::get_index_in_clip() { + if (parent_clip != NULL) { + for (int i=0;ieffects.size();i++) { + if (parent_clip->effects.at(i) == this) { + return i; + } + } + } + return -1; +} + bool Effect::is_enabled() { return container->enabled_check->isChecked(); } diff --git a/effects/effect.h b/effects/effect.h index f2a267847..a14ba272e 100644 --- a/effects/effect.h +++ b/effects/effect.h @@ -228,6 +228,11 @@ public: virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); public slots: void field_changed(); +private slots: + void show_context_menu(const QPoint&); + void delete_self(); + void move_up(); + void move_down(); protected: // glsl effect QOpenGLShaderProgram* glslProgram; @@ -254,6 +259,7 @@ private: bool valueHasChanged(double timecode); QVector cachedValues; void delete_texture(); + int get_index_in_clip(); }; #endif // EFFECT_H diff --git a/effects/effects/huesatbri.frag b/effects/effects/huesatbri.frag new file mode 100644 index 000000000..21f0fcecb --- /dev/null +++ b/effects/effects/huesatbri.frag @@ -0,0 +1,42 @@ +#version 110 + +uniform float hue; +uniform float saturation; +uniform float brightness; + +uniform sampler2D myTexture; +varying vec2 vTexCoord; + +vec3 rgb2hsv(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +vec3 hsv2rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +void main(void) { + vec4 tex_color = texture2D(myTexture, vTexCoord); + + vec3 hsv = rgb2hsv(tex_color.rgb); + hsv.r += (hue/360.0); + hsv.g *= (saturation*0.01); + hsv.b *= (brightness*0.01); + + vec3 rgb = hsv2rgb(hsv); + + gl_FragColor = vec4( + rgb.r, + rgb.g, + rgb.b, + tex_color.a + ); +} \ No newline at end of file diff --git a/effects/effects/huesatbri.xml b/effects/effects/huesatbri.xml new file mode 100644 index 000000000..b20b5219b --- /dev/null +++ b/effects/effects/huesatbri.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/project/undo.cpp b/project/undo.cpp index 8740a452f..d794730ff 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -1712,3 +1712,15 @@ void UpdateFootageTooltip::undo() { void UpdateFootageTooltip::redo() { update_footage_tooltip(item, media); } + +MoveEffectCommand::MoveEffectCommand() : + old_project_changed(mainWindow->isWindowModified()) +{} + +void MoveEffectCommand::undo() { + clip->effects.move(to, from); +} + +void MoveEffectCommand::redo() { + clip->effects.move(from, to); +} diff --git a/project/undo.h b/project/undo.h index f00fe0e43..f5566d4c4 100644 --- a/project/undo.h +++ b/project/undo.h @@ -545,4 +545,16 @@ private: Media* media; }; +class MoveEffectCommand : public QUndoCommand { +public: + MoveEffectCommand(); + void undo(); + void redo(); + Clip* clip; + int from; + int to; +private: + bool old_project_changed; +}; + #endif // UNDO_H diff --git a/ui/collapsiblewidget.cpp b/ui/collapsiblewidget.cpp index 78c360614..f9622b03a 100644 --- a/ui/collapsiblewidget.cpp +++ b/ui/collapsiblewidget.cpp @@ -40,6 +40,7 @@ CollapsibleWidget::CollapsibleWidget(QWidget* parent) : QWidget(parent) { connect(title_bar, SIGNAL(select(bool, bool)), this, SLOT(header_click(bool, bool))); + contents = NULL; } @@ -89,7 +90,9 @@ void CollapsibleWidget::on_visible_change() { emit visibleChanged(); } -CollapsibleWidgetHeader::CollapsibleWidgetHeader(QWidget* parent) : QWidget(parent), selected(false) {} +CollapsibleWidgetHeader::CollapsibleWidgetHeader(QWidget* parent) : QWidget(parent), selected(false) { + setContextMenuPolicy(Qt::CustomContextMenu); +} void CollapsibleWidgetHeader::mousePressEvent(QMouseEvent* event) { if (selected) {