diff --git a/effects/chromakey.frag b/effects/chromakey.frag
new file mode 100644
index 000000000..0365badc7
--- /dev/null
+++ b/effects/chromakey.frag
@@ -0,0 +1,55 @@
+/*a fast implementation of the chromakey program
+(c) 2008 Edward Cannon (adapted to GLSL by Olive Team)
+feel free to use or modify at will*/
+
+/*the follwing three functions convert RGB into YCbCr in the same manner as in JPEG images*/
+
+uniform sampler2D tex;
+varying vec2 vTexCoord;
+
+uniform vec3 key_color;
+uniform float tola;
+uniform float tolb;
+uniform bool opt;
+
+float rgb2y (vec3 c) {
+ /*a utility function to convert colors in RGB into YCbCr*/
+ return (0.299*c.r + 0.587*c.g + 0.114*c.b);
+}
+
+float rgb2cb (vec3 c) {
+ /*a utility function to convert colors in RGB into YCbCr*/
+ return (0.5 + -0.168736*c.r - 0.331264*c.g + 0.5*c.b);
+}
+
+float rgb2cr (vec3 c) {
+ /*a utility function to convert colors in RGB into YCbCr*/
+ return (0.5 + 0.5*c.r - 0.418688*c.g - 0.081312*c.b);
+}
+
+float colorclose(float Cb_p,float Cr_p,float Cb_key,float Cr_key,float tola,float tolb) {
+ /*decides if a color is close to the specified hue*/
+ float temp = sqrt(((Cb_key-Cb_p)*(Cb_key-Cb_p))+((Cr_key-Cr_p)*(Cr_key-Cr_p)));
+ if (temp < tola) {return (0.0);}
+ if (temp < tolb) {return ((temp-tola)/(tolb-tola));}
+ return (1.0);
+}
+
+void main(void) {
+ float cb_key = rgb2cb(key_color);
+ float cr_key = rgb2cr(key_color);
+
+ vec4 texture_color = texture2D(tex, vTexCoord);
+
+ float cb = rgb2cb(texture_color.rgb);
+ float cr = rgb2cr(texture_color.rgb);
+ float mask = colorclose(cb, cr, cb_key, cr_key, (tola/100.0), (tolb/100.0));
+ float submask = 1.0-mask;
+
+ texture_color.r = max(texture_color.r - submask*key_color.r, 0.0) + submask;
+ texture_color.g = max(texture_color.g - submask*key_color.g, 0.0) + submask;
+ texture_color.b = max(texture_color.b - submask*key_color.b, 0.0) + submask;
+ texture_color.a *= mask;
+
+ gl_FragColor = texture_color;
+}
\ No newline at end of file
diff --git a/effects/chromakey.xml b/effects/chromakey.xml
new file mode 100644
index 000000000..0ee7c9dbf
--- /dev/null
+++ b/effects/chromakey.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/effects/common.frag b/effects/common.frag
index f0a667b18..560ccee97 100644
--- a/effects/common.frag
+++ b/effects/common.frag
@@ -4,6 +4,6 @@ uniform sampler2D tex;
varying vec2 vTexCoord;
void main(void) {
- vec4 textureColor = texture2D(tex, vec2(vTexCoord.x, vTexCoord.y));
+ vec4 textureColor = texture2D(tex, vTexCoord);
gl_FragColor = textureColor;
}
\ No newline at end of file
diff --git a/project/effect.cpp b/project/effect.cpp
index 0c7c55d5b..c52b26d12 100644
--- a/project/effect.cpp
+++ b/project/effect.cpp
@@ -781,7 +781,7 @@ void Effect::process_shader(double timecode, GLTextureCoords&) {
glslProgram->setUniformValue(field->id.toLatin1().constData(), (GLfloat) field->get_double_value(timecode));
break;
case EFFECT_FIELD_COLOR:
- glslProgram->setUniformValue(field->id.toLatin1().constData(), field->get_color_value(timecode));
+ glslProgram->setUniformValue(field->id.toLatin1().constData(), field->get_color_value(timecode).redF(), field->get_color_value(timecode).greenF(), field->get_color_value(timecode).blueF());
break;
case EFFECT_FIELD_STRING: break; // can you even send a string to a uniform value?
case EFFECT_FIELD_BOOL:
diff --git a/project/undo.cpp b/project/undo.cpp
index 780bac2d7..c7aeca279 100644
--- a/project/undo.cpp
+++ b/project/undo.cpp
@@ -116,10 +116,7 @@ void DeleteClipAction::redo() {
// remove ref to clip
ref = seq->clips.at(index);
if (ref->open) {
- dout << "closing clip before deleting";
close_clip(ref);
- if (ref->multithreaded) ref->cacher->wait();
- dout << "FINISHED closing clip before deleting";
}
seq->clips[index] = NULL;
diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp
index f8586f85b..ab2e6bb84 100644
--- a/ui/timelinewidget.cpp
+++ b/ui/timelinewidget.cpp
@@ -324,7 +324,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
void TimelineWidget::dragMoveEvent(QDragMoveEvent *event) {
if (sequence != NULL && panel_timeline->importing) {
QPoint pos = event->pos();
- update_ghosts(pos);
+ update_ghosts(pos, event->keyboardModifiers() & Qt::ShiftModifier);
panel_timeline->move_insert = ((event->keyboardModifiers() & Qt::ControlModifier) && (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing));
update_ui(false);
}
@@ -1101,9 +1101,9 @@ void TimelineWidget::init_ghosts() {
}
}
-void TimelineWidget::update_ghosts(const QPoint& mouse_pos) {
- int mouse_track = getTrackFromScreenPoint(mouse_pos.y());
- long frame_diff = panel_timeline->getTimelineFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start;
+void TimelineWidget::update_ghosts(const QPoint& mouse_pos, bool lock_frame) {
+ int mouse_track = getTrackFromScreenPoint(mouse_pos.y());
+ long frame_diff = (lock_frame) ? 0 : panel_timeline->getTimelineFrameFromScreenPoint(mouse_pos.x()) - panel_timeline->drag_frame_start;
int track_diff = ((panel_timeline->tool == TIMELINE_TOOL_SLIDE || panel_timeline->transition_select != TA_NO_TRANSITION) && !panel_timeline->importing) ? 0 : mouse_track - panel_timeline->drag_track_start;
long validator;
long earliest_in_point = LONG_MAX;
@@ -1411,7 +1411,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
if (sequence != NULL) {
bool alt = (event->modifiers() & Qt::AltModifier);
- panel_timeline->cursor_frame = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x());
+ panel_timeline->cursor_frame = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x());
panel_timeline->cursor_track = getTrackFromScreenPoint(event->pos().y());
panel_timeline->move_insert = ((event->modifiers() & Qt::ControlModifier) && (panel_timeline->tool == TIMELINE_TOOL_POINTER || panel_timeline->importing || panel_timeline->creating));
@@ -1491,8 +1491,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
panel_timeline->calculate_track_height(track_target, new_height);
update();
} else if (panel_timeline->moving_proc) {
- QPoint pos = event->pos();
- update_ghosts(pos);
+ update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier);
} else {
// set up movement
// create ghosts
@@ -1907,7 +1906,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
} else if (panel_timeline->tool == TIMELINE_TOOL_TRANSITION) {
if (panel_timeline->transition_tool_init) {
if (panel_timeline->transition_tool_proc) {
- update_ghosts(event->pos());
+ update_ghosts(event->pos(), event->modifiers() & Qt::ShiftModifier);
} else {
Clip* c = sequence->clips.at(panel_timeline->transition_tool_pre_clip);
diff --git a/ui/timelinewidget.h b/ui/timelinewidget.h
index 29db1b980..07c6b6248 100644
--- a/ui/timelinewidget.h
+++ b/ui/timelinewidget.h
@@ -46,7 +46,7 @@ protected:
void wheelEvent(QWheelEvent *event);
private:
void init_ghosts();
- void update_ghosts(const QPoint &mouse_pos);
+ void update_ghosts(const QPoint& mouse_pos, bool lock_frame);
bool is_track_visible(int track);
int getTrackFromScreenPoint(int y);
int getScreenPointFromTrack(int track);
diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp
index fe36a4bbc..e1bfe35d2 100644
--- a/ui/viewerwidget.cpp
+++ b/ui/viewerwidget.cpp
@@ -352,7 +352,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio)
int half_height = s->height/2;
if (rendering || !nests.isEmpty()) half_height = -half_height; // invert vertical
glPushMatrix();
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 1.0, 1.0);
glLoadIdentity();
glOrtho(-half_width, half_width, half_height, -half_height, -1, 1);