From 7b64536c7ddc9065161ecb0b62da4686eb758409 Mon Sep 17 00:00:00 2001 From: p9malino26 Date: Thu, 15 Sep 2022 16:05:50 +0100 Subject: [PATCH] polygon: Implement polygon gizmo selection and dragging --- app/node/generator/polygon/polygon.cpp | 21 +++++++ app/node/generator/polygon/polygon.h | 4 +- app/node/gizmo/CMakeLists.txt | 1 + app/node/gizmo/point.cpp | 16 ++--- app/node/gizmo/point.h | 13 ++++- app/node/gizmo/selectable.cpp | 7 +++ app/node/gizmo/selectable.h | 13 +++++ app/node/node.h | 2 + app/widget/viewer/viewerdisplay.cpp | 81 +++++++++++++++++++------- app/widget/viewer/viewerdisplay.h | 4 ++ 10 files changed, 130 insertions(+), 32 deletions(-) create mode 100644 app/node/gizmo/selectable.cpp create mode 100644 app/node/gizmo/selectable.h diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp index ec65f8b7f3..c46fec5885 100644 --- a/app/node/generator/polygon/polygon.cpp +++ b/app/node/generator/polygon/polygon.cpp @@ -145,6 +145,12 @@ NodeGizmo *PolygonGenerator::CreateAppropriateGizmo() return AddDraggableGizmo(); } +template<> +NodeGizmo *PolygonGenerator::CreateAppropriateGizmo() +{ + return AddDraggableGizmo(); +} + template void PolygonGenerator::ValidateGizmoVectorSize(QVector &vec, int new_sz) { @@ -216,6 +222,21 @@ void PolygonGenerator::UpdateGizmoPositions(const NodeValueRow &row, const NodeG poly_gizmo_->SetPath(GeneratePath(points).translated(half_res)); } +void PolygonGenerator::UpdateGizmosOnSelection(QList &selected) +{ + for (int i = 0; i < gizmo_position_handles_.size(); i++) { + auto& position_handle = gizmo_position_handles_[i]; + bool point_selected = selected.contains(position_handle); + bool beziers_visible = (selected.size() == 1 && point_selected); + position_handle->SetSelected(point_selected); + + gizmo_bezier_handles_[i*2]->SetVisible(beziers_visible); + gizmo_bezier_lines_[i*2]->SetVisible(beziers_visible); + gizmo_bezier_handles_[i*2+1]->SetVisible(beziers_visible); + gizmo_bezier_lines_[i*2+1]->SetVisible(beziers_visible); + } +} + ShaderCode PolygonGenerator::GetShaderCode(const ShaderRequest &request) const { if (request.id == QStringLiteral("rgb")) { diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h index dd7e5623b6..97ded75d69 100644 --- a/app/node/generator/polygon/polygon.h +++ b/app/node/generator/polygon/polygon.h @@ -27,6 +27,7 @@ #include "node/generator/shape/generatorwithmerge.h" #include "node/gizmo/line.h" #include "node/gizmo/path.h" +#include "node/gizmo/selectable.h" #include "node/gizmo/point.h" #include "node/node.h" #include "node/inputdragger.h" @@ -53,6 +54,7 @@ class PolygonGenerator : public GeneratorWithMerge virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override; virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals) override; + virtual void UpdateGizmosOnSelection(QList &selected) override; virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override; @@ -77,7 +79,7 @@ protected slots: NodeGizmo *CreateAppropriateGizmo(); PathGizmo *poly_gizmo_; - QVector gizmo_position_handles_; + QVector gizmo_position_handles_; QVector gizmo_bezier_handles_; QVector gizmo_bezier_lines_; diff --git a/app/node/gizmo/CMakeLists.txt b/app/node/gizmo/CMakeLists.txt index c9f530d227..c923b9d967 100644 --- a/app/node/gizmo/CMakeLists.txt +++ b/app/node/gizmo/CMakeLists.txt @@ -32,5 +32,6 @@ set(OLIVE_SOURCES node/gizmo/screen.h node/gizmo/text.cpp node/gizmo/text.h + node/gizmo/selectable.cpp PARENT_SCOPE ) diff --git a/app/node/gizmo/point.cpp b/app/node/gizmo/point.cpp index d60ccf5bd0..cccb0196bf 100644 --- a/app/node/gizmo/point.cpp +++ b/app/node/gizmo/point.cpp @@ -19,25 +19,27 @@ ***/ #include "point.h" +#include #include namespace olive { -PointGizmo::PointGizmo(const Shape &shape, bool smaller, QObject *parent) : +PointGizmo::PointGizmo(const Shape &shape, bool smaller, QObject *parent, bool selectable) : DraggableGizmo{parent}, shape_(shape), - smaller_(smaller) + smaller_(smaller), + selectable_(selectable) { } -PointGizmo::PointGizmo(const Shape &shape, QObject *parent) : - PointGizmo(shape, false, parent) +PointGizmo::PointGizmo(const Shape &shape, QObject *parent,bool selectable) : + PointGizmo(shape, false, parent, selectable) { } -PointGizmo::PointGizmo(QObject *parent) : - PointGizmo(kSquare, parent) +PointGizmo::PointGizmo(QObject *parent, bool selectable) : + PointGizmo(kSquare, parent, selectable) { } @@ -47,7 +49,7 @@ void PointGizmo::Draw(QPainter *p) const if (shape_ != kAnchorPoint) { p->setPen(Qt::NoPen); - p->setBrush(Qt::white); + p->setBrush(selected_ ? Qt::red : Qt::white); } switch (shape_) { diff --git a/app/node/gizmo/point.h b/app/node/gizmo/point.h index 8f8a02f652..0c49934c9a 100644 --- a/app/node/gizmo/point.h +++ b/app/node/gizmo/point.h @@ -37,9 +37,9 @@ class PointGizmo : public DraggableGizmo kAnchorPoint }; - explicit PointGizmo(const Shape &shape, bool smaller, QObject *parent = nullptr); - explicit PointGizmo(const Shape &shape, QObject *parent = nullptr); - explicit PointGizmo(QObject *parent = nullptr); + explicit PointGizmo(const Shape &shape, bool smaller, QObject *parent = nullptr, bool selectable = false); + explicit PointGizmo(const Shape &shape, QObject *parent = nullptr, bool selectable = false); + explicit PointGizmo(QObject *parent = nullptr, bool selectable = false); const Shape &GetShape() const { return shape_; } void SetShape(const Shape &s) { shape_ = s; } @@ -50,6 +50,11 @@ class PointGizmo : public DraggableGizmo bool GetSmaller() const { return smaller_; } void SetSmaller(bool e) { smaller_ = e; } + bool IsSelectable() const { return selectable_; } + + void SetSelected(bool e) { selected_ = e; } + bool IsSelected() const { return selected_; } + virtual void Draw(QPainter *p) const override; QRectF GetClickingRect(const QTransform &t) const; @@ -64,6 +69,8 @@ class PointGizmo : public DraggableGizmo QPointF point_; bool smaller_; + bool selected_ = false; + bool selectable_ = false; }; diff --git a/app/node/gizmo/selectable.cpp b/app/node/gizmo/selectable.cpp new file mode 100644 index 0000000000..08c32df8f7 --- /dev/null +++ b/app/node/gizmo/selectable.cpp @@ -0,0 +1,7 @@ +#include "selectable.h" + +namespace olive { +SelectableGizmo::SelectableGizmo(QObject *parent) + :PointGizmo(parent, true) +{} +} diff --git a/app/node/gizmo/selectable.h b/app/node/gizmo/selectable.h new file mode 100644 index 0000000000..516432ebb3 --- /dev/null +++ b/app/node/gizmo/selectable.h @@ -0,0 +1,13 @@ +#ifndef SELECTABLE_H +#define SELECTABLE_H +#include "node/gizmo/point.h" + +namespace olive { +class SelectableGizmo: public PointGizmo { +Q_OBJECT +public: + explicit SelectableGizmo(QObject *parent = nullptr); +}; +} + +#endif diff --git a/app/node/node.h b/app/node/node.h index 2ca325d34b..ecc860e580 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -62,6 +62,7 @@ namespace olive { class NodeGraph; class Folder; +class PointGizmo; /** * @brief A single processing unit that can be connected with others to create intricate processing systems @@ -905,6 +906,7 @@ class Node : public QObject virtual QTransform GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const { return QTransform(); } virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals){} + virtual void UpdateGizmosOnSelection(QList &selected) {} const QString& GetLabel() const; void SetLabel(const QString& s); diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index 70bbc51f9d..0e441c9c46 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -21,6 +21,7 @@ #include "viewerdisplay.h" #include +#include #include #include #include @@ -177,6 +178,7 @@ void ViewerDisplayWidget::SetGizmos(Node *node) { if (gizmos_ != node) { gizmos_ = node; + selected_gizmos_.clear(); update(); } @@ -445,6 +447,7 @@ void ViewerDisplayWidget::OnPaint() p.setWorldTransform(gizmo_last_draw_transform_); gizmos_->UpdateGizmoPositions(gizmo_db_, NodeTraverser::GenerateGlobals(gizmo_params_, range)); + gizmos_->UpdateGizmosOnSelection(selected_gizmos_); foreach (NodeGizmo *gizmo, gizmos_->GetGizmos()) { if (gizmo->IsVisible()) { gizmo->Draw(&p); @@ -822,6 +825,25 @@ bool ViewerDisplayWidget::OnMousePress(QMouseEvent *event) gizmo_start_drag_ = event->pos(); gizmo_last_drag_ = gizmo_start_drag_; current_gizmo_->SetGlobals(NodeTraverser::GenerateGlobals(gizmo_params_, GenerateGizmoTime())); + //handle selection + if (PointGizmo* point_gizmo = dynamic_cast(current_gizmo_)) { + if (point_gizmo->IsSelectable()) { + for (PointGizmo* pg: selected_gizmos_) + pg->SetGlobals(NodeTraverser::GenerateGlobals(gizmo_params_, GenerateGizmoTime())); + if (event->modifiers().testFlag(Qt::ControlModifier)) { + if (selected_gizmos_.contains(point_gizmo)) { + selected_gizmos_.removeOne(point_gizmo); + } else { + selected_gizmos_.append(point_gizmo); + } + } else if (!selected_gizmos_.contains(point_gizmo)) { + selected_gizmos_.clear(); + selected_gizmos_.append(point_gizmo); + } + + } + update(); + } } else { @@ -872,7 +894,7 @@ bool ViewerDisplayWidget::OnMouseMove(QMouseEvent *event) } else if (current_gizmo_) { // Signal movement - if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { + if (PointGizmo *point_gizmo = dynamic_cast(current_gizmo_) ) { if (!gizmo_drag_started_) { QPointF start = gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; @@ -880,32 +902,41 @@ bool ViewerDisplayWidget::OnMouseMove(QMouseEvent *event) NodeTraverser t; t.SetCacheVideoParams(gizmo_params_); NodeValueRow row = t.GenerateRow(gizmos_, TimeRange(gizmo_time, gizmo_time + gizmo_params_.frame_rate_as_time_base())); - - draggable->DragStart(row, start.x(), start.y(), gizmo_time); + + if (point_gizmo->IsSelected()) { + for (DraggableGizmo* gizmo: selected_gizmos_) + gizmo->DragStart(row, start.x(), start.y(), gizmo_time); + } else { + point_gizmo->DragStart(row, start.x(), start.y(), gizmo_time); + } gizmo_drag_started_ = true; } - QPointF v = event->pos() * gizmo_last_draw_transform_inverted_; - switch (draggable->GetDragValueBehavior()) { - case DraggableGizmo::kAbsolute: - // Above value is correct - break; - case DraggableGizmo::kDeltaFromPrevious: - v -= gizmo_last_drag_ * gizmo_last_draw_transform_inverted_; - gizmo_last_drag_ = event->pos(); - break; - case DraggableGizmo::kDeltaFromStart: - v -= gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; - break; + switch (point_gizmo->GetDragValueBehavior()) { + case DraggableGizmo::kAbsolute: + // Above value is correct + break; + case DraggableGizmo::kDeltaFromPrevious: + v -= gizmo_last_drag_ * gizmo_last_draw_transform_inverted_; + gizmo_last_drag_ = event->pos(); + break; + case DraggableGizmo::kDeltaFromStart: + v -= gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; + break; } - draggable->DragMove(v.x(), v.y(), event->modifiers()); + if (point_gizmo->IsSelected()) { + for (DraggableGizmo* gizmo: selected_gizmos_) + gizmo->DragMove(v.x(), v.y(), event->modifiers()); + } else + point_gizmo->DragMove(v.x(), v.y(), event->modifiers()); + update(); return true; - } - + } } + return false; } @@ -940,8 +971,13 @@ bool ViewerDisplayWidget::OnMouseRelease(QMouseEvent *e) // Handle gizmo if (gizmo_drag_started_) { MultiUndoCommand *command = new MultiUndoCommand(); - if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { - draggable->DragEnd(command); + if (PointGizmo* point_gizmo= dynamic_cast(current_gizmo_)) { + + if (point_gizmo ->IsSelected()) { + for (DraggableGizmo* gizmo: selected_gizmos_) + gizmo->DragEnd(command); + } else + point_gizmo->DragEnd(command); } Core::instance()->undo_stack()->pushIfHasChildren(command); gizmo_drag_started_ = false; @@ -960,15 +996,18 @@ bool ViewerDisplayWidget::OnMouseDoubleClick(QMouseEvent *event) if (text_edit_) { return ForwardMouseEventToTextEdit(event); } else if (event->button() == Qt::LeftButton && gizmos_) { + selected_gizmos_.clear(); + QPointF ptr = TransformViewerSpaceToBufferSpace(event->pos()); foreach (NodeGizmo *g, gizmos_->GetGizmos()) { if (TextGizmo *text = dynamic_cast(g)) { if (text->GetRect().contains(ptr)) { OpenTextGizmo(text, event); - return true; } } } + update(); + return true; } return false; diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index ab39a2b10b..dee12848ef 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -55,6 +55,7 @@ namespace olive { * the same texture object, use SetTexture() since it will nearly always be faster to just set it than to check *and* * set it. */ +class PointGizmo; class ViewerDisplayWidget : public ManagedDisplayWidget, public TimeTargetObject { Q_OBJECT @@ -290,6 +291,8 @@ protected slots: void CloseTextEditor(); + bool DragGizmo(DraggableGizmo* gizmo, QMouseEvent *event); + /** * @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL(). */ @@ -408,6 +411,7 @@ protected slots: ViewerTextEditorToolBar *text_toolbar_; QTransform text_transform_; QTransform text_transform_inverted_; + QList selected_gizmos_; private slots: void UpdateFromQueue();