diff --git a/effects/internal/audionoiseeffect.cpp b/effects/internal/audionoiseeffect.cpp index bd0283a5b..effd65f6e 100644 --- a/effects/internal/audionoiseeffect.cpp +++ b/effects/internal/audionoiseeffect.cpp @@ -4,15 +4,15 @@ #include AudioNoiseEffect::AudioNoiseEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE, "amount"); + amount_val = add_row("Amount")->add_field(EFFECT_FIELD_DOUBLE, "amount"); amount_val->set_double_minimum_value(0); amount_val->set_double_maximum_value(100); - amount_val->set_double_default_value(20); + amount_val->set_double_default_value(20); - mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); + mix_val = add_row("Mix")->add_field(EFFECT_FIELD_BOOL, "mix"); mix_val->set_bool_value(true); - srand(QDateTime::currentMSecsSinceEpoch()); + srand(QDateTime::currentMSecsSinceEpoch()); } void AudioNoiseEffect::process_audio(double timecode_start, double timecode_end, quint8 *samples, int nb_bytes, int) { diff --git a/effects/internal/cornerpineffect.cpp b/effects/internal/cornerpineffect.cpp index 96069b0bf..5be93b671 100644 --- a/effects/internal/cornerpineffect.cpp +++ b/effects/internal/cornerpineffect.cpp @@ -5,59 +5,59 @@ #include "debug.h" CornerPinEffect::CornerPinEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { - enable_coords = true; + enable_coords = true; enable_shader = true; - EffectRow* top_left = add_row("Top Left:"); - top_left_x = top_left->add_field(EFFECT_FIELD_DOUBLE, "topleftx"); - top_left_y = top_left->add_field(EFFECT_FIELD_DOUBLE, "toplefty"); + EffectRow* top_left = add_row("Top Left"); + top_left_x = top_left->add_field(EFFECT_FIELD_DOUBLE, "topleftx"); + top_left_y = top_left->add_field(EFFECT_FIELD_DOUBLE, "toplefty"); - EffectRow* top_right = add_row("Top Right:"); - top_right_x = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprightx"); - top_right_y = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprighty"); + EffectRow* top_right = add_row("Top Right"); + top_right_x = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprightx"); + top_right_y = top_right->add_field(EFFECT_FIELD_DOUBLE, "toprighty"); - EffectRow* bottom_left = add_row("Bottom Left:"); - bottom_left_x = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomleftx"); - bottom_left_y = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomlefty"); + EffectRow* bottom_left = add_row("Bottom Left"); + bottom_left_x = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomleftx"); + bottom_left_y = bottom_left->add_field(EFFECT_FIELD_DOUBLE, "bottomlefty"); - EffectRow* bottom_right = add_row("Bottom Right:"); - bottom_right_x = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrightx"); - bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrighty"); + EffectRow* bottom_right = add_row("Bottom Right"); + bottom_right_x = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrightx"); + bottom_right_y = bottom_right->add_field(EFFECT_FIELD_DOUBLE, "bottomrighty"); - perspective = add_row("Perspective:")->add_field(EFFECT_FIELD_BOOL, "perspective"); - perspective->set_bool_value(true); + perspective = add_row("Perspective")->add_field(EFFECT_FIELD_BOOL, "perspective"); + perspective->set_bool_value(true); - top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_left_gizmo->x_field1 = top_left_x; - top_left_gizmo->y_field1 = top_left_y; + top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_left_gizmo->x_field1 = top_left_x; + top_left_gizmo->y_field1 = top_left_y; - top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_right_gizmo->x_field1 = top_right_x; - top_right_gizmo->y_field1 = top_right_y; + top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_right_gizmo->x_field1 = top_right_x; + top_right_gizmo->y_field1 = top_right_y; - bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_left_gizmo->x_field1 = bottom_left_x; - bottom_left_gizmo->y_field1 = bottom_left_y; + bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_left_gizmo->x_field1 = bottom_left_x; + bottom_left_gizmo->y_field1 = bottom_left_y; - bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_right_gizmo->x_field1 = bottom_right_x; - bottom_right_gizmo->y_field1 = bottom_right_y; + bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_right_gizmo->x_field1 = bottom_right_x; + bottom_right_gizmo->y_field1 = bottom_right_y; vertPath = "cornerpin.vert"; fragPath = "cornerpin.frag"; } void CornerPinEffect::process_coords(double timecode, GLTextureCoords &coords, int data) { - coords.vertexTopLeftX += top_left_x->get_double_value(timecode); - coords.vertexTopLeftY += top_left_y->get_double_value(timecode); + coords.vertexTopLeftX += top_left_x->get_double_value(timecode); + coords.vertexTopLeftY += top_left_y->get_double_value(timecode); - coords.vertexTopRightX += top_right_x->get_double_value(timecode); - coords.vertexTopRightY += top_right_y->get_double_value(timecode); + coords.vertexTopRightX += top_right_x->get_double_value(timecode); + coords.vertexTopRightY += top_right_y->get_double_value(timecode); - coords.vertexBottomLeftX += bottom_left_x->get_double_value(timecode); - coords.vertexBottomLeftY += bottom_left_y->get_double_value(timecode); + coords.vertexBottomLeftX += bottom_left_x->get_double_value(timecode); + coords.vertexBottomLeftY += bottom_left_y->get_double_value(timecode); - coords.vertexBottomRightX += bottom_right_x->get_double_value(timecode); + coords.vertexBottomRightX += bottom_right_x->get_double_value(timecode); coords.vertexBottomRightY += bottom_right_y->get_double_value(timecode); } @@ -66,12 +66,12 @@ void CornerPinEffect::process_shader(double timecode, GLTextureCoords &coords) { glslProgram->setUniformValue("p1", (GLfloat) coords.vertexBottomRightX, (GLfloat) coords.vertexBottomRightY); glslProgram->setUniformValue("p2", (GLfloat) coords.vertexTopLeftX, (GLfloat) coords.vertexTopLeftY); glslProgram->setUniformValue("p3", (GLfloat) coords.vertexTopRightX, (GLfloat) coords.vertexTopRightY); - glslProgram->setUniformValue("perspective", perspective->get_bool_value(timecode)); + glslProgram->setUniformValue("perspective", perspective->get_bool_value(timecode)); } void CornerPinEffect::gizmo_draw(double timecode, GLTextureCoords &coords) { - top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); - top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); - bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); - bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); } diff --git a/effects/internal/paneffect.cpp b/effects/internal/paneffect.cpp index 0a7b25a58..fcb862192 100644 --- a/effects/internal/paneffect.cpp +++ b/effects/internal/paneffect.cpp @@ -9,13 +9,13 @@ #include "ui/collapsiblewidget.h" PanEffect::PanEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - EffectRow* pan_row = add_row("Pan:"); - pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE, "pan"); + EffectRow* pan_row = add_row("Pan"); + pan_val = pan_row->add_field(EFFECT_FIELD_DOUBLE, "pan"); pan_val->set_double_minimum_value(-100); - pan_val->set_double_maximum_value(100); + pan_val->set_double_maximum_value(100); // set defaults - pan_val->set_double_default_value(0); + pan_val->set_double_default_value(0); } void PanEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { diff --git a/effects/internal/shakeeffect.cpp b/effects/internal/shakeeffect.cpp index 0687a71ad..92975fe8a 100644 --- a/effects/internal/shakeeffect.cpp +++ b/effects/internal/shakeeffect.cpp @@ -16,19 +16,19 @@ ShakeEffect::ShakeEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { enable_coords = true; - EffectRow* intensity_row = add_row("Intensity:"); - intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE, "intensity"); + EffectRow* intensity_row = add_row("Intensity"); + intensity_val = intensity_row->add_field(EFFECT_FIELD_DOUBLE, "intensity"); intensity_val->set_double_minimum_value(0); - EffectRow* rotation_row = add_row("Rotation:"); - rotation_val = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); + EffectRow* rotation_row = add_row("Rotation"); + rotation_val = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); rotation_val->set_double_minimum_value(0); - EffectRow* frequency_row = add_row("Frequency:"); - frequency_val = frequency_row->add_field(EFFECT_FIELD_DOUBLE, "frequency"); + EffectRow* frequency_row = add_row("Frequency"); + frequency_val = frequency_row->add_field(EFFECT_FIELD_DOUBLE, "frequency"); frequency_val->set_double_minimum_value(0); - // set defaults + // set defaults intensity_val->set_double_default_value(25); rotation_val->set_double_default_value(10); frequency_val->set_double_default_value(5); diff --git a/effects/internal/solideffect.cpp b/effects/internal/solideffect.cpp index 0f888da61..512dccda6 100644 --- a/effects/internal/solideffect.cpp +++ b/effects/internal/solideffect.cpp @@ -21,36 +21,36 @@ SolidEffect::SolidEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { enable_superimpose = true; - solid_type = add_row("Type:")->add_field(EFFECT_FIELD_COMBO, "type"); + solid_type = add_row("Type")->add_field(EFFECT_FIELD_COMBO, "type"); solid_type->add_combo_item("Solid Color", SOLID_TYPE_COLOR); solid_type->add_combo_item("SMPTE Bars", SOLID_TYPE_BARS); - solid_type->add_combo_item("Checkerboard", SOLID_TYPE_CHECKERBOARD); + solid_type->add_combo_item("Checkerboard", SOLID_TYPE_CHECKERBOARD); - opacity_field = add_row("Opacity:")->add_field(EFFECT_FIELD_DOUBLE, "opacity"); - opacity_field->set_double_minimum_value(0); - opacity_field->set_double_maximum_value(100); - opacity_field->set_double_default_value(100); + opacity_field = add_row("Opacity")->add_field(EFFECT_FIELD_DOUBLE, "opacity"); + opacity_field->set_double_minimum_value(0); + opacity_field->set_double_maximum_value(100); + opacity_field->set_double_default_value(100); - solid_color_field = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, "color"); - solid_color_field->set_color_value(Qt::red); + solid_color_field = add_row("Color")->add_field(EFFECT_FIELD_COLOR, "color"); + solid_color_field->set_color_value(Qt::red); - checkerboard_size_field = add_row("Checkerboard Size:")->add_field(EFFECT_FIELD_DOUBLE, "checker_size"); - checkerboard_size_field->set_double_minimum_value(1); - checkerboard_size_field->set_double_default_value(10); + checkerboard_size_field = add_row("Checkerboard Size")->add_field(EFFECT_FIELD_DOUBLE, "checker_size"); + checkerboard_size_field->set_double_minimum_value(1); + checkerboard_size_field->set_double_default_value(10); - // hacky but eh - QComboBox* solid_type_combo = static_cast(solid_type->get_ui_element()); - connect(solid_type_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(ui_update(int))); - ui_update(solid_type_combo->currentIndex()); + // hacky but eh + QComboBox* solid_type_combo = static_cast(solid_type->get_ui_element()); + connect(solid_type_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(ui_update(int))); + ui_update(solid_type_combo->currentIndex()); - /*vertPath = ":/shaders/common.vert"; - fragPath = ":/shaders/solideffect.frag";*/ + /*vertPath = ":/shaders/common.vert"; + fragPath = ":/shaders/solideffect.frag";*/ } void SolidEffect::redraw(double timecode) { int w = img.width(); int h = img.height(); - int alpha = qRound(opacity_field->get_double_value(timecode)*2.55); + int alpha = qRound(opacity_field->get_double_value(timecode)*2.55); switch (solid_type->get_combo_data(timecode).toInt()) { case SOLID_TYPE_COLOR: { @@ -141,37 +141,37 @@ void SolidEffect::redraw(double timecode) { third_color.setAlpha(alpha); p.fillRect(QRect(bar_x, third_bar_y, third_bar_width, third_bar_height), third_color); } - } - break; - case SOLID_TYPE_CHECKERBOARD: - { - // draw checkboard - QPainter p(&img); - img.fill(Qt::transparent); + } + break; + case SOLID_TYPE_CHECKERBOARD: + { + // draw checkboard + QPainter p(&img); + img.fill(Qt::transparent); - int checker_width = qCeil(checkerboard_size_field->get_double_value(timecode)); - int checker_x, checker_y; - int checkerboard_size_w = qCeil(double(w)/checker_width); - int checkerboard_size_h = qCeil(double(h)/checker_width); + int checker_width = qCeil(checkerboard_size_field->get_double_value(timecode)); + int checker_x, checker_y; + int checkerboard_size_w = qCeil(double(w)/checker_width); + int checkerboard_size_h = qCeil(double(h)/checker_width); - QColor checker_odd(QColor(0, 0, 0, alpha)); - QColor checker_even(solid_color_field->get_color_value(timecode)); - checker_even.setAlpha(alpha); - QVector checker_color{checker_odd, checker_even}; + QColor checker_odd(QColor(0, 0, 0, alpha)); + QColor checker_even(solid_color_field->get_color_value(timecode)); + checker_even.setAlpha(alpha); + QVector checker_color{checker_odd, checker_even}; - for(int i = 0; i < checkerboard_size_w; i++){ - checker_x = checker_width*i; - for(int j = 0; j < checkerboard_size_h; j++){ - checker_y = checker_width*j; - p.fillRect(QRect(checker_x, checker_y, checker_width, checker_width), checker_color[(i + j)%2]); - } - } - } - break; - } + for(int i = 0; i < checkerboard_size_w; i++){ + checker_x = checker_width*i; + for(int j = 0; j < checkerboard_size_h; j++){ + checker_y = checker_width*j; + p.fillRect(QRect(checker_x, checker_y, checker_width, checker_width), checker_color[(i + j)%2]); + } + } + } + break; + } } void SolidEffect::ui_update(int i) { - solid_color_field->set_enabled(i == SOLID_TYPE_COLOR || i == SOLID_TYPE_CHECKERBOARD); - checkerboard_size_field->set_enabled(i == SOLID_TYPE_CHECKERBOARD); + solid_color_field->set_enabled(i == SOLID_TYPE_COLOR || i == SOLID_TYPE_CHECKERBOARD); + checkerboard_size_field->set_enabled(i == SOLID_TYPE_CHECKERBOARD); } diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index 66a6a6108..cb3ea3155 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -24,43 +24,43 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) : Effect(c, em) { enable_superimpose = true; - enable_shader = true; + enable_shader = true; - text_val = add_row("Text:")->add_field(EFFECT_FIELD_STRING, "text", 2); + text_val = add_row("Text")->add_field(EFFECT_FIELD_STRING, "text", 2); - set_font_combobox = add_row("Font:")->add_field(EFFECT_FIELD_FONT, "font", 2); + set_font_combobox = add_row("Font")->add_field(EFFECT_FIELD_FONT, "font", 2); - size_val = add_row("Size:")->add_field(EFFECT_FIELD_DOUBLE, "size", 2); - size_val->set_double_minimum_value(0); + size_val = add_row("Size")->add_field(EFFECT_FIELD_DOUBLE, "size", 2); + size_val->set_double_minimum_value(0); - set_color_button = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, "color", 2); + set_color_button = add_row("Color")->add_field(EFFECT_FIELD_COLOR, "color", 2); - EffectRow* alignment_row = add_row("Alignment:"); - halign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "halign"); + EffectRow* alignment_row = add_row("Alignment"); + halign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "halign"); halign_field->add_combo_item("Left", Qt::AlignLeft); halign_field->add_combo_item("Center", Qt::AlignHCenter); halign_field->add_combo_item("Right", Qt::AlignRight); - halign_field->add_combo_item("Justify", Qt::AlignJustify); + halign_field->add_combo_item("Justify", Qt::AlignJustify); - valign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "valign"); + valign_field = alignment_row->add_field(EFFECT_FIELD_COMBO, "valign"); valign_field->add_combo_item("Top", Qt::AlignTop); valign_field->add_combo_item("Center", Qt::AlignVCenter); - valign_field->add_combo_item("Bottom", Qt::AlignBottom); + valign_field->add_combo_item("Bottom", Qt::AlignBottom); - word_wrap_field = add_row("Word Wrap:")->add_field(EFFECT_FIELD_BOOL, "wordwrap", 2); + word_wrap_field = add_row("Word Wrap")->add_field(EFFECT_FIELD_BOOL, "wordwrap", 2); - outline_bool = add_row("Outline:")->add_field(EFFECT_FIELD_BOOL, "outline", 2); - outline_color = add_row("Outline Color:")->add_field(EFFECT_FIELD_COLOR, "outlinecolor", 2); - outline_width = add_row("Outline Width:")->add_field(EFFECT_FIELD_DOUBLE, "outlinewidth", 2); + outline_bool = add_row("Outline")->add_field(EFFECT_FIELD_BOOL, "outline", 2); + outline_color = add_row("Outline Color")->add_field(EFFECT_FIELD_COLOR, "outlinecolor", 2); + outline_width = add_row("Outline Width")->add_field(EFFECT_FIELD_DOUBLE, "outlinewidth", 2); outline_width->set_double_minimum_value(0); - shadow_bool = add_row("Shadow:")->add_field(EFFECT_FIELD_BOOL, "shadow", 2); - shadow_color = add_row("Shadow Color:")->add_field(EFFECT_FIELD_COLOR, "shadowcolor", 2); - shadow_distance = add_row("Shadow Distance:")->add_field(EFFECT_FIELD_DOUBLE, "shadowdistance", 2); + shadow_bool = add_row("Shadow")->add_field(EFFECT_FIELD_BOOL, "shadow", 2); + shadow_color = add_row("Shadow Color")->add_field(EFFECT_FIELD_COLOR, "shadowcolor", 2); + shadow_distance = add_row("Shadow Distance")->add_field(EFFECT_FIELD_DOUBLE, "shadowdistance", 2); shadow_distance->set_double_minimum_value(0); - shadow_softness = add_row("Shadow Softness:")->add_field(EFFECT_FIELD_DOUBLE, "shadowsoftness", 2); + shadow_softness = add_row("Shadow Softness")->add_field(EFFECT_FIELD_DOUBLE, "shadowsoftness", 2); shadow_softness->set_double_minimum_value(0); - shadow_opacity = add_row("Shadow Opacity:")->add_field(EFFECT_FIELD_DOUBLE, "shadowopacity", 2); + shadow_opacity = add_row("Shadow Opacity")->add_field(EFFECT_FIELD_DOUBLE, "shadowopacity", 2); shadow_opacity->set_double_minimum_value(0); shadow_opacity->set_double_maximum_value(100); @@ -78,13 +78,13 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) : outline_width->set_double_default_value(20); outline_enable(false); - shadow_enable(false); + shadow_enable(false); connect(shadow_bool, SIGNAL(toggled(bool)), this, SLOT(shadow_enable(bool))); connect(outline_bool, SIGNAL(toggled(bool)), this, SLOT(outline_enable(bool))); - vertPath = "common.vert"; - fragPath = "dropshadow.frag"; + vertPath = "common.vert"; + fragPath = "dropshadow.frag"; } void TextEffect::redraw(double timecode) { @@ -170,7 +170,7 @@ void TextEffect::redraw(double timecode) { } path.addText(text_x, text_y, font, lines.at(i)); - } + } // draw outline int outline_width_val = outline_width->get_double_value(timecode); @@ -185,7 +185,7 @@ void TextEffect::redraw(double timecode) { // draw "master" text p.setPen(Qt::NoPen); p.setBrush(set_color_button->get_color_value(timecode)); - p.drawPath(path); + p.drawPath(path); } void TextEffect::shadow_enable(bool e) { diff --git a/effects/internal/timecodeeffect.cpp b/effects/internal/timecodeeffect.cpp index f09b7fecc..baba8c50d 100644 --- a/effects/internal/timecodeeffect.cpp +++ b/effects/internal/timecodeeffect.cpp @@ -24,82 +24,82 @@ #include "playback/playback.h" TimecodeEffect::TimecodeEffect(Clip *c, const EffectMeta* em) : - Effect(c, em) + Effect(c, em) { - enable_always_update = true; + enable_always_update = true; enable_superimpose = true; - EffectRow* tc_row = add_row("Timecode:"); - tc_select = tc_row->add_field(EFFECT_FIELD_COMBO, "tc_selector"); - tc_select->add_combo_item("Sequence", true); - tc_select->add_combo_item("Media", false); - tc_select->set_combo_index(0); + EffectRow* tc_row = add_row("Timecode"); + tc_select = tc_row->add_field(EFFECT_FIELD_COMBO, "tc_selector"); + tc_select->add_combo_item("Sequence", true); + tc_select->add_combo_item("Media", false); + tc_select->set_combo_index(0); - scale_val = add_row("Scale:")->add_field(EFFECT_FIELD_DOUBLE, "scale", 2); - scale_val->set_double_minimum_value(1); - scale_val->set_double_default_value(100); - scale_val->set_double_maximum_value(1000); + scale_val = add_row("Scale")->add_field(EFFECT_FIELD_DOUBLE, "scale", 2); + scale_val->set_double_minimum_value(1); + scale_val->set_double_default_value(100); + scale_val->set_double_maximum_value(1000); - color_val = add_row("Color:")->add_field(EFFECT_FIELD_COLOR, "color", 2); - color_val->set_color_value(Qt::white); + color_val = add_row("Color")->add_field(EFFECT_FIELD_COLOR, "color", 2); + color_val->set_color_value(Qt::white); - color_bg_val = add_row("Background Color:")->add_field(EFFECT_FIELD_COLOR, "bgcolor", 2); - color_bg_val->set_color_value(Qt::black); + color_bg_val = add_row("Background Color")->add_field(EFFECT_FIELD_COLOR, "bgcolor", 2); + color_bg_val->set_color_value(Qt::black); - bg_alpha = add_row("Background Opacity:")->add_field(EFFECT_FIELD_DOUBLE, "bgalpha", 2); - bg_alpha->set_double_minimum_value(0); - bg_alpha->set_double_maximum_value(100); - bg_alpha->set_double_default_value(50); + bg_alpha = add_row("Background Opacity")->add_field(EFFECT_FIELD_DOUBLE, "bgalpha", 2); + bg_alpha->set_double_minimum_value(0); + bg_alpha->set_double_maximum_value(100); + bg_alpha->set_double_default_value(50); - EffectRow* offset = add_row("Offset:"); - offset_x_val = offset->add_field(EFFECT_FIELD_DOUBLE, "offsetx"); - offset_y_val = offset->add_field(EFFECT_FIELD_DOUBLE, "offsety"); + EffectRow* offset = add_row("Offset"); + offset_x_val = offset->add_field(EFFECT_FIELD_DOUBLE, "offsetx"); + offset_y_val = offset->add_field(EFFECT_FIELD_DOUBLE, "offsety"); - prepend_text = add_row("Prepend:")->add_field(EFFECT_FIELD_STRING, "prepend", 2); + prepend_text = add_row("Prepend")->add_field(EFFECT_FIELD_STRING, "prepend", 2); } void TimecodeEffect::redraw(double timecode) { - if (tc_select->get_combo_data(timecode).toBool()){ - display_timecode = prepend_text->get_string_value(timecode) + frame_to_timecode(sequence->playhead, config.timecode_view, sequence->frame_rate);} - else { - double media_rate = parent_clip->getMediaFrameRate(); - display_timecode = prepend_text->get_string_value(timecode) + frame_to_timecode(timecode * media_rate, config.timecode_view, media_rate);} - img.fill(Qt::transparent); + if (tc_select->get_combo_data(timecode).toBool()){ + display_timecode = prepend_text->get_string_value(timecode) + frame_to_timecode(sequence->playhead, config.timecode_view, sequence->frame_rate);} + else { + double media_rate = parent_clip->getMediaFrameRate(); + display_timecode = prepend_text->get_string_value(timecode) + frame_to_timecode(timecode * media_rate, config.timecode_view, media_rate);} + img.fill(Qt::transparent); QPainter p(&img); - p.setRenderHint(QPainter::Antialiasing); + p.setRenderHint(QPainter::Antialiasing); int width = img.width(); int height = img.height(); // set font font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias); - font.setFamily("Helvetica"); - font.setPixelSize(qCeil(scale_val->get_double_value(timecode)*.01*(height/10))); - p.setFont(font); + font.setFamily("Helvetica"); + font.setPixelSize(qCeil(scale_val->get_double_value(timecode)*.01*(height/10))); + p.setFont(font); QFontMetrics fm(font); - QPainterPath path; + QPainterPath path; - int text_x, text_y, rect_y, offset_x, offset_y; - int text_height = fm.height(); - int text_width = fm.width(display_timecode); - QColor background_color = color_bg_val->get_color_value(timecode); - int alpha_val = bg_alpha->get_double_value(timecode)*2.55; - background_color.setAlpha(alpha_val); + int text_x, text_y, rect_y, offset_x, offset_y; + int text_height = fm.height(); + int text_width = fm.width(display_timecode); + QColor background_color = color_bg_val->get_color_value(timecode); + int alpha_val = bg_alpha->get_double_value(timecode)*2.55; + background_color.setAlpha(alpha_val); - offset_x = int(offset_x_val->get_double_value(timecode)); - offset_y = int(offset_y_val->get_double_value(timecode)); + offset_x = int(offset_x_val->get_double_value(timecode)); + offset_y = int(offset_y_val->get_double_value(timecode)); - text_x = offset_x + (width/2) - (text_width/2); - text_y = offset_y + height - height/10; - rect_y = text_y + fm.descent()/2 - text_height; + text_x = offset_x + (width/2) - (text_width/2); + text_y = offset_y + height - height/10; + rect_y = text_y + fm.descent()/2 - text_height; - path.addText(text_x, text_y, font, display_timecode); + path.addText(text_x, text_y, font, display_timecode); - p.setPen(Qt::NoPen); - p.setBrush(background_color); - p.drawRect(QRect(text_x-fm.descent()/2, rect_y, text_width+fm.descent(), text_height)); - p.setBrush(color_val->get_color_value(timecode)); - p.drawPath(path); + p.setPen(Qt::NoPen); + p.setBrush(background_color); + p.drawRect(QRect(text_x-fm.descent()/2, rect_y, text_width+fm.descent(), text_height)); + p.setBrush(color_val->get_color_value(timecode)); + p.drawPath(path); } diff --git a/effects/internal/toneeffect.cpp b/effects/internal/toneeffect.cpp index bb0fb7ac8..b17478e40 100644 --- a/effects/internal/toneeffect.cpp +++ b/effects/internal/toneeffect.cpp @@ -9,21 +9,21 @@ #include "debug.h" ToneEffect::ToneEffect(Clip* c, const EffectMeta *em) : Effect(c, em), sinX(INT_MIN) { - type_val = add_row("Type:")->add_field(EFFECT_FIELD_COMBO, "type"); + type_val = add_row("Type")->add_field(EFFECT_FIELD_COMBO, "type"); type_val->add_combo_item("Sine", TONE_TYPE_SINE); - freq_val = add_row("Frequency:")->add_field(EFFECT_FIELD_DOUBLE, "frequency"); + freq_val = add_row("Frequency")->add_field(EFFECT_FIELD_DOUBLE, "frequency"); freq_val->set_double_minimum_value(20); freq_val->set_double_maximum_value(20000); freq_val->set_double_default_value(1000); - amount_val = add_row("Amount:")->add_field(EFFECT_FIELD_DOUBLE, "amount"); + amount_val = add_row("Amount")->add_field(EFFECT_FIELD_DOUBLE, "amount"); amount_val->set_double_minimum_value(0); amount_val->set_double_maximum_value(100); amount_val->set_double_default_value(25); - mix_val = add_row("Mix:")->add_field(EFFECT_FIELD_BOOL, "mix"); - mix_val->set_bool_value(true); + mix_val = add_row("Mix")->add_field(EFFECT_FIELD_BOOL, "mix"); + mix_val->set_bool_value(true); } void ToneEffect::process_audio(double timecode_start, double timecode_end, quint8 *samples, int nb_bytes, int) { diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 42b54497c..0b7466dd5 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -28,104 +28,104 @@ #define BLEND_MODE_MULTIPLY 2 #define BLEND_MODE_OVERLAY 3 -TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { - enable_coords = true; +TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { + enable_coords = true; - EffectRow* position_row = add_row("Position:"); - position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X - position_y = position_row->add_field(EFFECT_FIELD_DOUBLE, "posy"); // position Y + EffectRow* position_row = add_row("Position"); + position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X + position_y = position_row->add_field(EFFECT_FIELD_DOUBLE, "posy"); // position Y - EffectRow* scale_row = add_row("Scale:"); - scale_x = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scalex"); // scale X (and Y is uniform scale is selected) + EffectRow* scale_row = add_row("Scale"); + scale_x = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scalex"); // scale X (and Y is uniform scale is selected) scale_x->set_double_minimum_value(0); scale_x->set_double_maximum_value(3000); - scale_y = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scaley"); // scale Y (disabled if uniform scale is selected) + scale_y = scale_row->add_field(EFFECT_FIELD_DOUBLE, "scaley"); // scale Y (disabled if uniform scale is selected) scale_y->set_double_minimum_value(0); scale_y->set_double_maximum_value(3000); - EffectRow* uniform_scale_row = add_row("Uniform Scale:"); - uniform_scale_field = uniform_scale_row->add_field(EFFECT_FIELD_BOOL, "uniformscale"); // uniform scale option + EffectRow* uniform_scale_row = add_row("Uniform Scale"); + uniform_scale_field = uniform_scale_row->add_field(EFFECT_FIELD_BOOL, "uniformscale"); // uniform scale option - EffectRow* rotation_row = add_row("Rotation:"); - rotation = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); + EffectRow* rotation_row = add_row("Rotation"); + rotation = rotation_row->add_field(EFFECT_FIELD_DOUBLE, "rotation"); - EffectRow* anchor_point_row = add_row("Anchor Point:"); - anchor_x_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchorx"); // anchor point X - anchor_y_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchory"); // anchor point Y + EffectRow* anchor_point_row = add_row("Anchor Point"); + anchor_x_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchorx"); // anchor point X + anchor_y_box = anchor_point_row->add_field(EFFECT_FIELD_DOUBLE, "anchory"); // anchor point Y - EffectRow* opacity_row = add_row("Opacity:"); - opacity = opacity_row->add_field(EFFECT_FIELD_DOUBLE, "opacity"); // opacity + EffectRow* opacity_row = add_row("Opacity"); + opacity = opacity_row->add_field(EFFECT_FIELD_DOUBLE, "opacity"); // opacity opacity->set_double_minimum_value(0); opacity->set_double_maximum_value(100); - EffectRow* blend_mode_row = add_row("Blend Mode:"); - blend_mode_box = blend_mode_row->add_field(EFFECT_FIELD_COMBO, "blendmode"); // blend mode + EffectRow* blend_mode_row = add_row("Blend Mode"); + blend_mode_box = blend_mode_row->add_field(EFFECT_FIELD_COMBO, "blendmode"); // blend mode blend_mode_box->add_combo_item("Normal", BLEND_MODE_NORMAL); blend_mode_box->add_combo_item("Overlay", BLEND_MODE_OVERLAY); blend_mode_box->add_combo_item("Screen", BLEND_MODE_SCREEN); blend_mode_box->add_combo_item("Multiply", BLEND_MODE_MULTIPLY); - // set up gizmos - top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_left_gizmo->set_cursor(Qt::SizeFDiagCursor); - top_left_gizmo->x_field1 = scale_x; + // set up gizmos + top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_left_gizmo->set_cursor(Qt::SizeFDiagCursor); + top_left_gizmo->x_field1 = scale_x; - top_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_center_gizmo->set_cursor(Qt::SizeVerCursor); - top_center_gizmo->y_field1 = scale_x; + top_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_center_gizmo->set_cursor(Qt::SizeVerCursor); + top_center_gizmo->y_field1 = scale_x; - top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - top_right_gizmo->set_cursor(Qt::SizeBDiagCursor); - top_right_gizmo->x_field1 = scale_x; + top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_right_gizmo->set_cursor(Qt::SizeBDiagCursor); + top_right_gizmo->x_field1 = scale_x; - bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_left_gizmo->set_cursor(Qt::SizeBDiagCursor); - bottom_left_gizmo->x_field1 = scale_x; + bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_left_gizmo->set_cursor(Qt::SizeBDiagCursor); + bottom_left_gizmo->x_field1 = scale_x; - bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_center_gizmo->set_cursor(Qt::SizeVerCursor); - bottom_center_gizmo->y_field1 = scale_x; + bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_center_gizmo->set_cursor(Qt::SizeVerCursor); + bottom_center_gizmo->y_field1 = scale_x; - bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); - bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor); - bottom_right_gizmo->x_field1 = scale_x; + bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_right_gizmo->set_cursor(Qt::SizeFDiagCursor); + bottom_right_gizmo->x_field1 = scale_x; - left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); - left_center_gizmo->set_cursor(Qt::SizeHorCursor); - left_center_gizmo->x_field1 = scale_x; + left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + left_center_gizmo->set_cursor(Qt::SizeHorCursor); + left_center_gizmo->x_field1 = scale_x; - right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); - right_center_gizmo->set_cursor(Qt::SizeHorCursor); - right_center_gizmo->x_field1 = scale_x; + right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + right_center_gizmo->set_cursor(Qt::SizeHorCursor); + right_center_gizmo->x_field1 = scale_x; - anchor_gizmo = add_gizmo(GIZMO_TYPE_TARGET); - anchor_gizmo->set_cursor(Qt::SizeAllCursor); - anchor_gizmo->x_field1 = anchor_x_box; - anchor_gizmo->y_field1 = anchor_y_box; - anchor_gizmo->x_field2 = position_x; - anchor_gizmo->y_field2 = position_y; + anchor_gizmo = add_gizmo(GIZMO_TYPE_TARGET); + anchor_gizmo->set_cursor(Qt::SizeAllCursor); + anchor_gizmo->x_field1 = anchor_x_box; + anchor_gizmo->y_field1 = anchor_y_box; + anchor_gizmo->x_field2 = position_x; + anchor_gizmo->y_field2 = position_y; - rotate_gizmo = add_gizmo(GIZMO_TYPE_DOT); - rotate_gizmo->color = Qt::green; - rotate_gizmo->set_cursor(Qt::SizeAllCursor); - rotate_gizmo->x_field1 = rotation; + rotate_gizmo = add_gizmo(GIZMO_TYPE_DOT); + rotate_gizmo->color = Qt::green; + rotate_gizmo->set_cursor(Qt::SizeAllCursor); + rotate_gizmo->x_field1 = rotation; - rect_gizmo = add_gizmo(GIZMO_TYPE_POLY); - rect_gizmo->x_field1 = position_x; - rect_gizmo->y_field1 = position_y; + rect_gizmo = add_gizmo(GIZMO_TYPE_POLY); + rect_gizmo->x_field1 = position_x; + rect_gizmo->y_field1 = position_y; - connect(uniform_scale_field, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool))); + connect(uniform_scale_field, SIGNAL(toggled(bool)), this, SLOT(toggle_uniform_scale(bool))); - // set defaults + // set defaults uniform_scale_field->set_bool_value(true); blend_mode_box->set_combo_index(0); refresh(); } void TransformEffect::refresh() { - if (parent_clip != NULL && parent_clip->sequence != NULL) { - double default_pos_x = parent_clip->sequence->width/2; - double default_pos_y = parent_clip->sequence->height/2; + if (parent_clip != NULL && parent_clip->sequence != NULL) { + double default_pos_x = parent_clip->sequence->width/2; + double default_pos_y = parent_clip->sequence->height/2; position_x->set_double_default_value(default_pos_x); position_y->set_double_default_value(default_pos_y); @@ -140,35 +140,35 @@ void TransformEffect::refresh() { anchor_x_box->set_double_default_value(default_anchor_x); anchor_y_box->set_double_default_value(default_anchor_y); - opacity->set_double_default_value(100); + opacity->set_double_default_value(100); - double x_percent_multipler = 200.0 / parent_clip->sequence->width; - double y_percent_multipler = 200.0 / parent_clip->sequence->height; - top_left_gizmo->x_field_multi1 = -x_percent_multipler; - top_left_gizmo->y_field_multi1 = -y_percent_multipler; - top_center_gizmo->y_field_multi1 = -y_percent_multipler; - top_right_gizmo->x_field_multi1 = x_percent_multipler; - top_right_gizmo->y_field_multi1 = -y_percent_multipler; - bottom_left_gizmo->x_field_multi1 = -x_percent_multipler; - bottom_left_gizmo->y_field_multi1 = y_percent_multipler; - bottom_center_gizmo->y_field_multi1 = y_percent_multipler; - bottom_right_gizmo->x_field_multi1 = x_percent_multipler; - bottom_right_gizmo->y_field_multi1 = y_percent_multipler; - left_center_gizmo->x_field_multi1 = -x_percent_multipler; - right_center_gizmo->x_field_multi1 = x_percent_multipler; - rotate_gizmo->x_field_multi1 = x_percent_multipler; + double x_percent_multipler = 200.0 / parent_clip->sequence->width; + double y_percent_multipler = 200.0 / parent_clip->sequence->height; + top_left_gizmo->x_field_multi1 = -x_percent_multipler; + top_left_gizmo->y_field_multi1 = -y_percent_multipler; + top_center_gizmo->y_field_multi1 = -y_percent_multipler; + top_right_gizmo->x_field_multi1 = x_percent_multipler; + top_right_gizmo->y_field_multi1 = -y_percent_multipler; + bottom_left_gizmo->x_field_multi1 = -x_percent_multipler; + bottom_left_gizmo->y_field_multi1 = y_percent_multipler; + bottom_center_gizmo->y_field_multi1 = y_percent_multipler; + bottom_right_gizmo->x_field_multi1 = x_percent_multipler; + bottom_right_gizmo->y_field_multi1 = y_percent_multipler; + left_center_gizmo->x_field_multi1 = -x_percent_multipler; + right_center_gizmo->x_field_multi1 = x_percent_multipler; + rotate_gizmo->x_field_multi1 = x_percent_multipler; } } void TransformEffect::toggle_uniform_scale(bool enabled) { scale_y->set_enabled(!enabled); - top_center_gizmo->y_field1 = enabled ? scale_x : scale_y; - bottom_center_gizmo->y_field1 = enabled ? scale_x : scale_y; - top_left_gizmo->y_field1 = enabled ? NULL : scale_y; - top_right_gizmo->y_field1 = enabled ? NULL : scale_y; - bottom_left_gizmo->y_field1 = enabled ? NULL : scale_y; - bottom_right_gizmo->y_field1 = enabled ? NULL : scale_y; + top_center_gizmo->y_field1 = enabled ? scale_x : scale_y; + bottom_center_gizmo->y_field1 = enabled ? scale_x : scale_y; + top_left_gizmo->y_field1 = enabled ? NULL : scale_y; + top_right_gizmo->y_field1 = enabled ? NULL : scale_y; + bottom_left_gizmo->y_field1 = enabled ? NULL : scale_y; + bottom_right_gizmo->y_field1 = enabled ? NULL : scale_y; } void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int data) { @@ -188,51 +188,51 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i coords.vertexBottomRightY -= anchor_y_offset; // rotation - glRotatef(rotation->get_double_value(timecode), 0, 0, 1); + glRotatef(rotation->get_double_value(timecode), 0, 0, 1); // scale float sx = scale_x->get_double_value(timecode)*0.01; float sy = (uniform_scale_field->get_bool_value(timecode)) ? sx : scale_y->get_double_value(timecode)*0.01; - glScalef(sx, sy, 1); + glScalef(sx, sy, 1); - // blend mode + // blend mode switch (blend_mode_box->get_combo_data(timecode).toInt()) { - case BLEND_MODE_NORMAL: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case BLEND_MODE_OVERLAY: + case BLEND_MODE_NORMAL: + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case BLEND_MODE_OVERLAY: glBlendFunc(GL_SRC_ALPHA, GL_ONE); - break; - case BLEND_MODE_SCREEN: - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); - break; - case BLEND_MODE_MULTIPLY: + break; + case BLEND_MODE_SCREEN: + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + break; + case BLEND_MODE_MULTIPLY: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - break; - default: + break; + default: dout << "[ERROR] Invalid blend mode. This is a bug - please contact developers"; - } + } // opacity - float color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(timecode)*0.01)); + float color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + glColor4f(1.0, 1.0, 1.0, color[3]*(opacity->get_double_value(timecode)*0.01)); } void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { - top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); - top_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); - top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); - right_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); - bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); - bottom_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); - bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); - left_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); + top_left_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); + top_right_gizmo->world_pos[0] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + right_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); + bottom_right_gizmo->world_pos[0] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); + bottom_left_gizmo->world_pos[0] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + left_center_gizmo->world_pos[0] = QPoint(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); - rotate_gizmo->world_pos[0] = QPoint(lerp(top_center_gizmo->world_pos[0].x(), bottom_center_gizmo->world_pos[0].x(), -0.1), lerp(top_center_gizmo->world_pos[0].y(), bottom_center_gizmo->world_pos[0].y(), -0.1)); + rotate_gizmo->world_pos[0] = QPoint(lerp(top_center_gizmo->world_pos[0].x(), bottom_center_gizmo->world_pos[0].x(), -0.1), lerp(top_center_gizmo->world_pos[0].y(), bottom_center_gizmo->world_pos[0].y(), -0.1)); - rect_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); - rect_gizmo->world_pos[1] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); - rect_gizmo->world_pos[2] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); - rect_gizmo->world_pos[3] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + rect_gizmo->world_pos[0] = QPoint(coords.vertexTopLeftX, coords.vertexTopLeftY); + rect_gizmo->world_pos[1] = QPoint(coords.vertexTopRightX, coords.vertexTopRightY); + rect_gizmo->world_pos[2] = QPoint(coords.vertexBottomRightX, coords.vertexBottomRightY); + rect_gizmo->world_pos[3] = QPoint(coords.vertexBottomLeftX, coords.vertexBottomLeftY); } diff --git a/effects/internal/volumeeffect.cpp b/effects/internal/volumeeffect.cpp index 6a71d06a7..b7b18017b 100644 --- a/effects/internal/volumeeffect.cpp +++ b/effects/internal/volumeeffect.cpp @@ -9,12 +9,12 @@ #include "ui/collapsiblewidget.h" VolumeEffect::VolumeEffect(Clip* c, const EffectMeta *em) : Effect(c, em) { - EffectRow* volume_row = add_row("Volume:"); - volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE, "volume"); + EffectRow* volume_row = add_row("Volume"); + volume_val = volume_row->add_field(EFFECT_FIELD_DOUBLE, "volume"); volume_val->set_double_minimum_value(0); // set defaults - volume_val->set_double_default_value(100); + volume_val->set_double_default_value(100); } void VolumeEffect::process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int) { diff --git a/io/math.cpp b/io/math.cpp index c26bb5cad..4d71229a4 100644 --- a/io/math.cpp +++ b/io/math.cpp @@ -1,15 +1,54 @@ #include "math.h" #include +#include + +#include "debug.h" int lerp(int a, int b, double t) { - return qRound(((1.0 - t) * a) + (t * b)); + return qRound(((1.0 - t) * a) + (t * b)); } float float_lerp(float a, float b, float t) { - return ((1.0F - t) * a) + (t * b); + return ((1.0F - t) * a) + (t * b); } double double_lerp(double a, double b, double t) { - return ((1.0 - t) * a) + (t * b); + return ((1.0 - t) * a) + (t * b); +} + +double quad_from_t(double a, double b, double c, double t) { + return qPow(1.0 - t, 2)*a + 2*(1.0 - t)*t*b + qPow(t, 2)*c; +} + +double quad_t_from_x(double x, double a, double b, double c) { + return (a - b + qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); + // alt: return (a - b - qSqrt(a*x + c*x - 2*b*x + qPow(b, 2) - a*c))/(a - 2*b + c); +} + +double cubic_from_t(double a, double b, double c, double d, double t) { + return qPow(1.0 - t, 3)*a + 3*qPow(1.0 - t, 2)*t*b + 3*(1.0 - t)*qPow(t, 2)*c + qPow(t, 3)*d; +} + +double cubic_t_from_x(double x_target, double a, double b, double c, double d) { + double tolerance = 0.0001; + + double lower = 0.0; + double upper = 1.0; + + double percent = 0.5; + double x = cubic_from_t(a, b, c, d, percent); + + while (qAbs(x_target - x) > tolerance) { + if (x_target > x) { + lower = percent; + } else { + upper = percent; + } + + percent = (upper + lower) / 2.0; + x = cubic_from_t(a, b, c, d, percent); + } + + return percent; } diff --git a/io/math.h b/io/math.h index 927e988ac..ba1e7ed9e 100644 --- a/io/math.h +++ b/io/math.h @@ -4,5 +4,10 @@ int lerp(int a, int b, double t); float float_lerp(float a, float b, float t); double double_lerp(double a, double b, double t); +double quad_from_t(double a, double b, double c, double t); +double quad_t_from_x(double x, double a, double b, double c); +double cubic_from_t(double a, double b, double c, double d, double t); +double cubic_t_from_x(double x_target, double a, double b, double c, double d); +double solveCubicBezier(double p0, double p1, double p2, double p3, double x); #endif // MATH_H diff --git a/panels/grapheditor.cpp b/panels/grapheditor.cpp index 9b84dd8d0..7dc981fb4 100644 --- a/panels/grapheditor.cpp +++ b/panels/grapheditor.cpp @@ -59,10 +59,13 @@ GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent), row(NULL) { left_tool_layout->addStretch(); linear_button = new QPushButton("Linear"); + linear_button->setProperty("type", KEYFRAME_TYPE_LINEAR); linear_button->setCheckable(true); bezier_button = new QPushButton("Bezier"); + bezier_button->setProperty("type", KEYFRAME_TYPE_BEZIER); bezier_button->setCheckable(true); hold_button = new QPushButton("Hold"); + hold_button->setProperty("type", KEYFRAME_TYPE_HOLD); hold_button->setCheckable(true); center_tool_layout->addStretch(); @@ -91,9 +94,6 @@ GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent), row(NULL) { value_widget->setLayout(values); values->addStretch(); - current_row_desc = new QLabel(); - values->addWidget(current_row_desc); - QWidget* central_value_widget = new QWidget(); value_layout = new QHBoxLayout(); value_layout->setMargin(0); @@ -103,9 +103,18 @@ GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent), row(NULL) { values->addStretch(); layout->addWidget(value_widget); + current_row_desc = new QLabel(); + current_row_desc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + current_row_desc->setAlignment(Qt::AlignCenter); + layout->addWidget(current_row_desc); + connect(view, SIGNAL(zoom_changed(double)), header, SLOT(update_zoom(double))); connect(view, SIGNAL(x_scroll_changed(int)), header, SLOT(set_scroll(int))); - connect(view, SIGNAL(selection_changed(bool)), this, SLOT(set_key_button_enabled(bool))); + connect(view, SIGNAL(selection_changed(bool, int)), this, SLOT(set_key_button_enabled(bool, int))); + + connect(linear_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + connect(bezier_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); + connect(hold_button, SIGNAL(clicked(bool)), this, SLOT(set_keyframe_type())); } void GraphEditor::update_panel() { @@ -129,8 +138,10 @@ void GraphEditor::update_panel() { void GraphEditor::set_row(EffectRow *r) { for (int i=0;ifieldCount();i++) { EffectField* field = r->field(i); if (field->type == EFFECT_FIELD_DOUBLE) { + QPushButton* slider_button = new QPushButton(); + slider_button->setCheckable(true); + slider_button->setChecked(true); + slider_button->setIcon(QIcon(":/icons/record.png")); + slider_button->setProperty("field", i); + slider_button->setIconSize(QSize(8, 8)); + slider_button->setMaximumSize(QSize(12, 12)); + connect(slider_button, SIGNAL(toggled(bool)), this, SLOT(set_field_visibility(bool))); + slider_proxy_buttons.append(slider_button); + value_layout->addWidget(slider_button); + LabelSlider* slider = new LabelSlider(); slider->set_color(get_curve_color(i, r->fieldCount()).name()); connect(slider, SIGNAL(valueChanged()), this, SLOT(passthrough_slider_value())); - slider_proxies.append(slider); value_layout->addWidget(slider); @@ -175,10 +196,13 @@ void GraphEditor::set_row(EffectRow *r) { update_panel(); } -void GraphEditor::set_key_button_enabled(bool e) { +void GraphEditor::set_key_button_enabled(bool e, int type) { linear_button->setEnabled(e); + linear_button->setChecked(type == KEYFRAME_TYPE_LINEAR); bezier_button->setEnabled(e); + bezier_button->setChecked(type == KEYFRAME_TYPE_BEZIER); hold_button->setEnabled(e); + hold_button->setChecked(type == KEYFRAME_TYPE_HOLD); } void GraphEditor::passthrough_slider_value() { @@ -188,3 +212,14 @@ void GraphEditor::passthrough_slider_value() { } } } + +void GraphEditor::set_keyframe_type() { + linear_button->setChecked(linear_button == sender()); + bezier_button->setChecked(bezier_button == sender()); + hold_button->setChecked(hold_button == sender()); + view->set_selected_keyframe_type(sender()->property("type").toInt()); +} + +void GraphEditor::set_field_visibility(bool b) { + view->set_field_visibility(sender()->property("field").toInt(), b); +} diff --git a/panels/grapheditor.h b/panels/grapheditor.h index 79329342b..467de9ec3 100644 --- a/panels/grapheditor.h +++ b/panels/grapheditor.h @@ -23,6 +23,7 @@ private: TimelineHeader* header; QHBoxLayout* value_layout; QVector slider_proxies; + QVector slider_proxy_buttons; QVector slider_proxy_sources; QLabel* current_row_desc; EffectRow* row; @@ -31,8 +32,10 @@ private: QPushButton* bezier_button; QPushButton* hold_button; private slots: - void set_key_button_enabled(bool e); + void set_key_button_enabled(bool e, int type); void passthrough_slider_value(); + void set_keyframe_type(); + void set_field_visibility(bool b); }; #endif // GRAPHEDITOR_H diff --git a/project/effect.cpp b/project/effect.cpp index bf20bd12a..40fc2b6b0 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -52,14 +52,14 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { switch (em->internal) { case EFFECT_INTERNAL_TRANSFORM: return new TransformEffect(c, em); case EFFECT_INTERNAL_TEXT: return new TextEffect(c, em); - case EFFECT_INTERNAL_TIMECODE: return new TimecodeEffect(c, em); + case EFFECT_INTERNAL_TIMECODE: return new TimecodeEffect(c, em); case EFFECT_INTERNAL_SOLID: return new SolidEffect(c, em); case EFFECT_INTERNAL_NOISE: return new AudioNoiseEffect(c, em); case EFFECT_INTERNAL_VOLUME: return new VolumeEffect(c, em); case EFFECT_INTERNAL_PAN: return new PanEffect(c, em); case EFFECT_INTERNAL_TONE: return new ToneEffect(c, em); - case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em); - case EFFECT_INTERNAL_CORNERPIN: return new CornerPinEffect(c, em); + case EFFECT_INTERNAL_SHAKE: return new ShakeEffect(c, em); + case EFFECT_INTERNAL_CORNERPIN: return new CornerPinEffect(c, em); } } else { dout << "[ERROR] Invalid effect data"; @@ -69,12 +69,12 @@ Effect* create_effect(Clip* c, const EffectMeta* em) { } const EffectMeta* get_internal_meta(int internal_id, int type) { - for (int i=0;ienabled_check, SIGNAL(clicked(bool)), this, SLOT(field_changed())); - ui = new QWidget(); - ui_layout = new QGridLayout(); + // set up base UI + container = new CollapsibleWidget(); + connect(container->enabled_check, SIGNAL(clicked(bool)), this, SLOT(field_changed())); + ui = new QWidget(); + ui_layout = new QGridLayout(); ui_layout->setSpacing(4); - ui->setLayout(ui_layout); + 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 + // set up UI from effect file container->setText(em->name); if (!em->filename.isEmpty()) { @@ -277,7 +277,7 @@ Effect::Effect(Clip* c, const EffectMeta *em) : } } if (!row_name.isEmpty()) { - EffectRow* row = add_row(row_name + ":"); + EffectRow* row = add_row(row_name); while (!reader.atEnd() && !(reader.name() == "row" && reader.isEndElement())) { reader.readNext(); if (reader.name() == "field" && reader.isStartElement()) { @@ -311,7 +311,7 @@ Effect::Effect(Clip* c, const EffectMeta *em) : if (id.isEmpty()) { dout << "[ERROR] Couldn't load field from" << em->filename << "- ID cannot be empty."; } else if (type > -1) { - EffectField* field = row->add_field(type, id); + EffectField* field = row->add_field(type, id); connect(field, SIGNAL(changed()), this, SLOT(field_changed())); switch (type) { case EFFECT_FIELD_DOUBLE: @@ -447,27 +447,27 @@ Effect::~Effect() { for (int i=0;irows.at(i); - copy_row->setKeyframing(row->isKeyframing()); + copy_row->setKeyframing(row->isKeyframing()); for (int j=0;jfieldCount();j++) { - EffectField* field = row->field(j); - EffectField* copy_field = copy_row->field(j); - copy_field->keyframes = field->keyframes; + EffectField* field = row->field(j); + EffectField* copy_field = copy_row->field(j); + copy_field->keyframes = field->keyframes; } } } EffectRow* Effect::add_row(const QString& name, bool savable) { - EffectRow* row = new EffectRow(this, savable, ui_layout, name, rows.size()); - rows.append(row); + EffectRow* row = new EffectRow(this, savable, ui_layout, name, rows.size()); + rows.append(row); return row; } @@ -476,53 +476,53 @@ EffectRow* Effect::row(int i) { } int Effect::row_count() { - return rows.size(); + return rows.size(); } EffectGizmo *Effect::add_gizmo(int type) { - EffectGizmo* gizmo = new EffectGizmo(type); - gizmos.append(gizmo); - return gizmo; + EffectGizmo* gizmo = new EffectGizmo(type); + gizmos.append(gizmo); + return gizmo; } EffectGizmo *Effect::gizmo(int i) { - return gizmos.at(i); + return gizmos.at(i); } int Effect::gizmo_count(){ - return gizmos.size(); + return gizmos.size(); } void Effect::refresh() {} void Effect::field_changed() { - panel_sequence_viewer->viewer_widget->update(); + panel_sequence_viewer->viewer_widget->update(); panel_graph_editor->update_panel(); } void Effect::show_context_menu(const QPoint& pos) { - if (meta->type == EFFECT_TYPE_EFFECT) { - QMenu menu(mainWindow); + if (meta->type == EFFECT_TYPE_EFFECT) { + QMenu menu(mainWindow); - int index = get_index_in_clip(); + 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 > 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())); - } + 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(); + menu.addSeparator(); - QAction* del_action = menu.addAction("D&elete"); - connect(del_action, SIGNAL(triggered(bool)), this, SLOT(delete_self())); + QAction* del_action = menu.addAction("D&elete"); + connect(del_action, SIGNAL(triggered(bool)), this, SLOT(delete_self())); - menu.exec(container->title_bar->mapToGlobal(pos)); - } + menu.exec(container->title_bar->mapToGlobal(pos)); + } } void Effect::delete_self() { @@ -572,24 +572,24 @@ void Effect::set_enabled(bool b) { QVariant load_data_from_string(int type, const QString& string) { switch (type) { - case EFFECT_FIELD_DOUBLE: return string.toDouble(); - case EFFECT_FIELD_COLOR: return QColor(string); - case EFFECT_FIELD_STRING: return string; - case EFFECT_FIELD_BOOL: return (string == "1"); - case EFFECT_FIELD_COMBO: return string.toInt(); - case EFFECT_FIELD_FONT: return string; + case EFFECT_FIELD_DOUBLE: return string.toDouble(); + case EFFECT_FIELD_COLOR: return QColor(string); + case EFFECT_FIELD_STRING: return string; + case EFFECT_FIELD_BOOL: return (string == "1"); + case EFFECT_FIELD_COMBO: return string.toInt(); + case EFFECT_FIELD_FONT: return string; } return QVariant(); } QString save_data_to_string(int type, const QVariant& data) { switch (type) { - case EFFECT_FIELD_DOUBLE: return QString::number(data.toDouble()); - case EFFECT_FIELD_COLOR: return data.value().name(); - case EFFECT_FIELD_STRING: return data.toString(); - case EFFECT_FIELD_BOOL: return QString::number(data.toBool()); - case EFFECT_FIELD_COMBO: return QString::number(data.toInt()); - case EFFECT_FIELD_FONT: return data.toString(); + case EFFECT_FIELD_DOUBLE: return QString::number(data.toDouble()); + case EFFECT_FIELD_COLOR: return data.value().name(); + case EFFECT_FIELD_STRING: return data.toString(); + case EFFECT_FIELD_BOOL: return QString::number(data.toBool()); + case EFFECT_FIELD_COMBO: return QString::number(data.toInt()); + case EFFECT_FIELD_FONT: return data.toString(); } return QString(); } @@ -610,7 +610,7 @@ void Effect::load(QXmlStreamReader& stream) { stream.readNext(); // read keyframes - /*if (stream.name() == "keyframes" && stream.isStartElement()) { + /*if (stream.name() == "keyframes" && stream.isStartElement()) { for (int k=0;kfieldCount();k++) { - EffectField* field = row->field(k); - EffectKeyframe key; - key.time = keyframe_frame; - key.type = keyframe_type; - field->keyframes.append(key); - } + for (int k=0;kfieldCount();k++) { + EffectField* field = row->field(k); + EffectKeyframe key; + key.time = keyframe_frame; + key.type = keyframe_type; + field->keyframes.append(key); + } } stream.readNext(); } } stream.readNext(); - }*/ + }*/ // read field if (stream.name() == "field" && stream.isStartElement()) { @@ -683,22 +683,22 @@ void Effect::load(QXmlStreamReader& stream) { while (!stream.atEnd() && !(stream.name() == "field" && stream.isEndElement())) { stream.readNext(); - // read keyframes + // read keyframes if (stream.name() == "key" && stream.isStartElement()) { - row->setKeyframing(true); + row->setKeyframing(true); - EffectKeyframe key; - for (int k=0;ktype, attr.value().toString()); - } else if (attr.name() == "frame") { - key.time = attr.value().toLong(); - } else if (attr.name() == "type") { - key.type = attr.value().toInt(); - } - } - field->keyframes.append(key); + EffectKeyframe key; + for (int k=0;ktype, attr.value().toString()); + } else if (attr.name() == "frame") { + key.time = attr.value().toLong(); + } else if (attr.name() == "type") { + key.type = attr.value().toInt(); + } + } + field->keyframes.append(key); } } } else { @@ -718,29 +718,29 @@ void Effect::load(QXmlStreamReader& stream) { void Effect::save(QXmlStreamWriter& stream) { stream.writeAttribute("name", meta->name); - stream.writeAttribute("enabled", QString::number(is_enabled())); + stream.writeAttribute("enabled", QString::number(is_enabled())); for (int i=0;isavable) { - stream.writeStartElement("row"); // row - for (int j=0;jfieldCount();j++) { - EffectField* field = row->field(j); - stream.writeStartElement("field"); // field - stream.writeAttribute("id", field->id); - stream.writeAttribute("value", save_data_to_string(field->type, field->get_current_data())); - for (int k=0;kkeyframes.size();k++) { - const EffectKeyframe& key = field->keyframes.at(k); - stream.writeStartElement("key"); - stream.writeAttribute("value", save_data_to_string(field->type, key.data)); - stream.writeAttribute("frame", QString::number(key.time)); - stream.writeAttribute("type", QString::number(key.type)); - stream.writeEndElement(); // key - } - stream.writeEndElement(); // field - } - stream.writeEndElement(); // row - } + if (row->savable) { + stream.writeStartElement("row"); // row + for (int j=0;jfieldCount();j++) { + EffectField* field = row->field(j); + stream.writeStartElement("field"); // field + stream.writeAttribute("id", field->id); + stream.writeAttribute("value", save_data_to_string(field->type, field->get_current_data())); + for (int k=0;kkeyframes.size();k++) { + const EffectKeyframe& key = field->keyframes.at(k); + stream.writeStartElement("key"); + stream.writeAttribute("value", save_data_to_string(field->type, key.data)); + stream.writeAttribute("frame", QString::number(key.time)); + stream.writeAttribute("type", QString::number(key.type)); + stream.writeEndElement(); // key + } + stream.writeEndElement(); // field + } + stream.writeEndElement(); // row + } } } @@ -790,16 +790,16 @@ void Effect::startEffect() { void Effect::endEffect() { if (bound) glslProgram->release(); - bound = false; + bound = false; } void Effect::process_image(double, uint8_t *, int) {} Effect* Effect::copy(Clip* c) { Effect* copy = create_effect(c, meta); - copy->set_enabled(is_enabled()); - copy_field_keyframes(copy); - return copy; + copy->set_enabled(is_enabled()); + copy_field_keyframes(copy); + return copy; } void Effect::process_shader(double timecode, GLTextureCoords&) { @@ -844,7 +844,7 @@ GLuint Effect::process_superimpose(double timecode) { recreate_texture = true; } - if (valueHasChanged(timecode) || recreate_texture || enable_always_update) { + if (valueHasChanged(timecode) || recreate_texture || enable_always_update) { redraw(timecode); } @@ -865,78 +865,78 @@ GLuint Effect::process_superimpose(double timecode) { void Effect::process_audio(double, double, quint8*, int, int) { // only volume/pan, hand off to AU and VST for all other cases - /*double interval = (timecode_end-timecode_start)/nb_bytes; + /*double interval = (timecode_end-timecode_start)/nb_bytes; for (int i=0;ifield(0)->get_double_value(timecode_start+(interval*i), true)); QJSValue result = eval.call(); - samp = result.toInt(); - QJSValueList args; - args << samples << nb_bytes; + samp = result.toInt(); + QJSValueList args; + args << samples << nb_bytes; samples[i+1] = (quint8) (samp >> 8); samples[i] = (quint8) samp; - }*/ + }*/ } void Effect::gizmo_draw(double, GLTextureCoords &) {} void Effect::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, double timecode, bool done) { - for (int i=0;ix_field1 != NULL) { - gizmo->x_field1->set_double_value(gizmo->x_field1->get_double_value(timecode) + x_movement*gizmo->x_field_multi1); - gizmo->x_field1->make_key_from_change(ca); - } - if (gizmo->y_field1 != NULL) { - gizmo->y_field1->set_double_value(gizmo->y_field1->get_double_value(timecode) + y_movement*gizmo->y_field_multi1); - gizmo->y_field1->make_key_from_change(ca); - } - if (gizmo->x_field2 != NULL) { - gizmo->x_field2->set_double_value(gizmo->x_field2->get_double_value(timecode) + x_movement*gizmo->x_field_multi2); - gizmo->x_field2->make_key_from_change(ca); - } - if (gizmo->y_field2 != NULL) { - gizmo->y_field2->set_double_value(gizmo->y_field2->get_double_value(timecode) + y_movement*gizmo->y_field_multi2); - gizmo->y_field2->make_key_from_change(ca); - } - if (done) undo_stack.push(ca); - break; - } - } + for (int i=0;ix_field1 != NULL) { + gizmo->x_field1->set_double_value(gizmo->x_field1->get_double_value(timecode) + x_movement*gizmo->x_field_multi1); + gizmo->x_field1->make_key_from_change(ca); + } + if (gizmo->y_field1 != NULL) { + gizmo->y_field1->set_double_value(gizmo->y_field1->get_double_value(timecode) + y_movement*gizmo->y_field_multi1); + gizmo->y_field1->make_key_from_change(ca); + } + if (gizmo->x_field2 != NULL) { + gizmo->x_field2->set_double_value(gizmo->x_field2->get_double_value(timecode) + x_movement*gizmo->x_field_multi2); + gizmo->x_field2->make_key_from_change(ca); + } + if (gizmo->y_field2 != NULL) { + gizmo->y_field2->set_double_value(gizmo->y_field2->get_double_value(timecode) + y_movement*gizmo->y_field_multi2); + gizmo->y_field2->make_key_from_change(ca); + } + if (done) undo_stack.push(ca); + break; + } + } } void Effect::gizmo_world_to_screen() { - GLfloat view_val[16]; - GLfloat projection_val[16]; - glGetFloatv(GL_MODELVIEW_MATRIX, view_val); - glGetFloatv(GL_PROJECTION_MATRIX, projection_val); + GLfloat view_val[16]; + GLfloat projection_val[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, view_val); + glGetFloatv(GL_PROJECTION_MATRIX, projection_val); - QMatrix4x4 view_matrix(view_val); - QMatrix4x4 projection_matrix(projection_val); + QMatrix4x4 view_matrix(view_val); + QMatrix4x4 projection_matrix(projection_val); - for (int i=0;iget_point_count();j++) { - QVector4D screen_pos = QVector4D(g->world_pos[j].x(), g->world_pos[j].y(), 0, 1.0) * (view_matrix * projection_matrix); + for (int j=0;jget_point_count();j++) { + QVector4D screen_pos = QVector4D(g->world_pos[j].x(), g->world_pos[j].y(), 0, 1.0) * (view_matrix * projection_matrix); - int adjusted_sx1 = qRound(((screen_pos.x()*0.5f)+0.5f)*parent_clip->sequence->width); - int adjusted_sy1 = qRound((1.0f-((screen_pos.y()*0.5f)+0.5f))*parent_clip->sequence->height); + int adjusted_sx1 = qRound(((screen_pos.x()*0.5f)+0.5f)*parent_clip->sequence->width); + int adjusted_sy1 = qRound((1.0f-((screen_pos.y()*0.5f)+0.5f))*parent_clip->sequence->height); - g->screen_pos[j] = QPoint(adjusted_sx1, adjusted_sy1); - } - } + g->screen_pos[j] = QPoint(adjusted_sx1, adjusted_sy1); + } + } } bool Effect::are_gizmos_enabled() { - return (gizmos.size() > 0); + return (gizmos.size() > 0); } void Effect::redraw(double) { diff --git a/project/effectfield.cpp b/project/effectfield.cpp index 00435b91d..6eda75505 100644 --- a/project/effectfield.cpp +++ b/project/effectfield.cpp @@ -15,353 +15,366 @@ #include "project/sequence.h" #include "io/math.h" -#include +#include + +#include "debug.h" EffectField::EffectField(EffectRow *parent, int t, const QString &i) : - parent_row(parent), - type(t), - id(i) + parent_row(parent), + type(t), + id(i) { - switch (t) { - case EFFECT_FIELD_DOUBLE: - { - LabelSlider* ls = new LabelSlider(); - ui_element = ls; - connect(ls, SIGNAL(valueChanged()), this, SLOT(ui_element_change())); + switch (t) { + case EFFECT_FIELD_DOUBLE: + { + LabelSlider* ls = new LabelSlider(); + ui_element = ls; + connect(ls, SIGNAL(valueChanged()), this, SLOT(ui_element_change())); connect(ls, SIGNAL(clicked()), this, SIGNAL(clicked())); - } - break; - case EFFECT_FIELD_COLOR: - { - ColorButton* cb = new ColorButton(); - ui_element = cb; - connect(cb, SIGNAL(color_changed()), this, SLOT(ui_element_change())); - } - break; - case EFFECT_FIELD_STRING: - { - TextEditEx* edit = new TextEditEx(); - edit->setUndoRedoEnabled(true); - ui_element = edit; - connect(edit, SIGNAL(textChanged()), this, SLOT(ui_element_change())); - } - break; - case EFFECT_FIELD_BOOL: - { - CheckboxEx* cb = new CheckboxEx(); - ui_element = cb; - connect(cb, SIGNAL(clicked(bool)), this, SLOT(ui_element_change())); - connect(cb, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool))); - } - break; - case EFFECT_FIELD_COMBO: - { - ComboBoxEx* cb = new ComboBoxEx(); - ui_element = cb; - connect(cb, SIGNAL(activated(int)), this, SLOT(ui_element_change())); - } - break; - case EFFECT_FIELD_FONT: - { - FontCombobox* fcb = new FontCombobox(); - ui_element = fcb; - connect(fcb, SIGNAL(activated(int)), this, SLOT(ui_element_change())); - } - break; - } + } + break; + case EFFECT_FIELD_COLOR: + { + ColorButton* cb = new ColorButton(); + ui_element = cb; + connect(cb, SIGNAL(color_changed()), this, SLOT(ui_element_change())); + } + break; + case EFFECT_FIELD_STRING: + { + TextEditEx* edit = new TextEditEx(); + edit->setUndoRedoEnabled(true); + ui_element = edit; + connect(edit, SIGNAL(textChanged()), this, SLOT(ui_element_change())); + } + break; + case EFFECT_FIELD_BOOL: + { + CheckboxEx* cb = new CheckboxEx(); + ui_element = cb; + connect(cb, SIGNAL(clicked(bool)), this, SLOT(ui_element_change())); + connect(cb, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool))); + } + break; + case EFFECT_FIELD_COMBO: + { + ComboBoxEx* cb = new ComboBoxEx(); + ui_element = cb; + connect(cb, SIGNAL(activated(int)), this, SLOT(ui_element_change())); + } + break; + case EFFECT_FIELD_FONT: + { + FontCombobox* fcb = new FontCombobox(); + ui_element = fcb; + connect(fcb, SIGNAL(activated(int)), this, SLOT(ui_element_change())); + } + break; + } } QVariant EffectField::get_previous_data() { - switch (type) { - case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->getPreviousValue(); - case EFFECT_FIELD_COLOR: return static_cast(ui_element)->getPreviousValue(); - case EFFECT_FIELD_STRING: return static_cast(ui_element)->getPreviousValue(); - case EFFECT_FIELD_BOOL: return !static_cast(ui_element)->isChecked(); - case EFFECT_FIELD_COMBO: return static_cast(ui_element)->getPreviousIndex(); - case EFFECT_FIELD_FONT: return static_cast(ui_element)->getPreviousValue(); - } - return QVariant(); + switch (type) { + case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->getPreviousValue(); + case EFFECT_FIELD_COLOR: return static_cast(ui_element)->getPreviousValue(); + case EFFECT_FIELD_STRING: return static_cast(ui_element)->getPreviousValue(); + case EFFECT_FIELD_BOOL: return !static_cast(ui_element)->isChecked(); + case EFFECT_FIELD_COMBO: return static_cast(ui_element)->getPreviousIndex(); + case EFFECT_FIELD_FONT: return static_cast(ui_element)->getPreviousValue(); + } + return QVariant(); } QVariant EffectField::get_current_data() { - switch (type) { - case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->value(); - case EFFECT_FIELD_COLOR: return static_cast(ui_element)->get_color(); - case EFFECT_FIELD_STRING: return static_cast(ui_element)->getPlainTextEx(); - case EFFECT_FIELD_BOOL: return static_cast(ui_element)->isChecked(); - case EFFECT_FIELD_COMBO: return static_cast(ui_element)->currentIndex(); - case EFFECT_FIELD_FONT: return static_cast(ui_element)->currentText(); - } - return QVariant(); + switch (type) { + case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->value(); + case EFFECT_FIELD_COLOR: return static_cast(ui_element)->get_color(); + case EFFECT_FIELD_STRING: return static_cast(ui_element)->getPlainTextEx(); + case EFFECT_FIELD_BOOL: return static_cast(ui_element)->isChecked(); + case EFFECT_FIELD_COMBO: return static_cast(ui_element)->currentIndex(); + case EFFECT_FIELD_FONT: return static_cast(ui_element)->currentText(); + } + return QVariant(); } double EffectField::frameToTimecode(long frame) { - return ((double) frame / parent_row->parent_effect->parent_clip->sequence->frame_rate); + return ((double) frame / parent_row->parent_effect->parent_clip->sequence->frame_rate); } long EffectField::timecodeToFrame(double timecode) { - return qRound(timecode * parent_row->parent_effect->parent_clip->sequence->frame_rate); + return qRound(timecode * parent_row->parent_effect->parent_clip->sequence->frame_rate); } void EffectField::set_current_data(const QVariant& data) { - switch (type) { - case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->set_value(data.toDouble(), false); - case EFFECT_FIELD_COLOR: return static_cast(ui_element)->set_color(data.value()); - case EFFECT_FIELD_STRING: return static_cast(ui_element)->setPlainTextEx(data.toString()); - case EFFECT_FIELD_BOOL: return static_cast(ui_element)->setChecked(data.toBool()); - case EFFECT_FIELD_COMBO: return static_cast(ui_element)->setCurrentIndexEx(data.toInt()); - case EFFECT_FIELD_FONT: return static_cast(ui_element)->setCurrentTextEx(data.toString()); - } + switch (type) { + case EFFECT_FIELD_DOUBLE: return static_cast(ui_element)->set_value(data.toDouble(), false); + case EFFECT_FIELD_COLOR: return static_cast(ui_element)->set_color(data.value()); + case EFFECT_FIELD_STRING: return static_cast(ui_element)->setPlainTextEx(data.toString()); + case EFFECT_FIELD_BOOL: return static_cast(ui_element)->setChecked(data.toBool()); + case EFFECT_FIELD_COMBO: return static_cast(ui_element)->setCurrentIndexEx(data.toInt()); + case EFFECT_FIELD_FONT: return static_cast(ui_element)->setCurrentTextEx(data.toString()); + } } void EffectField::get_keyframe_data(double timecode, int &before, int &after, double &progress) { - int before_keyframe_index = -1; - int after_keyframe_index = -1; - long before_keyframe_time = LONG_MIN; - long after_keyframe_time = LONG_MAX; - long frame = timecodeToFrame(timecode); + int before_keyframe_index = -1; + int after_keyframe_index = -1; + long before_keyframe_time = LONG_MIN; + long after_keyframe_time = LONG_MAX; + long frame = timecodeToFrame(timecode); - for (int i=0;i before_keyframe_time) { - before_keyframe_index = i; - before_keyframe_time = eval_keyframe_time; - } else if (eval_keyframe_time > frame && eval_keyframe_time < after_keyframe_time) { - after_keyframe_index = i; - after_keyframe_time = eval_keyframe_time; - } - } + for (int i=0;i before_keyframe_time) { + before_keyframe_index = i; + before_keyframe_time = eval_keyframe_time; + } else if (eval_keyframe_time > frame && eval_keyframe_time < after_keyframe_time) { + after_keyframe_index = i; + after_keyframe_time = eval_keyframe_time; + } + } - if ((type == EFFECT_FIELD_DOUBLE || type == EFFECT_FIELD_COLOR) && (before_keyframe_index > -1 && after_keyframe_index > -1)) { - // interpolate - before = before_keyframe_index; - after = after_keyframe_index; - - if (keyframes.at(before).type == KEYFRAME_TYPE_HOLD) { - progress = 0; - } else { - // TODO replace with bezier function - progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time)); - } - } else if (before_keyframe_index > -1) { - before = before_keyframe_index; - after = before_keyframe_index; - } else { - before = after_keyframe_index; - after = after_keyframe_index; - } + if ((type == EFFECT_FIELD_DOUBLE || type == EFFECT_FIELD_COLOR) && (before_keyframe_index > -1 && after_keyframe_index > -1)) { + // interpolate + before = before_keyframe_index; + after = after_keyframe_index; + progress = (timecode-frameToTimecode(before_keyframe_time))/(frameToTimecode(after_keyframe_time)-frameToTimecode(before_keyframe_time)); + } else if (before_keyframe_index > -1) { + before = before_keyframe_index; + after = before_keyframe_index; + } else { + before = after_keyframe_index; + after = after_keyframe_index; + } } bool EffectField::hasKeyframes() { - return (parent_row->isKeyframing() && keyframes.size() > 0); + return (parent_row->isKeyframing() && keyframes.size() > 0); } QVariant EffectField::validate_keyframe_data(double timecode, bool async) { - if (hasKeyframes()) { - int before_keyframe; - int after_keyframe; - double progress; - get_keyframe_data(timecode, before_keyframe, after_keyframe, progress); + if (hasKeyframes()) { + int before_keyframe; + int after_keyframe; + double progress; + get_keyframe_data(timecode, before_keyframe, after_keyframe, progress); - /*int kf_type = (progress < 0.5) ? parent_row->keyframe_types.at(before_keyframe) : parent_row->keyframe_types.at(after_keyframe); - if (kf_type == KEYFRAME_TYPE_BEZIER) { - double x = (8.0 * progress) - 4.0; - progress = 1.0 / (1.0 + qPow(M_E, -x)); - progress *= 1.0373; - progress -= 0.01865; - }*/ + const QVariant& before_data = keyframes.at(before_keyframe).data; + switch (type) { + case EFFECT_FIELD_DOUBLE: + { + double value; + if (before_keyframe == after_keyframe) { + value = keyframes.at(before_keyframe).data.toDouble(); + } else { + const EffectKeyframe& before_key = keyframes.at(before_keyframe); + const EffectKeyframe& after_key = keyframes.at(after_keyframe); - const QVariant& before_data = keyframes.at(before_keyframe).data; - switch (type) { - case EFFECT_FIELD_DOUBLE: - { - double value; - if (before_keyframe == after_keyframe) { - value = keyframes.at(before_keyframe).data.toDouble(); - } else { - double before_dbl = keyframes.at(before_keyframe).data.toDouble(); - double after_dbl = keyframes.at(after_keyframe).data.toDouble(); - value = double_lerp(before_dbl, after_dbl, progress); - } - if (async) { - return value; - } - static_cast(ui_element)->set_value(value, false); - } - break; - case EFFECT_FIELD_COLOR: - { - QColor value; - if (before_keyframe == after_keyframe) { - value = keyframes.at(before_keyframe).data.value(); - } else { - QColor before_data = keyframes.at(before_keyframe).data.value(); - QColor after_data = keyframes.at(after_keyframe).data.value(); - value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress)); - } - if (async) { - return value; - } - static_cast(ui_element)->set_color(value); - } - break; - case EFFECT_FIELD_STRING: - if (async) { - return before_data; - } - static_cast(ui_element)->setPlainTextEx(before_data.toString()); - break; - case EFFECT_FIELD_BOOL: - if (async) { - return before_data; - } - static_cast(ui_element)->setChecked(before_data.toBool()); - break; - case EFFECT_FIELD_COMBO: - if (async) { - return before_data; - } - static_cast(ui_element)->setCurrentIndexEx(before_data.toInt()); - break; - case EFFECT_FIELD_FONT: - if (async) { - return before_data; - } - static_cast(ui_element)->setCurrentTextEx(before_data.toString()); - break; - } - } - return QVariant(); + double before_dbl = before_key.data.toDouble(); + double after_dbl = after_key.data.toDouble(); + + if (before_key.type == KEYFRAME_TYPE_HOLD) { + // hold + value = before_dbl; + } else if (before_key.type == KEYFRAME_TYPE_BEZIER || after_key.type == KEYFRAME_TYPE_BEZIER) { + // bezier interpolation + if (before_key.type == KEYFRAME_TYPE_BEZIER && after_key.type == KEYFRAME_TYPE_BEZIER) { + // cubic bezier + double t = cubic_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+before_key.post_handle_x, after_key.time+after_key.pre_handle_x, after_key.time); + value = cubic_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl+after_key.pre_handle_y, after_dbl, t); + } else if (after_key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier + // last keyframe is the bezier one + double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+before_key.post_handle_x, after_key.time); + value = quad_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl, t); + } else { + // this keyframe is the bezier one + double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, after_key.time+after_key.pre_handle_x, after_key.time); + value = quad_from_t(before_dbl, after_dbl+after_key.pre_handle_y, after_dbl, t); + } + } else { + // linear + value = double_lerp(before_dbl, after_dbl, progress); + } + } + if (async) { + return value; + } + static_cast(ui_element)->set_value(value, false); + } + break; + case EFFECT_FIELD_COLOR: + { + QColor value; + if (before_keyframe == after_keyframe) { + value = keyframes.at(before_keyframe).data.value(); + } else { + QColor before_data = keyframes.at(before_keyframe).data.value(); + QColor after_data = keyframes.at(after_keyframe).data.value(); + value = QColor(lerp(before_data.red(), after_data.red(), progress), lerp(before_data.green(), after_data.green(), progress), lerp(before_data.blue(), after_data.blue(), progress)); + } + if (async) { + return value; + } + static_cast(ui_element)->set_color(value); + } + break; + case EFFECT_FIELD_STRING: + if (async) { + return before_data; + } + static_cast(ui_element)->setPlainTextEx(before_data.toString()); + break; + case EFFECT_FIELD_BOOL: + if (async) { + return before_data; + } + static_cast(ui_element)->setChecked(before_data.toBool()); + break; + case EFFECT_FIELD_COMBO: + if (async) { + return before_data; + } + static_cast(ui_element)->setCurrentIndexEx(before_data.toInt()); + break; + case EFFECT_FIELD_FONT: + if (async) { + return before_data; + } + static_cast(ui_element)->setCurrentTextEx(before_data.toString()); + break; + } + } + return QVariant(); } void EffectField::ui_element_change() { - bool dragging_double = (type == EFFECT_FIELD_DOUBLE && static_cast(ui_element)->is_dragging()); - ComboAction* ca = NULL; - if (!dragging_double) ca = new ComboAction(); - make_key_from_change(ca); - if (!dragging_double) undo_stack.push(ca); - emit changed(); + bool dragging_double = (type == EFFECT_FIELD_DOUBLE && static_cast(ui_element)->is_dragging()); + ComboAction* ca = NULL; + if (!dragging_double) ca = new ComboAction(); + make_key_from_change(ca); + if (!dragging_double) undo_stack.push(ca); + emit changed(); } void EffectField::make_key_from_change(ComboAction* ca) { - if (parent_row->isKeyframing()) { - parent_row->set_keyframe_now(ca); - } else if (ca != NULL) { - // set undo - ca->append(new EffectFieldUndo(this)); - } + if (parent_row->isKeyframing()) { + parent_row->set_keyframe_now(ca); + } else if (ca != NULL) { + // set undo + ca->append(new EffectFieldUndo(this)); + } } QWidget* EffectField::get_ui_element() { - return ui_element; + return ui_element; } void EffectField::set_enabled(bool e) { - ui_element->setEnabled(e); + ui_element->setEnabled(e); } double EffectField::get_double_value(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).toDouble(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->value(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).toDouble(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->value(); } void EffectField::set_double_value(double v) { - static_cast(ui_element)->set_value(v, false); + static_cast(ui_element)->set_value(v, false); } void EffectField::set_double_default_value(double v) { - static_cast(ui_element)->set_default_value(v); + static_cast(ui_element)->set_default_value(v); } void EffectField::set_double_minimum_value(double v) { - static_cast(ui_element)->set_minimum_value(v); + static_cast(ui_element)->set_minimum_value(v); } void EffectField::set_double_maximum_value(double v) { - static_cast(ui_element)->set_maximum_value(v); + static_cast(ui_element)->set_maximum_value(v); } void EffectField::add_combo_item(const QString& name, const QVariant& data) { - static_cast(ui_element)->addItem(name, data); + static_cast(ui_element)->addItem(name, data); } int EffectField::get_combo_index(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).toInt(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->currentIndex(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).toInt(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->currentIndex(); } const QVariant EffectField::get_combo_data(double timecode) { - validate_keyframe_data(timecode); - return static_cast(ui_element)->currentData(); + validate_keyframe_data(timecode); + return static_cast(ui_element)->currentData(); } const QString EffectField::get_combo_string(double timecode) { - validate_keyframe_data(timecode); - return static_cast(ui_element)->currentText(); + validate_keyframe_data(timecode); + return static_cast(ui_element)->currentText(); } void EffectField::set_combo_index(int index) { - static_cast(ui_element)->setCurrentIndexEx(index); + static_cast(ui_element)->setCurrentIndexEx(index); } void EffectField::set_combo_string(const QString& s) { - static_cast(ui_element)->setCurrentTextEx(s); + static_cast(ui_element)->setCurrentTextEx(s); } bool EffectField::get_bool_value(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).toBool(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->isChecked(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).toBool(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->isChecked(); } void EffectField::set_bool_value(bool b) { - return static_cast(ui_element)->setChecked(b); + return static_cast(ui_element)->setChecked(b); } const QString EffectField::get_string_value(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).toString(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->getPlainTextEx(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).toString(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->getPlainTextEx(); } void EffectField::set_string_value(const QString& s) { - static_cast(ui_element)->setPlainTextEx(s); + static_cast(ui_element)->setPlainTextEx(s); } const QString EffectField::get_font_name(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).toString(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->currentText(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).toString(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->currentText(); } void EffectField::set_font_name(const QString& s) { - static_cast(ui_element)->setCurrentText(s); + static_cast(ui_element)->setCurrentText(s); } QColor EffectField::get_color_value(double timecode, bool async) { - if (async && hasKeyframes()) { - return validate_keyframe_data(timecode, true).value(); - } - validate_keyframe_data(timecode); - return static_cast(ui_element)->get_color(); + if (async && hasKeyframes()) { + return validate_keyframe_data(timecode, true).value(); + } + validate_keyframe_data(timecode); + return static_cast(ui_element)->get_color(); } void EffectField::set_color_value(QColor color) { - static_cast(ui_element)->set_color(color); + static_cast(ui_element)->set_color(color); } diff --git a/project/effectfield.h b/project/effectfield.h index f95c896cd..c946c475b 100644 --- a/project/effectfield.h +++ b/project/effectfield.h @@ -12,20 +12,11 @@ #include #include +#include "keyframe.h" + class EffectRow; class ComboAction; -class EffectKeyframe { -public: - long time; - int type; - QVariant data; - - // only for bezier type - QPointF pre_handle; - QPointF post_handle; -}; - class EffectField : public QObject { Q_OBJECT public: diff --git a/project/effectrow.cpp b/project/effectrow.cpp index c980c37f3..a9b7fd0f1 100644 --- a/project/effectrow.cpp +++ b/project/effectrow.cpp @@ -17,123 +17,123 @@ #include "ui/clickablelabel.h" EffectRow::EffectRow(Effect *parent, bool save, QGridLayout *uilayout, const QString &n, int row) : - parent_effect(parent), - savable(save), - keyframing(false), - ui(uilayout), - name(n), - ui_row(row), - just_made_unsafe_keyframe(false) + parent_effect(parent), + savable(save), + keyframing(false), + ui(uilayout), + name(n), + ui_row(row), + just_made_unsafe_keyframe(false) { - label = new ClickableLabel(name); + label = new ClickableLabel(name + ":"); - ui->addWidget(label, row, 0); + ui->addWidget(label, row, 0); - if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { + if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { connect(label, SIGNAL(clicked()), this, SLOT(focus_row())); - keyframe_nav = new KeyframeNavigator(); - connect(keyframe_nav, SIGNAL(goto_previous_key()), this, SLOT(goto_previous_key())); - connect(keyframe_nav, SIGNAL(toggle_key()), this, SLOT(toggle_key())); - connect(keyframe_nav, SIGNAL(goto_next_key()), this, SLOT(goto_next_key())); + keyframe_nav = new KeyframeNavigator(); + connect(keyframe_nav, SIGNAL(goto_previous_key()), this, SLOT(goto_previous_key())); + connect(keyframe_nav, SIGNAL(toggle_key()), this, SLOT(toggle_key())); + connect(keyframe_nav, SIGNAL(goto_next_key()), this, SLOT(goto_next_key())); connect(keyframe_nav, SIGNAL(keyframe_enabled_changed(bool)), this, SLOT(set_keyframe_enabled(bool))); connect(keyframe_nav, SIGNAL(clicked()), this, SLOT(focus_row())); - ui->addWidget(keyframe_nav, row, 6); - } + ui->addWidget(keyframe_nav, row, 6); + } } bool EffectRow::isKeyframing() { - return keyframing; + return keyframing; } void EffectRow::setKeyframing(bool b) { - if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { - keyframing = b; - keyframe_nav->enable_keyframes(b); - } + if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) { + keyframing = b; + keyframe_nav->enable_keyframes(b); + } } void EffectRow::set_keyframe_enabled(bool enabled) { - if (enabled) { - ComboAction* ca = new ComboAction(); - set_keyframe_now(ca); - undo_stack.push(ca); - } else { - if (QMessageBox::question(panel_effect_controls, "Disable Keyframes", "Disabling keyframes will delete all current keyframes. Are you sure you want to do this?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { - // clear - ComboAction* ca = new ComboAction(); - for (int i=0;ikeyframes.size();j++) { - ca->append(new KeyframeDelete(f, 0)); - } - } - undo_stack.push(ca); - panel_effect_controls->update_keyframes(); - } else { - setKeyframing(true); - } - } + if (enabled) { + ComboAction* ca = new ComboAction(); + set_keyframe_now(ca); + undo_stack.push(ca); + } else { + if (QMessageBox::question(panel_effect_controls, "Disable Keyframes", "Disabling keyframes will delete all current keyframes. Are you sure you want to do this?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { + // clear + ComboAction* ca = new ComboAction(); + for (int i=0;ikeyframes.size();j++) { + ca->append(new KeyframeDelete(f, 0)); + } + } + undo_stack.push(ca); + panel_effect_controls->update_keyframes(); + } else { + setKeyframing(true); + } + } } void EffectRow::goto_previous_key() { - long key = LONG_MIN; - Clip* c = parent_effect->parent_clip; - for (int i=0;ikeyframes.size();j++) { - long comp = f->keyframes.at(i).time - c->clip_in + c->timeline_in; - if (comp < sequence->playhead) { - key = qMax(comp, key); - } - } - } - if (key != LONG_MIN) panel_sequence_viewer->seek(key); + long key = LONG_MIN; + Clip* c = parent_effect->parent_clip; + for (int i=0;ikeyframes.size();j++) { + long comp = f->keyframes.at(j).time - c->clip_in + c->timeline_in; + if (comp < sequence->playhead) { + key = qMax(comp, key); + } + } + } + if (key != LONG_MIN) panel_sequence_viewer->seek(key); } void EffectRow::toggle_key() { - QVector key_fields; - QVector key_field_index; - Clip* c = parent_effect->parent_clip; - for (int j=0;jkeyframes.size();i++) { - long comp = c->timeline_in - c->clip_in + f->keyframes.at(i).time; - if (comp == sequence->playhead) { - key_fields.append(f); - key_field_index.append(i); - } - } - } + QVector key_fields; + QVector key_field_index; + Clip* c = parent_effect->parent_clip; + for (int j=0;jkeyframes.size();i++) { + long comp = c->timeline_in - c->clip_in + f->keyframes.at(i).time; + if (comp == sequence->playhead) { + key_fields.append(f); + key_field_index.append(i); + } + } + } - ComboAction* ca = new ComboAction(); - if (key_fields.size() == 0) { - // keyframe doesn't exist, set one - set_keyframe_now(ca); - } else { - for (int i=0;iappend(new KeyframeDelete(key_fields.at(i), key_field_index.at(i))); - } - } - undo_stack.push(ca); - panel_effect_controls->update_keyframes(); - panel_sequence_viewer->viewer_widget->update(); + ComboAction* ca = new ComboAction(); + if (key_fields.size() == 0) { + // keyframe doesn't exist, set one + set_keyframe_now(ca); + } else { + for (int i=0;iappend(new KeyframeDelete(key_fields.at(i), key_field_index.at(i))); + } + } + undo_stack.push(ca); + panel_effect_controls->update_keyframes(); + panel_sequence_viewer->viewer_widget->update(); } void EffectRow::goto_next_key() { - long key = LONG_MAX; - Clip* c = parent_effect->parent_clip; - for (int i=0;ikeyframes.size();j++) { - long comp = f->keyframes.at(i).time - c->clip_in + c->timeline_in; - if (comp > sequence->playhead) { - key = qMin(comp, key); - } - } - } - if (key != LONG_MAX) panel_sequence_viewer->seek(key); + long key = LONG_MAX; + Clip* c = parent_effect->parent_clip; + for (int i=0;ikeyframes.size();j++) { + long comp = f->keyframes.at(j).time - c->clip_in + c->timeline_in; + if (comp > sequence->playhead) { + key = qMin(comp, key); + } + } + } + if (key != LONG_MAX) panel_sequence_viewer->seek(key); } void EffectRow::focus_row() { @@ -141,58 +141,58 @@ void EffectRow::focus_row() { } EffectField* EffectRow::add_field(int type, const QString& id, int colspan) { - EffectField* field = new EffectField(this, type, id); + EffectField* field = new EffectField(this, type, id); if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION) connect(field, SIGNAL(clicked()), this, SLOT(focus_row())); - fields.append(field); - QWidget* element = field->get_ui_element(); - ui->addWidget(element, ui_row, fields.size(), 1, colspan); - connect(field, SIGNAL(changed()), parent_effect, SLOT(field_changed())); - return field; + fields.append(field); + QWidget* element = field->get_ui_element(); + ui->addWidget(element, ui_row, fields.size(), 1, colspan); + connect(field, SIGNAL(changed()), parent_effect, SLOT(field_changed())); + return field; } EffectRow::~EffectRow() { - for (int i=0;iplayhead-parent_effect->parent_clip->timeline_in+parent_effect->parent_clip->clip_in; - for (int j=0;jkeyframes.size();i++) { - if (f->keyframes.at(i).time == time) { - index = i; - break; - } - } - } + int index = -1; + long time = sequence->playhead-parent_effect->parent_clip->timeline_in+parent_effect->parent_clip->clip_in; + for (int j=0;jkeyframes.size();i++) { + if (f->keyframes.at(i).time == time) { + index = i; + break; + } + } + } - KeyframeSet* ks = new KeyframeSet(this, index, time, just_made_unsafe_keyframe); + KeyframeSet* ks = new KeyframeSet(this, index, time, just_made_unsafe_keyframe); - if (ca != NULL) { - just_made_unsafe_keyframe = false; - ca->append(ks); - } else { - if (index == -1) just_made_unsafe_keyframe = true; - ks->redo(); - delete ks; - } + if (ca != NULL) { + just_made_unsafe_keyframe = false; + ca->append(ks); + } else { + if (index == -1) just_made_unsafe_keyframe = true; + ks->redo(); + delete ks; + } - panel_effect_controls->update_keyframes(); + panel_effect_controls->update_keyframes(); } void EffectRow::delete_keyframe_at_time(ComboAction* ca, long time) { - for (int j=0;jkeyframes.size();i++) { - if (f->keyframes.at(i).time == time) { - ca->append(new KeyframeDelete(f, i)); - break; - } - } - } + for (int j=0;jkeyframes.size();i++) { + if (f->keyframes.at(i).time == time) { + ca->append(new KeyframeDelete(f, i)); + break; + } + } + } } const QString &EffectRow::get_name() { @@ -200,9 +200,9 @@ const QString &EffectRow::get_name() { } EffectField* EffectRow::field(int i) { - return fields.at(i); + return fields.at(i); } int EffectRow::fieldCount() { - return fields.size(); + return fields.size(); } diff --git a/project/keyframe.cpp b/project/keyframe.cpp index 8068d5129..3d12220df 100644 --- a/project/keyframe.cpp +++ b/project/keyframe.cpp @@ -1,2 +1,9 @@ #include "keyframe.h" + +EffectKeyframe::EffectKeyframe() { + pre_handle_x = -40; + pre_handle_y = 0; + post_handle_x = 40; + post_handle_y = 0; +} diff --git a/project/keyframe.h b/project/keyframe.h index 7cad20bfc..7974a8a1b 100644 --- a/project/keyframe.h +++ b/project/keyframe.h @@ -1,17 +1,21 @@ #ifndef KEYFRAME_H #define KEYFRAME_H - - #include -#include -class KeyframeData -{ +class EffectKeyframe { public: + EffectKeyframe(); + + long time; + int type; QVariant data; - QPoint handle_pre; - QPoint handle_post; + + // only for bezier type + double pre_handle_x; + double pre_handle_y; + double post_handle_x; + double post_handle_y; }; #endif // KEYFRAME_H diff --git a/project/undo.cpp b/project/undo.cpp index 5187d2a6e..3e2b445d0 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -738,20 +738,20 @@ void MediaRename::redo() { } KeyframeDelete::KeyframeDelete(EffectField *ifield, int iindex) : - field(ifield), - index(iindex), - old_project_changed(mainWindow->isWindowModified()) + field(ifield), + index(iindex), + old_project_changed(mainWindow->isWindowModified()) {} void KeyframeDelete::undo() { - field->keyframes.insert(index, deleted_key); + field->keyframes.insert(index, deleted_key); mainWindow->setWindowModified(old_project_changed); } void KeyframeDelete::redo() { - deleted_key = field->keyframes.at(index); - field->keyframes.removeAt(index); - mainWindow->setWindowModified(true); + deleted_key = field->keyframes.at(index); + field->keyframes.removeAt(index); + mainWindow->setWindowModified(true); } KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) : @@ -771,7 +771,7 @@ KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) : if (field->type == EFFECT_FIELD_DOUBLE) { old_values[i] = static_cast(field->ui_element)->getPreviousValue(); } else { - old_values[i] = field->keyframes.at(index).data; + old_values[i] = field->keyframes.at(index).data; } } new_values[i] = field->get_current_data(); @@ -781,12 +781,12 @@ KeyframeSet::KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe) : void KeyframeSet::undo() { if (enable_keyframes) row->setKeyframing(false); - bool append = (index == -1 || just_made_keyframe); + bool append = (index == -1 || just_made_keyframe); for (int i=0;ifieldCount();i++) { if (append) { - row->field(i)->keyframes.removeLast(); + row->field(i)->keyframes.removeLast(); } else { - row->field(i)->keyframes[index].data = old_values.at(i); + row->field(i)->keyframes[index].data = old_values.at(i); } } @@ -797,15 +797,15 @@ void KeyframeSet::undo() { void KeyframeSet::redo() { bool append = (index == -1 || (just_made_keyframe && !done)); for (int i=0;ifieldCount();i++) { - EffectField* f = row->field(i); + EffectField* f = row->field(i); if (append) { - EffectKeyframe k; - k.data = new_values.at(i); - k.time = time; - k.type = (f->keyframes.size() > 0) ? f->keyframes.last().type : EFFECT_KEYFRAME_LINEAR; - f->keyframes.append(k); + EffectKeyframe k; + k.data = new_values.at(i); + k.time = time; + k.type = (f->keyframes.size() > 0) ? f->keyframes.last().type : EFFECT_KEYFRAME_LINEAR; + f->keyframes.append(k); } else { - f->keyframes[index].data = new_values.at(i); + f->keyframes[index].data = new_values.at(i); } } row->setKeyframing(true); @@ -1229,9 +1229,9 @@ void RippleAction::redo() { ca->redo(); } -SetDouble::SetDouble(double* pointer, double new_value) : +SetDouble::SetDouble(double* pointer, double old_value, double new_value) : p(pointer), - oldval(*pointer), + oldval(old_value), newval(new_value), old_project_changed(mainWindow->isWindowModified()) {} diff --git a/project/undo.h b/project/undo.h index 9ef3a1e3b..fcb44f500 100644 --- a/project/undo.h +++ b/project/undo.h @@ -331,21 +331,21 @@ private: class KeyframeDelete : public QUndoCommand { public: - KeyframeDelete(EffectField* ifield, int iindex); + KeyframeDelete(EffectField* ifield, int iindex); void undo(); void redo(); private: - EffectField* field; - int index; - bool done; - EffectKeyframe deleted_key; - bool old_project_changed; + EffectField* field; + int index; + bool done; + EffectKeyframe deleted_key; + bool old_project_changed; }; class KeyframeSet : public QUndoCommand { public: - KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe); + KeyframeSet(EffectRow* r, int i, long t, bool justMadeKeyframe); void undo(); void redo(); QVector old_values; @@ -523,7 +523,7 @@ private: class SetDouble : public QUndoCommand { public: - SetDouble(double* pointer, double new_value); + SetDouble(double* pointer, double old_value, double new_value); void undo(); void redo(); private: diff --git a/ui/graphview.cpp b/ui/graphview.cpp index 5accaacad..84a87cebe 100644 --- a/ui/graphview.cpp +++ b/ui/graphview.cpp @@ -11,11 +11,17 @@ #include "project/effectfield.h" #include "ui/keyframedrawing.h" #include "project/undo.h" +#include "project/effect.h" #include "debug.h" #define GRAPH_ZOOM_SPEED 0.05 #define GRAPH_SIZE 100 +#define BEZIER_HANDLE_SIZE 3 + +#define BEZIER_HANDLE_NONE 1 +#define BEZIER_HANDLE_PRE 2 +#define BEZIER_HANDLE_POST 3 QColor get_curve_color(int index, int length) { QColor c; @@ -31,7 +37,8 @@ GraphView::GraphView(QWidget* parent) : mousedown(false), zoom(1.0), row(NULL), - moved_keys(false) + moved_keys(false), + current_handle(BEZIER_HANDLE_NONE) { setMouseTracking(true); } @@ -40,7 +47,8 @@ void GraphView::paintEvent(QPaintEvent *event) { QPainter p(this); if (panel_sequence_viewer->seq != NULL) { - // draw lines + // draw grid lines + //int graph_size = GRAPH_SIZE*zoom; bool draw_text = true;//(fontMetrics().height() < graph_size && fontMetrics().width("0000") < graph_size); @@ -75,53 +83,100 @@ void GraphView::paintEvent(QPaintEvent *event) { QPen line_pen; line_pen.setWidth(2); - for (int i=0;ifieldCount();i++) { - EffectField* field = row->field(i); + for (int i=0;ifieldCount();i++) { + EffectField* field = row->field(i); - if (field->type == EFFECT_FIELD_DOUBLE) { - // sort keyframes by time - QVector sorted_keys; - for (int k=0;kkeyframes.size();k++) { - bool inserted = false; - for (int j=0;jkeyframes.at(sorted_keys.at(j)).time > field->keyframes.at(k).time) { - sorted_keys.insert(j, k); - inserted = true; - break; - } - } - if (!inserted) { - sorted_keys.append(i); - } - } + if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) { + // sort keyframes by time + QVector sorted_keys; + for (int k=0;kkeyframes.size();k++) { + bool inserted = false; + for (int j=0;jkeyframes.at(sorted_keys.at(j)).time > field->keyframes.at(k).time) { + sorted_keys.insert(j, k); + inserted = true; + break; + } + } + if (!inserted) { + sorted_keys.append(k); + } + } - int last_key_x, last_key_y; + int last_key_x, last_key_y; + // draw lines for (int j=0;jkeyframes.at(sorted_keys.at(j)); - int key_x = get_screen_x(field->keyframes.at(key_index).time); - int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble()); + int key_x = get_screen_x(key.time); + int key_y = get_screen_y(key.data.toDouble()); line_pen.setColor(get_curve_color(i, row->fieldCount())); p.setPen(line_pen); - if (key_index == 0) { + if (j == 0) { p.drawLine(0, key_y, key_x, key_y); } else { - p.drawLine(last_key_x, last_key_y, key_x, key_y); + const EffectKeyframe& last_key = field->keyframes.at(sorted_keys.at(j-1)); + if (last_key.type == KEYFRAME_TYPE_HOLD) { + // hold + p.drawLine(last_key_x, last_key_y, key_x, last_key_y); + p.drawLine(key_x, last_key_y, key_x, key_y); + } else if (last_key.type == KEYFRAME_TYPE_BEZIER || key.type == KEYFRAME_TYPE_BEZIER) { + QPainterPath bezier_path; + bezier_path.moveTo(last_key_x, last_key_y); + if (last_key.type == KEYFRAME_TYPE_BEZIER && key.type == KEYFRAME_TYPE_BEZIER) { + // cubic bezier + bezier_path.cubicTo( + QPointF(last_key_x+last_key.post_handle_x, last_key_y+last_key.post_handle_y), + QPointF(key_x+key.pre_handle_x, key_y+key.pre_handle_y), + QPointF(key_x, key_y) + ); + } else if (key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier + // last keyframe is the bezier one + bezier_path.quadTo( + QPointF(last_key_x+last_key.post_handle_x, last_key_y+last_key.post_handle_y), + QPointF(key_x, key_y) + ); + } else { + // this keyframe is the bezier one + bezier_path.quadTo( + QPointF(key_x+key.pre_handle_x, key_y+key.pre_handle_y), + QPointF(key_x, key_y) + ); + } + p.drawPath(bezier_path); + } else { + // linear + p.drawLine(last_key_x, last_key_y, key_x, key_y); + } } last_key_x = key_x; last_key_y = key_y; } + + // draw keys for (int j=0;jkeyframes.at(sorted_keys.at(j)); - int key_x = get_screen_x(field->keyframes.at(key_index).time); - int key_y = get_screen_y(field->keyframes.at(key_index).data.toDouble()); + int key_x = get_screen_x(key.time); + int key_y = get_screen_y(key.data.toDouble()); - draw_keyframe(p, field->keyframes.at(key_index).type, key_x, key_y, (selected_keys.contains(key_index) && selected_keys_fields.contains(i))); + if (key.type == KEYFRAME_TYPE_BEZIER) { + p.setPen(Qt::gray); + + // pre handle line + QPointF pre_point(key_x + key.pre_handle_x*zoom, key_y + key.pre_handle_y*zoom); + p.drawLine(pre_point, QPointF(key_x, key_y)); + p.drawEllipse(pre_point, BEZIER_HANDLE_SIZE, BEZIER_HANDLE_SIZE); + + // post handle line + QPointF post_point(key_x + key.post_handle_x*zoom, key_y + key.post_handle_y*zoom); + p.drawLine(post_point, QPointF(key_x, key_y)); + p.drawEllipse(post_point, BEZIER_HANDLE_SIZE, BEZIER_HANDLE_SIZE); + } + + draw_keyframe(p, key.type, key_x, key_y, (selected_keys.contains(sorted_keys.at(j)) && selected_keys_fields.contains(i))); } } } @@ -153,13 +208,15 @@ void GraphView::mousePressEvent(QMouseEvent *event) { selected_keys.clear(); selected_keys_fields.clear(); } + current_handle = BEZIER_HANDLE_NONE; if (row != NULL) { for (int i=0;ifieldCount();i++) { EffectField* field = row->field(i); - if (field->type == EFFECT_FIELD_DOUBLE) { - for (int j=0;jkeyframes.size();j++) { - int key_x = get_screen_x(field->keyframes.at(j).time); - int key_y = get_screen_y(field->keyframes.at(j).data.toDouble()); + if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) { + for (int j=0;jkeyframes.size();j++) { + const EffectKeyframe& key = field->keyframes.at(j); + int key_x = get_screen_x(key.time); + int key_y = get_screen_y(key.data.toDouble()); if (event->pos().x() > key_x-KEYFRAME_SIZE && event->pos().x() < key_x+KEYFRAME_SIZE && event->pos().y() > key_y-KEYFRAME_SIZE @@ -167,6 +224,33 @@ void GraphView::mousePressEvent(QMouseEvent *event) { sel_key = j; sel_key_field = i; break; + } else { + // selecting a handle + QPointF pre_point(key_x + key.pre_handle_x*zoom, key_y + key.pre_handle_y*zoom); + if (event->pos().x() > pre_point.x()-BEZIER_HANDLE_SIZE + && event->pos().x() < pre_point.x()+BEZIER_HANDLE_SIZE + && event->pos().y() > pre_point.y()-BEZIER_HANDLE_SIZE + && event->pos().y() < pre_point.y()+BEZIER_HANDLE_SIZE) { + sel_key = j; + sel_key_field = i; + old_handle_x = key.pre_handle_x; + old_handle_y = key.pre_handle_y; + current_handle = BEZIER_HANDLE_PRE; + break; + } else { + QPointF post_point(key_x + key.post_handle_x*zoom, key_y + key.post_handle_y*zoom); + if (event->pos().x() > post_point.x()-BEZIER_HANDLE_SIZE + && event->pos().x() < post_point.x()+BEZIER_HANDLE_SIZE + && event->pos().y() > post_point.y()-BEZIER_HANDLE_SIZE + && event->pos().y() < post_point.y()+BEZIER_HANDLE_SIZE) { + sel_key = j; + sel_key_field = i; + old_handle_x = key.post_handle_x; + old_handle_y = key.post_handle_y; + current_handle = BEZIER_HANDLE_POST; + break; + } + } } } } @@ -179,16 +263,24 @@ void GraphView::mousePressEvent(QMouseEvent *event) { selected_keys_old_vals.clear(); selected_keys_old_doubles.clear(); + + int selected_key_type = -1; + for (int i=0;ifield(selected_keys_fields.at(j))->keyframes.at(selected_keys.at(i)).time); - selected_keys_old_doubles.append(row->field(selected_keys_fields.at(j))->keyframes.at(selected_keys.at(i)).data.toDouble()); + const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i)); + selected_keys_old_vals.append(key.time); + selected_keys_old_doubles.append(key.data.toDouble()); + + if (selected_key_type == -1) { + selected_key_type = key.type; + } else if (selected_key_type != key.type) { + selected_key_type = -2; } } update(); - emit selection_changed(selected_keys.size() > 0); + emit selection_changed(selected_keys.size() > 0, selected_key_type); } void GraphView::mouseMoveEvent(QMouseEvent *event) { @@ -200,39 +292,60 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) { start_y = event->pos().y(); update(); } else { - for (int i=0;ifield(selected_keys_fields.at(j))->keyframes[selected_keys.at(i)].time = selected_keys_old_vals.at(index) + (double(event->pos().x() - start_x)/zoom); - row->field(selected_keys_fields.at(j))->keyframes[selected_keys.at(i)].data = selected_keys_old_doubles.at(index) + (double(start_y - event->pos().y())/zoom); + switch (current_handle) { + case BEZIER_HANDLE_NONE: + for (int i=0;ifield(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].time = qRound(selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/zoom)); + row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = qRound(selected_keys_old_doubles.at(i) + (double(start_y - event->pos().y())/zoom)); } + moved_keys = true; + update_ui(false); + break; + case BEZIER_HANDLE_PRE: + row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].pre_handle_x = old_handle_x + double(event->pos().x() - start_x)/zoom; + row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].pre_handle_y = old_handle_y + double(event->pos().y() - start_y)/zoom; + moved_keys = true; + update_ui(false); + break; + case BEZIER_HANDLE_POST: + row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].post_handle_x = old_handle_x + double(event->pos().x() - start_x)/zoom; + row->field(selected_keys_fields.last())->keyframes[selected_keys.last()].post_handle_y = old_handle_y + double(event->pos().y() - start_y)/zoom; + moved_keys = true; + update_ui(false); + break; } - moved_keys = true; - update_ui(false); + } } } void GraphView::mouseReleaseEvent(QMouseEvent *event) { if (moved_keys && selected_keys.size() > 0) { - /*ComboAction* ca = new ComboAction(); - QVector rows; - QVector new_vals; - - for (int i=0;ikeyframe_times.at(selected_keys.at(i))); - - for (int j=0;jappend(new SetQVariant(&row->field(selected_keys_fields.at(j))->keyframe_data[selected_keys.at(i)], - selected_keys_old_doubles.at((i*selected_keys_fields.size())+j), - row->field(selected_keys_fields.at(j))->keyframe_data.at(selected_keys.at(i)))); + ComboAction* ca = new ComboAction(); + switch (current_handle) { + case BEZIER_HANDLE_NONE: + for (int i=0;ifield(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)]; + ca->append(new SetLong(&key.time, selected_keys_old_vals.at(i), key.time)); + ca->append(new SetQVariant(&key.data, selected_keys_old_doubles.at(i), key.data)); } - //ca->append(new KeyframeSet(row, selected_keys.at(i), 0, false)); - } - - ca->append(new KeyframeMove(rows, selected_keys, selected_keys_old_vals, new_vals)); - undo_stack.push(ca);*/ + break; + case BEZIER_HANDLE_PRE: + { + EffectKeyframe& key = row->field(selected_keys_fields.last())->keyframes[selected_keys.last()]; + ca->append(new SetDouble(&key.pre_handle_x, old_handle_x, key.pre_handle_x)); + ca->append(new SetDouble(&key.pre_handle_y, old_handle_y, key.pre_handle_y)); + } + break; + case BEZIER_HANDLE_POST: + { + EffectKeyframe& key = row->field(selected_keys_fields.last())->keyframes[selected_keys.last()]; + ca->append(new SetDouble(&key.post_handle_x, old_handle_x, key.post_handle_x)); + ca->append(new SetDouble(&key.post_handle_y, old_handle_y, key.post_handle_y)); + } + break; + } + undo_stack.push(ca); } moved_keys = false; mousedown = false; @@ -269,19 +382,39 @@ void GraphView::set_row(EffectRow *r) { selected_keys_fields.clear(); selected_keys_old_vals.clear(); selected_keys_old_doubles.clear(); - emit selection_changed(false); + emit selection_changed(false, -1); row = r; + if (row != NULL) { + field_visibility.resize(row->fieldCount()); + field_visibility.fill(true); + } + update(); +} + +void GraphView::set_selected_keyframe_type(int type) { + if (selected_keys.size() > 0) { + ComboAction* ca = new ComboAction(); + for (int i=0;ifield(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)]; + ca->append(new SetInt(&key.type, type)); + } + undo_stack.push(ca); + update_ui(false); + } +} + +void GraphView::set_field_visibility(int field, bool b) { + field_visibility[field] = b; update(); } void GraphView::set_scroll_x(int s) { - x_scroll = s;//qMax(0, s); - dout << x_scroll; + x_scroll = s; emit x_scroll_changed(x_scroll); } void GraphView::set_scroll_y(int s) { - y_scroll = s;//qMax(0, s); + y_scroll = s; emit y_scroll_changed(y_scroll); } diff --git a/ui/graphview.h b/ui/graphview.h index 97b6e1e2c..d7511184b 100644 --- a/ui/graphview.h +++ b/ui/graphview.h @@ -20,11 +20,14 @@ public: void wheelEvent(QWheelEvent *event); void set_row(EffectRow* r); + + void set_selected_keyframe_type(int type); + void set_field_visibility(int field, bool b); signals: void x_scroll_changed(int); void y_scroll_changed(int); void zoom_changed(double); - void selection_changed(bool); + void selection_changed(bool, int); private: int x_scroll; int y_scroll; @@ -39,13 +42,20 @@ private: int get_screen_x(double); int get_screen_y(double); + QVector field_visibility; + QVector selected_keys; QVector selected_keys_fields; QVector selected_keys_old_vals; QVector selected_keys_old_doubles; + double old_handle_x; + double old_handle_y; + bool moved_keys; + int current_handle; + EffectRow* row; }; diff --git a/ui/keyframeview.cpp b/ui/keyframeview.cpp index 7518c4575..4137f68e2 100644 --- a/ui/keyframeview.cpp +++ b/ui/keyframeview.cpp @@ -44,13 +44,13 @@ KeyframeView::KeyframeView(QWidget *parent) : } void KeyframeView::show_context_menu(const QPoint& pos) { - if (selected_fields.size() > 0) { + if (selected_fields.size() > 0) { QMenu menu(this); QAction* linear = menu.addAction("Linear"); linear->setData(KEYFRAME_TYPE_LINEAR); - QAction* smooth = menu.addAction("Smooth"); - smooth->setData(KEYFRAME_TYPE_BEZIER); + QAction* bezier = menu.addAction("Bezier"); + bezier->setData(KEYFRAME_TYPE_BEZIER); QAction* hold = menu.addAction("Hold"); hold->setData(KEYFRAME_TYPE_HOLD); menu.addSeparator(); @@ -67,12 +67,12 @@ void KeyframeView::menu_set_key_type(QAction* a) { panel_graph_editor->show(); } else { ComboAction* ca = new ComboAction(); - for (int i=0;iappend(new SetInt(&f->keyframes[selected_keyframes.at(i)].type, a->data().toInt())); + for (int i=0;iappend(new SetInt(&f->keyframes[selected_keyframes.at(i)].type, a->data().toInt())); } undo_stack.push(ca); - update_keys(); + update_ui(false); } } @@ -103,19 +103,19 @@ void KeyframeView::paintEvent(QPaintEvent*) { ClickableLabel* label = row->label; QWidget* contents = e->container->contents; - QVector key_times; + QVector key_times; int keyframe_y = label->y() + (label->height()>>1) + mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - e->container->title_bar->height()/* - y_scroll*/; - for (int l=0;lfieldCount();l++) { - EffectField* f = row->field(l); - for (int k=0;kkeyframes.size();k++) { - if (!key_times.contains(f->keyframes.at(k).time)) { - bool keyframe_selected = keyframeIsSelected(f, k); - long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time); - draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected); - key_times.append(f->keyframes.at(k).time); - } - } - } + for (int l=0;lfieldCount();l++) { + EffectField* f = row->field(l); + for (int k=0;kkeyframes.size();k++) { + if (!key_times.contains(f->keyframes.at(k).time)) { + bool keyframe_selected = keyframeIsSelected(f, k); + long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time); + draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected); + key_times.append(f->keyframes.at(k).time); + } + } + } rows.append(row); rowY.append(keyframe_y); @@ -150,8 +150,8 @@ void KeyframeView::paintEvent(QPaintEvent*) { } bool KeyframeView::keyframeIsSelected(EffectField *field, int keyframe) { - for (int i=0;iappend(new KeyframeDelete(selected_fields.at(i), selected_keyframes.at(i))); + // TODO these need to be sorted + ca->append(new KeyframeDelete(selected_fields.at(i), selected_keyframes.at(i))); del = true; } if (del) { - undo_stack.push(ca); + undo_stack.push(ca); selected_keyframes.clear(); - selected_fields.clear(); + selected_fields.clear(); update_keys(); panel_sequence_viewer->viewer_widget->update(); } else { - delete ca; + delete ca; } } @@ -211,7 +211,7 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { int mouse_x = event->x() + x_scroll; int mouse_y = event->y(); int row_index = -1; - int field_index = -1; + int field_index = -1; int keyframe_index = -1; long frame_diff = 0; long frame_min = getFrameFromScreenPoint(panel_effect_controls->zoom, mouse_x-KEYFRAME_SIZE); @@ -223,41 +223,41 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) { row->focus_row(); - for (int k=0;kfieldCount();k++) { - EffectField* f = row->field(k); - for (int j=0;jkeyframes.size();j++) { - long eval_keyframe_time = f->keyframes.at(j).time-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in); - if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) { - long eval_frame_diff = qAbs(eval_keyframe_time - drag_frame_start); - if (keyframe_index == -1 || eval_frame_diff < frame_diff) { - row_index = i; - field_index = k; - keyframe_index = j; - frame_diff = eval_frame_diff; - } - } - } - } + for (int k=0;kfieldCount();k++) { + EffectField* f = row->field(k); + for (int j=0;jkeyframes.size();j++) { + long eval_keyframe_time = f->keyframes.at(j).time-row->parent_effect->parent_clip->clip_in+(row->parent_effect->parent_clip->timeline_in-visible_in); + if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) { + long eval_frame_diff = qAbs(eval_keyframe_time - drag_frame_start); + if (keyframe_index == -1 || eval_frame_diff < frame_diff) { + row_index = i; + field_index = k; + keyframe_index = j; + frame_diff = eval_frame_diff; + } + } + } + } break; } } bool already_selected = false; keys_selected = false; - if (keyframe_index > -1) already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index); + if (keyframe_index > -1) already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index); if (!already_selected) { if (!(event->modifiers() & Qt::ShiftModifier)) { - selected_fields.clear(); + selected_fields.clear(); selected_keyframes.clear(); } if (keyframe_index > -1) { - selected_fields.append(rows.at(row_index)->field(field_index)); + selected_fields.append(rows.at(row_index)->field(field_index)); selected_keyframes.append(keyframe_index); } } - if (selected_fields.size() > 0) { - for (int i=0;ikeyframes.at(selected_keyframes.at(i)).time); + if (selected_fields.size() > 0) { + for (int i=0;ikeyframes.at(selected_keyframes.at(i)).time); } keys_selected = true; @@ -291,8 +291,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { panel_timeline->snapped = false; if (panel_timeline->snapping) { for (int i=0;iparent_row->parent_effect->parent_clip; + EffectField* field = selected_fields.at(i); + Clip* c = field->parent_row->parent_effect->parent_clip; long key_time = old_key_vals.at(i) + frame_diff - c->clip_in + c->timeline_in; long key_eval = key_time; if (panel_timeline->snap_to_point(sequence->playhead, &key_eval)) { @@ -303,11 +303,11 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { } // validate frame_diff (make sure no keyframes overlap each other) - for (int i=0;ikeyframes.size();j++) { - while (!keyframeIsSelected(field, j) && field->keyframes.at(j).time == eval_key + frame_diff) { + for (int j=0;jkeyframes.size();j++) { + while (!keyframeIsSelected(field, j) && field->keyframes.at(j).time == eval_key + frame_diff) { if (last_frame_diff > frame_diff) { frame_diff++; panel_timeline->snapped = false; @@ -321,8 +321,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { // apply frame_diffs for (int i=0;ikeyframes[selected_keyframes.at(i)].time = old_key_vals.at(i) + frame_diff; + EffectField* field = selected_fields.at(i); + field->keyframes[selected_keyframes.at(i)].time = old_key_vals.at(i) + frame_diff; } last_frame_diff = frame_diff; @@ -346,16 +346,16 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { for (int i=0;i= min_row && rowY.at(i) <= max_row) { EffectRow* row = rows.at(i); - for (int k=0;kfieldCount();k++) { - EffectField* field = row->field(k); - for (int j=0;jkeyframes.size();j++) { - long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time); - if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) { - selected_fields.append(field); - selected_keyframes.append(j); - } - } - } + for (int k=0;kfieldCount();k++) { + EffectField* field = row->field(k); + for (int j=0;jkeyframes.size();j++) { + long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time); + if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) { + selected_fields.append(field); + selected_keyframes.append(j); + } + } + } } } @@ -368,15 +368,15 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) { void KeyframeView::mouseReleaseEvent(QMouseEvent*) { if (dragging) { - ComboAction* ca = new ComboAction(); - for (int i=0;iappend(new SetLong( - &selected_fields.at(i)->keyframes[selected_keyframes.at(i)].time, - old_key_vals.at(i), - selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time - )); + ComboAction* ca = new ComboAction(); + for (int i=0;iappend(new SetLong( + &selected_fields.at(i)->keyframes[selected_keyframes.at(i)].time, + old_key_vals.at(i), + selected_fields.at(i)->keyframes.at(selected_keyframes.at(i)).time + )); } - undo_stack.push(ca); + undo_stack.push(ca); } select_rect = false;