diff --git a/effects/internal/transformeffect.cpp b/effects/internal/transformeffect.cpp index 48a4eed65..73d4353fd 100644 --- a/effects/internal/transformeffect.cpp +++ b/effects/internal/transformeffect.cpp @@ -1,4 +1,4 @@ -#include "transformeffect.h" +#include "transformeffect.h" #include #include @@ -13,19 +13,23 @@ #include "project/clip.h" #include "project/sequence.h" #include "io/media.h" +#include "io/math.h" #include "ui/labelslider.h" #include "ui/comboboxex.h" #include "panels/project.h" #include "debug.h" +#include "panels/panels.h" +#include "panels/viewer.h" +#include "ui/viewerwidget.h" + #define BLEND_MODE_NORMAL 0 #define BLEND_MODE_SCREEN 1 #define BLEND_MODE_MULTIPLY 2 #define BLEND_MODE_OVERLAY 3 TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) { - enable_coords = true; - enable_gizmos = true; + enable_coords = true; EffectRow* position_row = add_row("Position:"); position_x = position_row->add_field(EFFECT_FIELD_DOUBLE, "posx"); // position X @@ -61,6 +65,15 @@ TransformEffect::TransformEffect(Clip* c, const EffectMeta* em) : Effect(c, em) blend_mode_box->add_combo_item("Screen", BLEND_MODE_SCREEN); blend_mode_box->add_combo_item("Multiply", BLEND_MODE_MULTIPLY); + top_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + top_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_left_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + bottom_right_gizmo = add_gizmo(GIZMO_TYPE_DOT); + left_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + right_center_gizmo = add_gizmo(GIZMO_TYPE_DOT); + // set defaults scale_y->set_enabled(false); uniform_scale_field->set_bool_value(true); @@ -145,43 +158,17 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i } void TransformEffect::gizmo_draw(double timecode, GLTextureCoords& coords) { - // proof of concept drawing pattern - - /*float color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - glBegin(GL_TRIANGLES); - glColor4f(1.0, 0.0, 0.0, 0.5); - glVertex3f(coords.vertexTopLeftX, coords.vertexTopLeftY, 1); - glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); - glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); - glColor4f(0.0, 0.0, 1.0, 0.5); - glVertex3f(coords.vertexTopRightX, coords.vertexTopRightY, 1); - glVertex3f(coords.vertexBottomLeftX, coords.vertexBottomLeftY, 1); - glVertex3f(coords.vertexBottomRightX, coords.vertexBottomRightY, 1); - glEnd(); - - glColor4f(color[0], color[1], color[2], color[3]);*/ + top_left_gizmo->set_pos(coords.vertexTopLeftX, coords.vertexTopLeftY); + top_center_gizmo->set_pos(lerp(coords.vertexTopLeftX, coords.vertexTopRightX, 0.5), lerp(coords.vertexTopLeftY, coords.vertexTopRightY, 0.5)); + top_right_gizmo->set_pos(coords.vertexTopRightX, coords.vertexTopRightY); + right_center_gizmo->set_pos(lerp(coords.vertexTopRightX, coords.vertexBottomRightX, 0.5), lerp(coords.vertexTopRightY, coords.vertexBottomRightY, 0.5)); + bottom_right_gizmo->set_pos(coords.vertexBottomRightX, coords.vertexBottomRightY); + bottom_center_gizmo->set_pos(lerp(coords.vertexBottomRightX, coords.vertexBottomLeftX, 0.5), lerp(coords.vertexBottomRightY, coords.vertexBottomLeftY, 0.5)); + bottom_left_gizmo->set_pos(coords.vertexBottomLeftX, coords.vertexBottomLeftY); + left_center_gizmo->set_pos(lerp(coords.vertexBottomLeftX, coords.vertexTopLeftX, 0.5), lerp(coords.vertexBottomLeftY, coords.vertexTopLeftY, 0.5)); } -void TransformEffect::gizmo_down(QMouseEvent *event, double) { - dragging = true; - drag_start_x = event->pos().x(); - drag_start_y = event->pos().y(); -} - -void TransformEffect::gizmo_move(QMouseEvent *event, double timecode) { - if (dragging) { - position_x->set_double_value(position_x->get_double_value(timecode) + (event->pos().x() - drag_start_x)); - position_y->set_double_value(position_y->get_double_value(timecode) + (event->pos().y() - drag_start_y)); - - drag_start_x = event->pos().x(); - drag_start_y = event->pos().y(); - - field_changed(); - } -} - -void TransformEffect::gizmo_up(QMouseEvent *event, double) { - dragging = false; +void TransformEffect::gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode) { + position_x->set_double_value(position_x->get_double_value(timecode) + x_movement); + position_y->set_double_value(position_y->get_double_value(timecode) + y_movement); } diff --git a/effects/internal/transformeffect.h b/effects/internal/transformeffect.h index 38834c45d..c2f936544 100644 --- a/effects/internal/transformeffect.h +++ b/effects/internal/transformeffect.h @@ -11,29 +11,32 @@ public: void process_coords(double timecode, GLTextureCoords& coords, int data); void gizmo_draw(double timecode, GLTextureCoords& coords); - void gizmo_down(QMouseEvent *event, double); - void gizmo_move(QMouseEvent *event, double); - void gizmo_up(QMouseEvent *event, double); - - EffectField* position_x; - EffectField* position_y; - EffectField* scale_x; - EffectField* scale_y; - EffectField* uniform_scale_field; - EffectField* rotation; - EffectField* anchor_x_box; - EffectField* anchor_y_box; - EffectField* opacity; - EffectField* blend_mode_box; + void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode); public slots: void toggle_uniform_scale(bool enabled); private: - int default_anchor_x; - int default_anchor_y; + EffectField* position_x; + EffectField* position_y; + EffectField* scale_x; + EffectField* scale_y; + EffectField* uniform_scale_field; + EffectField* rotation; + EffectField* anchor_x_box; + EffectField* anchor_y_box; + EffectField* opacity; + EffectField* blend_mode_box; - bool dragging; - int drag_start_x; - int drag_start_y; + EffectGizmo* top_left_gizmo; + EffectGizmo* top_center_gizmo; + EffectGizmo* top_right_gizmo; + EffectGizmo* bottom_left_gizmo; + EffectGizmo* bottom_center_gizmo; + EffectGizmo* bottom_right_gizmo; + EffectGizmo* left_center_gizmo; + EffectGizmo* right_center_gizmo; + + int default_anchor_x; + int default_anchor_y; }; #endif // TRANSFORMEFFECT_H diff --git a/olive.pro b/olive.pro index f81d7e964..368d37887 100644 --- a/olive.pro +++ b/olive.pro @@ -88,7 +88,8 @@ SOURCES += \ project/transition.cpp \ project/effectrow.cpp \ project/effectfield.cpp \ - effects/internal/cubetransition.cpp + effects/internal/cubetransition.cpp \ + project/effectgizmo.cpp HEADERS += \ mainwindow.h \ @@ -156,7 +157,8 @@ HEADERS += \ project/transition.h \ project/effectrow.h \ project/effectfield.h \ - effects/internal/cubetransition.h + effects/internal/cubetransition.h \ + project/effectgizmo.h FORMS += \ mainwindow.ui \ diff --git a/panels/project.cpp b/panels/project.cpp index 96ad97d39..3db428698 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -1496,6 +1496,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int if (t != NULL) { stream.writeStartElement("transition"); stream.writeAttribute("id", QString::number(j)); + stream.writeAttribute("length", QString::number(t->get_true_length())); t->save(stream); stream.writeEndElement(); // transition } diff --git a/project/effect.cpp b/project/effect.cpp index bd524fb98..228c45bee 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -223,7 +223,6 @@ Effect::Effect(Clip* c, const EffectMeta *em) : enable_shader(false), enable_coords(false), enable_superimpose(false), - enable_gizmos(false), glslProgram(NULL), texture(NULL), isOpen(false), @@ -456,7 +455,21 @@ 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 *Effect::gizmo(int i) { + return gizmos.at(i); +} + +int Effect::gizmo_count(){ + return gizmos.size(); } void Effect::refresh() {} @@ -834,9 +847,30 @@ void Effect::process_audio(double, double, quint8*, int, int) { } void Effect::gizmo_draw(double, GLTextureCoords &) {} -void Effect::gizmo_down(QMouseEvent *, double) {} -void Effect::gizmo_move(QMouseEvent *, double) {} -void Effect::gizmo_up(QMouseEvent *, double) {} +void Effect::gizmo_move(EffectGizmo* , int , int , double ) {} + +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); + + QMatrix4x4 view_matrix(view_val[0], view_val[4], view_val[8], view_val[12], view_val[1], view_val[5], view_val[9], view_val[13], view_val[2], view_val[6], view_val[10], view_val[14], view_val[3], view_val[7], view_val[11], view_val[15]); + QMatrix4x4 projection_matrix(projection_val[0], projection_val[4], projection_val[8], projection_val[12], projection_val[1], projection_val[5], projection_val[9], projection_val[13], projection_val[2], projection_val[6], projection_val[10], projection_val[14], projection_val[3], projection_val[7], projection_val[11], projection_val[15]); + + for (int i=0;iget_x(), g->get_y(), 0, 1.0); + QVector4D screen_pos = world_pos * (view_matrix * projection_matrix); + + g->set_screen_pos(screen_pos.x(), screen_pos.y()); + } +} + +bool Effect::are_gizmos_enabled() { + return (gizmos.size() > 0); +} void Effect::redraw(double) { /* diff --git a/project/effect.h b/project/effect.h index be7979199..928da37c3 100644 --- a/project/effect.h +++ b/project/effect.h @@ -1,4 +1,4 @@ -#ifndef EFFECT_H +#ifndef EFFECT_H #define EFFECT_H #include @@ -105,6 +105,7 @@ qint16 mix_audio_sample(qint16 a, qint16 b); #include "effectfield.h" #include "effectrow.h" +#include "effectgizmo.h" class Effect : public QObject { Q_OBJECT @@ -121,6 +122,10 @@ public: EffectRow* row(int i); int row_count(); + EffectGizmo* add_gizmo(int type); + EffectGizmo* gizmo(int i); + int gizmo_count(); + bool is_enabled(); void set_enabled(bool b); @@ -140,8 +145,7 @@ public: bool enable_shader; bool enable_coords; - bool enable_superimpose; - bool enable_gizmos; + bool enable_superimpose; int getIterations(); void setIterations(int i); @@ -154,9 +158,9 @@ public: virtual void process_audio(double timecode_start, double timecode_end, quint8* samples, int nb_bytes, int channel_count); virtual void gizmo_draw(double timecode, GLTextureCoords& coords); - virtual void gizmo_down(QMouseEvent* event, double); - virtual void gizmo_move(QMouseEvent* event, double); - virtual void gizmo_up(QMouseEvent* event, double); + virtual void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode); + void gizmo_world_to_screen(); + bool are_gizmos_enabled(); public slots: void field_changed(); private slots: @@ -179,6 +183,7 @@ private: bool isOpen; QVector rows; + QVector gizmos; QGridLayout* ui_layout; QWidget* ui; bool bound; diff --git a/project/effectgizmo.cpp b/project/effectgizmo.cpp new file mode 100644 index 000000000..a6a747863 --- /dev/null +++ b/project/effectgizmo.cpp @@ -0,0 +1,35 @@ +#include "effectgizmo.h" + +EffectGizmo::EffectGizmo(int type) : + type(type) +{} + +void EffectGizmo::set_pos(int ix, int iy) { + x = ix; + y = iy; +} + +int EffectGizmo::get_x() { + return x; +} + +int EffectGizmo::get_y() { + return y; +} + +int EffectGizmo::get_type() { + return type; +} + +void EffectGizmo::set_screen_pos(int isx, int isy) { + sx = isx; + sy = isy; +} + +int EffectGizmo::get_screen_x() { + return sx; +} + +int EffectGizmo::get_screen_y() { + return sy; +} diff --git a/project/effectgizmo.h b/project/effectgizmo.h new file mode 100644 index 000000000..6a9588d95 --- /dev/null +++ b/project/effectgizmo.h @@ -0,0 +1,30 @@ +#ifndef EFFECTGIZMO_H +#define EFFECTGIZMO_H + +#define GIZMO_TYPE_DOT 0 +#define GIZMO_TYPE_QUAD 1 + +#include + +class EffectGizmo +{ +public: + EffectGizmo(int type); + + void set_pos(int ix, int iy); + int get_x(); + int get_y(); + int get_type(); + + void set_screen_pos(int isx, int isy); + int get_screen_x(); + int get_screen_y(); +private: + int type; + int x; + int y; + int sx; + int sy; +}; + +#endif // EFFECTGIZMO_H diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 8f01b761d..e1470406e 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -135,9 +135,23 @@ double get_timecode(Clip* c, long playhead) { } void ViewerWidget::mousePressEvent(QMouseEvent* event) { - if (waveform) seek_from_click(event->x()); - dragging = true; - if (gizmos != NULL) gizmos->gizmo_down(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + if (waveform) { + seek_from_click(event->x()); + } else { + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); + + if (gizmos != NULL) { + int clicked = -1; + for (int i=0;igizmo_count();i++) { + EffectGizmo* g = gizmos->gizmo(i); + + dout << "gizmo" << i << "screen pos was" << g->get_screen_x() << g->get_screen_y() << "compared to" << g->get_x() << g->get_y(); + } + dout << "clicked on" << clicked; + } + } + dragging = true; } void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { @@ -150,14 +164,24 @@ void ViewerWidget::mouseMoveEvent(QMouseEvent* event) { mimeData->setText("h"); // QMimeData will fail without some kind of data drag->setMimeData(mimeData); drag->exec(); - } + } else { + double multiplier = (double) viewer->seq->width / (double) width(); + + int x_movement = (event->pos().x() - drag_start_x)*multiplier; + int y_movement = (event->pos().y() - drag_start_y)*multiplier; + +// gizmos->gizmo_move(g, x_movement, y_movement, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + + drag_start_x = event->pos().x(); + drag_start_y = event->pos().y(); + + gizmos->field_changed(); + } } - if (gizmos != NULL) gizmos->gizmo_move(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); } void ViewerWidget::mouseReleaseEvent(QMouseEvent *event) { - dragging = false; - if (gizmos != NULL) gizmos->gizmo_up(event, get_timecode(gizmos->parent_clip, gizmos->parent_clip->sequence->playhead)); + dragging = false; } void ViewerWidget::drawTitleSafeArea() { @@ -470,7 +494,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) Effect* e = c->effects.at(j); process_effect(c, e, timecode, coords, composite_texture, fbo_switcher, TA_NO_TRANSITION); - if (!rendering && gizmos == NULL && e->enable_gizmos && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { + if (!rendering && gizmos == NULL && e->are_gizmos_enabled() && (e->container->selected || panel_timeline->is_clip_selected(c, true))) { gizmos = e; draw_gizmos = true; } @@ -528,9 +552,9 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) float rows = coords.grid_size; float cols = coords.grid_size; - for (float i=0;i& nests, bool render_audio) glBindTexture(GL_TEXTURE_2D, 0); // unbind texture if (draw_gizmos) { - gizmos->gizmo_draw(timecode, coords); + float color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + + float multiplier = (float) width() / (float) viewer->seq->width; + float dot_size = 20 * multiplier; + + gizmos->gizmo_draw(timecode, coords); // set correct gizmo coords + gizmos->gizmo_world_to_screen(); + for (int j=0;jgizmo_count();j++) { + EffectGizmo* g = gizmos->gizmo(j); + switch (g->get_type()) { + case GIZMO_TYPE_DOT: // draw dot + glBegin(GL_QUADS); + glColor4f(1.0, 1.0, 1.0, 1.0); + glVertex2f(g->get_x()-dot_size, g->get_y()-dot_size); + glVertex2f(g->get_x()+dot_size, g->get_y()-dot_size); + glVertex2f(g->get_x()+dot_size, g->get_y()+dot_size); + glVertex2f(g->get_x()-dot_size, g->get_y()+dot_size); + glEnd(); + break; + } + } + + glColor4f(color[0], color[1], color[2], color[3]); } if (!nests.isEmpty()) { diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index 3b3cc709f..0be77f172 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -1,4 +1,4 @@ -#ifndef VIEWERWIDGET_H +#ifndef VIEWERWIDGET_H #define VIEWERWIDGET_H #include @@ -14,6 +14,7 @@ struct Clip; struct MediaStream; class QOpenGLFramebufferObject; class Effect; +class EffectGizmo; struct GLTextureCoords; class ViewerWidget : public QOpenGLWidget @@ -48,6 +49,9 @@ private: GLuint draw_clip(QOpenGLFramebufferObject *clip, GLuint texture, bool clear); void process_effect(Clip* c, Effect* e, double timecode, GLTextureCoords& coords, GLuint& composite_texture, bool& fbo_switcher, int data); Effect* gizmos; + int drag_start_x; + int drag_start_y; + EffectGizmo* selected_gizmo; private slots: void retry(); void show_context_menu();