added rudimentary shake effect

This commit is contained in:
itsmattkc
2018-07-16 23:19:22 +01:00
parent 4d53cb41c1
commit 97343fb752
14 changed files with 224 additions and 6 deletions
+2
View File
@@ -13,6 +13,7 @@ void init_effects() {
audio_effect_names.resize(AUDIO_EFFECT_COUNT);
video_effect_names[VIDEO_TRANSFORM_EFFECT] = "Transform";
video_effect_names[VIDEO_SHAKE_EFFECT] = "Shake";
audio_effect_names[AUDIO_VOLUME_EFFECT] = "Volume";
audio_effect_names[AUDIO_PAN_EFFECT] = "Pan";
@@ -22,6 +23,7 @@ Effect* create_effect(int effect_id, Clip* c) {
if (c->track < 0) {
switch (effect_id) {
case VIDEO_TRANSFORM_EFFECT: return new TransformEffect(c);
case VIDEO_SHAKE_EFFECT: return new ShakeEffect(c);
}
} else {
switch (effect_id) {
+30
View File
@@ -11,6 +11,7 @@ class LabelSlider;
enum VideoEffects {
VIDEO_TRANSFORM_EFFECT,
VIDEO_SHAKE_EFFECT,
VIDEO_EFFECT_COUNT
};
@@ -52,6 +53,35 @@ private:
int default_anchor_y;
};
class ShakeEffect : public Effect {
Q_OBJECT
public:
ShakeEffect(Clip* c);
void process_gl(int* anchor_x, int* anchor_y);
Effect* copy(Clip *c);
void load(QXmlStreamReader* stream);
void save(QXmlStreamWriter* stream);
LabelSlider* intensity_val;
LabelSlider* rotation_val;
LabelSlider* frequency_val;
private slots:
void set_values();
private:
int shake_progress;
int shake_limit;
int next_x;
int next_y;
int next_rot;
int offset_x;
int offset_y;
int offset_rot;
int prev_x;
int prev_y;
int prev_rot;
double t;
};
// audio effects
class VolumeEffect : public Effect {
public:
+122
View File
@@ -0,0 +1,122 @@
#include "effects/effects.h"
#include <QGridLayout>
#include <QLabel>
#include <QtMath>
#include <QOpenGLFunctions>
#include <QDebug>
#include "ui/labelslider.h"
#include "ui/collapsiblewidget.h"
#include "project/clip.h"
#include "project/sequence.h"
#include "panels/timeline.h"
ShakeEffect::ShakeEffect(Clip *c) : Effect(c) {
setup_effect(EFFECT_TYPE_VIDEO, VIDEO_SHAKE_EFFECT);
QGridLayout* ui_layout = new QGridLayout();
ui_layout->addWidget(new QLabel("Intensity:"), 0, 0);
intensity_val = new LabelSlider();
intensity_val->set_minimum_value(0);
ui_layout->addWidget(intensity_val, 0, 1);
ui_layout->addWidget(new QLabel("Rotation:"), 1, 0);
rotation_val = new LabelSlider();
rotation_val->set_minimum_value(0);
ui_layout->addWidget(rotation_val, 1, 1);
ui_layout->addWidget(new QLabel("Frequency:"), 2, 0);
frequency_val = new LabelSlider();
frequency_val->set_minimum_value(0);
ui_layout->addWidget(frequency_val, 2, 1);
ui->setLayout(ui_layout);
container->setContents(ui);
// set defaults
intensity_val->set_value(50);
rotation_val->set_value(0);
frequency_val->set_value(10);
set_values();
connect(intensity_val, SIGNAL(valueChanged()), this, SLOT(field_changed()));
connect(rotation_val, SIGNAL(valueChanged()), this, SLOT(field_changed()));
connect(frequency_val, SIGNAL(valueChanged()), this, SLOT(field_changed()));
connect(intensity_val, SIGNAL(valueChanged()), this, SLOT(set_values()));
connect(rotation_val, SIGNAL(valueChanged()), this, SLOT(set_values()));
connect(frequency_val, SIGNAL(valueChanged()), this, SLOT(set_values()));
}
void ShakeEffect::set_values() {
shake_limit = qRound(parent_clip->sequence->frame_rate / frequency_val->value());
shake_progress = shake_limit;
next_x = 0;
next_y = 0;
next_rot = 0;
}
Effect* ShakeEffect::copy(Clip* c) {
ShakeEffect* e = new ShakeEffect(c);
e->intensity_val->set_value(intensity_val->value());
e->rotation_val->set_value(rotation_val->value());
e->frequency_val->set_value(frequency_val->value());
return e;
}
void ShakeEffect::load(QXmlStreamReader* reader) {
const QXmlStreamAttributes& attr = reader->attributes();
for (int i=0;i<attr.size();i++) {
const QXmlStreamAttribute& a = attr.at(i);
if (a.name() == "intensity") {
intensity_val->set_value(a.value().toFloat());
} else if (a.name() == "rotation") {
rotation_val->set_value(a.value().toFloat());
} else if (a.name() == "frequency") {
frequency_val->set_value(a.value().toFloat());
}
}
}
void ShakeEffect::save(QXmlStreamWriter* stream) {
stream->writeAttribute("intensity", QString::number(intensity_val->value()));
stream->writeAttribute("rotation", QString::number(rotation_val->value()));
stream->writeAttribute("frequency", QString::number(frequency_val->value()));
}
void ShakeEffect::process_gl(int*, int*) {
if (shake_progress > shake_limit) {
if (intensity_val->value() > 0) {
prev_x = next_x;
prev_y = next_y;
next_x = (qrand() % (int) (intensity_val->value() * 2)) - intensity_val->value();
next_y = (qrand() % (int) (intensity_val->value() * 2)) - intensity_val->value();
} else {
prev_x = 0;
prev_y = 0;
next_x = 0;
next_y = 0;
offset_x = 0;
offset_y = 0;
}
if (rotation_val->value() > 0) {
prev_rot = next_rot;
next_rot = (qrand() % (int) (rotation_val->value() * 2)) - rotation_val->value();
} else {
prev_rot = 0;
next_rot = 0;
offset_rot = 0;
}
shake_progress = 0;
}
t = 1 - qPow(((double) shake_progress / (double) shake_limit)-1, 2);
offset_x = lerp(prev_x, next_x, t);
offset_y = lerp(prev_y, next_y, t);
offset_rot = lerp(prev_rot, next_rot, t);
glTranslatef(offset_x, offset_y, 0);
glRotatef(offset_rot, 0, 0, 1);
shake_progress++;
}
+1
View File
@@ -14,6 +14,7 @@ bool custom_scale = false;
bool saved_layout = false;
bool left_mouse_dominant = true;
bool show_track_lines = false;
bool scroll_zooms = false;
void load_config() {
/*if (!custom_scale) {
+2
View File
@@ -10,6 +10,8 @@ extern bool custom_scale;
extern bool saved_layout;
extern bool show_track_lines;
extern bool scroll_zooms;
void load_config();
void save_config();
+6
View File
@@ -540,6 +540,7 @@ void MainWindow::toolMenu_About_To_Be_Shown() {
ui->actionSelecting_Also_Seeks->setChecked(panel_timeline->select_also_seeks);
ui->actionSeek_to_the_End_of_Pastes->setChecked(panel_timeline->paste_seeks);
ui->actionToggle_Snapping->setChecked(panel_timeline->snapping);
ui->actionScroll_Wheel_Zooms->setChecked(scroll_zooms);
}
void MainWindow::on_actionEdit_Tool_Selects_Links_triggered() {
@@ -609,3 +610,8 @@ void MainWindow::load_recent_project() {
panel_project->load_project();
}
}
void MainWindow::on_actionScroll_Wheel_Zooms_triggered()
{
scroll_zooms = !scroll_zooms;
}
+2
View File
@@ -150,6 +150,8 @@ private slots:
void load_recent_project();
void on_actionScroll_Wheel_Zooms_triggered();
private:
Ui::MainWindow *ui;
void setup_layout();
+9
View File
@@ -139,6 +139,7 @@
<addaction name="actionEdit_Tool_Also_Seeks"/>
<addaction name="actionEdit_Tool_Selects_Links"/>
<addaction name="actionSeek_to_the_End_of_Pastes"/>
<addaction name="actionScroll_Wheel_Zooms"/>
<addaction name="separator"/>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
@@ -600,6 +601,14 @@
<string>Clear Recent List</string>
</property>
</action>
<action name="actionScroll_Wheel_Zooms">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Scroll Wheel Zooms</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
+5 -2
View File
@@ -59,7 +59,9 @@ SOURCES += \
effects/transition.cpp \
effects/crossdissolvetransition.cpp \
ui/audiomonitor.cpp \
project/undo.cpp
project/undo.cpp \
ui/scrollarea.cpp \
effects/shakeeffect.cpp
HEADERS += \
mainwindow.h \
@@ -93,7 +95,8 @@ HEADERS += \
dialogs/preferencesdialog.h \
effects/transition.h \
ui/audiomonitor.h \
project/undo.h
project/undo.h \
ui/scrollarea.h
FORMS += \
mainwindow.ui \
+4 -3
View File
@@ -329,8 +329,8 @@ void Timeline::delete_selection(bool ripple_delete) {
}
}
int lerp(int a, int b, float t) {
return ((1.0f - t) * a) + (t * b);
int lerp(int a, int b, double t) {
return ((1.0 - t) * a) + (t * b);
}
void Timeline::set_zoom(bool in) {
@@ -343,7 +343,7 @@ void Timeline::set_zoom(bool in) {
lerp(
ui->timeline_area->horizontalScrollBar()->value(),
getScreenPointFromFrame(playhead) - (ui->timeline_area->width()/2),
0.99f
0.99
)
);
redraw_all_clips(false);
@@ -653,6 +653,7 @@ void Timeline::paste() {
// create copy of clip and offset by playhead
Clip* cc = c->copy();
cc->sequence = sequence;
cc->timeline_in += playhead;
cc->timeline_out += playhead;
cc->track = c->track;
+2
View File
@@ -16,6 +16,8 @@ struct Clip;
struct Media;
struct MediaStream;
int lerp(int a, int b, double t);
struct Ghost {
int clip;
long in;
+7 -1
View File
@@ -346,7 +346,7 @@
</widget>
</item>
<item>
<widget class="QScrollArea" name="timeline_area">
<widget class="ScrollArea" name="timeline_area">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
@@ -459,6 +459,12 @@
<header>ui/audiomonitor.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ScrollArea</class>
<extends>QScrollArea</extends>
<header>ui/scrollarea.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../icons/icons.qrc"/>
+19
View File
@@ -0,0 +1,19 @@
#include "scrollarea.h"
#include <QWheelEvent>
#include <QDebug>
#include "io/config.h"
#include "panels/panels.h"
#include "panels/timeline.h"
ScrollArea::ScrollArea(QWidget* parent) : QScrollArea(parent) {}
void ScrollArea::wheelEvent(QWheelEvent *e) {
if (scroll_zooms) {
e->ignore();
if (e->angleDelta().y() != 0) panel_timeline->set_zoom(e->angleDelta().y() < 0);
} else {
QScrollArea::wheelEvent(e);
}
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef SCROLLAREA_H
#define SCROLLAREA_H
#include <QScrollArea>
class ScrollArea : public QScrollArea
{
public:
ScrollArea(QWidget* parent = 0);
void wheelEvent(QWheelEvent *);
};
#endif // SCROLLAREA_H