From 5b956729b339f35e5aba6914d34c204f847bc0dc Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 7 May 2020 18:12:18 +1000 Subject: [PATCH] gizmos: work towards gizmos in the matrix transform node --- app/node/generator/matrix/matrix.cpp | 187 ++++++++++++++++++++++--- app/node/generator/matrix/matrix.h | 37 ++++- app/node/generator/polygon/polygon.cpp | 11 +- app/node/generator/polygon/polygon.h | 6 +- app/node/node.cpp | 6 +- app/node/node.h | 6 +- app/widget/viewer/viewerdisplay.cpp | 6 +- 7 files changed, 219 insertions(+), 40 deletions(-) diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp index 55f87357e..bafa5d530 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -20,9 +20,12 @@ #include "matrix.h" +#include #include #include +#include "common/range.h" + OLIVE_NAMESPACE_ENTER MatrixGenerator::MatrixGenerator() @@ -97,55 +100,201 @@ NodeValueTable MatrixGenerator::Value(NodeValueDatabase &value) const return output; } -/* +bool MatrixGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize &viewport) +{ + GizmoSharedData gizmo_data(viewport, scale); + + QPointF anchor_pt = GetGizmoAnchorPoint(db, gizmo_data); + int anchor_radius = GetGizmoAnchorPointRadius(); + + if (InRange(p.x(), anchor_pt.x(), anchor_radius * 2.0) + && InRange(p.y(), anchor_pt.y(), anchor_radius * 2.0)) { + gizmo_drag_ = anchor_input_; + gizmo_start2_ = db[position_input_].Get(NodeParam::kVec2).value(); + } else { + gizmo_drag_ = position_input_; + } + + gizmo_start_ = db[gizmo_drag_].Get(NodeParam::kVec2).value(); + gizmo_mouse_start_ = p; + + return true; +} + +void MatrixGenerator::GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) +{ + QVector2D movement = 2.0 * QVector2D(p - gizmo_mouse_start_) / scale; + QVector2D new_pos = gizmo_start_ + movement; + + if (!gizmo_x_dragger_.IsStarted()) { + gizmo_x_dragger_.Start(gizmo_drag_, time, 0); + } + + if (!gizmo_y_dragger_.IsStarted()) { + gizmo_y_dragger_.Start(gizmo_drag_, time, 1); + } + + gizmo_x_dragger_.Drag(new_pos.x()); + gizmo_y_dragger_.Drag(new_pos.y()); + + if (gizmo_drag_ == anchor_input_) { + // If we're dragging the anchor, counter the position at the same time + QVector2D new_pos2 = gizmo_start2_ + movement; + + if (!gizmo_x2_dragger_.IsStarted()) { + gizmo_x2_dragger_.Start(position_input_, time, 0); + } + + if (!gizmo_y2_dragger_.IsStarted()) { + gizmo_y2_dragger_.Start(position_input_, time, 1); + } + + gizmo_x2_dragger_.Drag(new_pos2.x()); + gizmo_y2_dragger_.Drag(new_pos2.y()); + + InvalidateVisible(position_input_, position_input_); + } + + InvalidateVisible(gizmo_drag_, gizmo_drag_); +} + +void MatrixGenerator::GizmoRelease() +{ + gizmo_x_dragger_.End(); + gizmo_y_dragger_.End(); + gizmo_x2_dragger_.End(); + gizmo_y2_dragger_.End(); +} + bool MatrixGenerator::HasGizmos() const { return true; } -void MatrixGenerator::DrawGizmos(NodeValueDatabase &db, QPainter *p, const QVector2D &scale) const +void MatrixGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize& viewport) const { - // FIXME: Implement this properly p->setPen(Qt::white); - // Fold values into a matrix - QMatrix4x4 matrix = GenerateMatrix(db); + GizmoSharedData gizmo_data(viewport, scale); - // Set QPainter transform to our matrix - p->setTransform(matrix.toTransform()); + { + // Fold values into a matrix + QMatrix4x4 matrix; + matrix.scale(gizmo_data.half_scale); + matrix *= GenerateMatrix(db, false); + matrix.scale(gizmo_data.inverted_half_scale); - // Draw ellipse - p->drawEllipse(QRect(0, 0, 100, 100)); + // Create rect and transform it + QVector points = {QPointF(-100, -100), + QPointF(100, -100), + QPointF(100, 100), + QPointF(-100, 100), + QPointF(-100, -100)}; + QPolygonF poly(points); + poly = matrix.toTransform().map(poly); + poly.translate(gizmo_data.half_viewport); + + // Draw square + p->drawPolyline(poly); + } + + { + // Draw anchor point marker (with no anchor point translation) + QPointF pt = GetGizmoAnchorPoint(db, gizmo_data); + + // Draw anchor point + int anchor_pt_radius = GetGizmoAnchorPointRadius(); + + p->drawEllipse(pt, anchor_pt_radius, anchor_pt_radius); + + p->drawLines({QLineF(pt.x() - anchor_pt_radius, pt.y(), + pt.x() + anchor_pt_radius, pt.y()), + QLineF(pt.x(), pt.y() - anchor_pt_radius, + pt.x(), pt.y() + anchor_pt_radius)}); + } } -*/ QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value) const +{ + return GenerateMatrix(value[position_input_].Take(NodeParam::kVec2).value(), + value[rotation_input_].Take(NodeParam::kFloat).toFloat(), + value[scale_input_].Take(NodeParam::kVec2).value(), + value[uniform_scale_input_].Take(NodeParam::kBoolean).toBool(), + value[anchor_input_].Take(NodeParam::kVec2).value()); +} + +QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueDatabase &value, bool ignore_anchor) const +{ + QVector2D anchor; + + if (!ignore_anchor) { + anchor = value[anchor_input_].Get(NodeParam::kVec2).value(); + } + + return GenerateMatrix(value[position_input_].Get(NodeParam::kVec2).value(), + value[rotation_input_].Get(NodeParam::kFloat).toFloat(), + value[scale_input_].Get(NodeParam::kVec2).value(), + value[uniform_scale_input_].Get(NodeParam::kBoolean).toBool(), + anchor); +} + +QMatrix4x4 MatrixGenerator::GenerateMatrix(const QVector2D& pos, + const float& rot, + const QVector2D& scale, + bool uniform_scale, + const QVector2D& anchor) { QMatrix4x4 mat; - // Position translate - QVector2D pos = value[position_input_].Take(NodeParam::kVec2).value(); + // Position mat.translate(pos); // Rotation - mat.rotate(value[rotation_input_].Take(NodeParam::kFloat).toFloat(), 0, 0, 1); + mat.rotate(rot, 0, 0, 1); - // Scale and Uniform Scale - QVector2D scale = value[scale_input_].Take(NodeParam::kVec2).value(); - if (value[uniform_scale_input_].Take(NodeParam::kBoolean).toBool()) { - scale.setY(scale.x()); + // Scale + if (uniform_scale) { + QVector2D uniformed(scale.x(), scale.x()); + mat.scale(uniformed); + } else { + mat.scale(scale); } - mat.scale(scale); // Anchor Point - mat.translate(-value[anchor_input_].Take(NodeParam::kVec2).value()); + mat.translate(-anchor); return mat; } +QPointF MatrixGenerator::GetGizmoAnchorPoint(const NodeValueDatabase &db, + const GizmoSharedData& gizmo_data) const +{ + QMatrix4x4 matrix; + matrix.scale(gizmo_data.half_scale); + matrix *= GenerateMatrix(db, true); + matrix.scale(gizmo_data.inverted_half_scale); + + QPointF pt = matrix.toTransform().map(QPointF()); + pt += gizmo_data.half_viewport; + + return pt; +} + +int MatrixGenerator::GetGizmoAnchorPointRadius() +{ + return QFontMetrics(qApp->font()).height() / 2; +} + void MatrixGenerator::UniformScaleChanged() { scale_input_->set_property("disabley", uniform_scale_input_->get_standard_value().toBool()); } +MatrixGenerator::GizmoSharedData::GizmoSharedData(const QSize &viewport, const QVector2D &scale) +{ + half_viewport = QPointF(viewport.width() / 2, viewport.height() / 2); + half_scale = scale * 0.5; + inverted_half_scale = QVector2D(1.0f / half_scale.x(), 1.0f / half_scale.y()); +} + OLIVE_NAMESPACE_EXIT diff --git a/app/node/generator/matrix/matrix.h b/app/node/generator/matrix/matrix.h index fce9c3a8d..453f8eb76 100644 --- a/app/node/generator/matrix/matrix.h +++ b/app/node/generator/matrix/matrix.h @@ -21,7 +21,10 @@ #ifndef MATRIXGENERATOR_H #define MATRIXGENERATOR_H +#include + #include "node/node.h" +#include "node/inputdragger.h" OLIVE_NAMESPACE_ENTER @@ -43,11 +46,33 @@ public: virtual NodeValueTable Value(NodeValueDatabase& value) const override; - //virtual bool HasGizmos() const override; - //virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p, const QVector2D &scale) const override; + virtual bool HasGizmos() const override; + virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override; + + virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override; + virtual void GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) override; + virtual void GizmoRelease() override; private: + struct GizmoSharedData { + GizmoSharedData(const QSize& viewport, const QVector2D& scale); + + QPointF half_viewport; + QVector2D half_scale; + QVector2D inverted_half_scale; + }; + QMatrix4x4 GenerateMatrix(NodeValueDatabase& value) const; + QMatrix4x4 GenerateMatrix(const NodeValueDatabase& value, bool ignore_anchor) const; + static QMatrix4x4 GenerateMatrix(const QVector2D &pos, + const float &rot, + const QVector2D &scale, + bool uniform_scale, + const QVector2D &anchor); + + QPointF GetGizmoAnchorPoint(const NodeValueDatabase &db, const GizmoSharedData &gizmo_data) const; + static int GetGizmoAnchorPointRadius(); + NodeInput* gizmo_drag_; NodeInput* position_input_; @@ -59,6 +84,14 @@ private: NodeInput* anchor_input_; + QVector2D gizmo_start_; + QVector2D gizmo_start2_; + QPointF gizmo_mouse_start_; + NodeInputDragger gizmo_x_dragger_; + NodeInputDragger gizmo_y_dragger_; + NodeInputDragger gizmo_x2_dragger_; + NodeInputDragger gizmo_y2_dragger_; + private slots: void UniformScaleChanged(); diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp index 15441c1f9..37b896492 100644 --- a/app/node/generator/polygon/polygon.cpp +++ b/app/node/generator/polygon/polygon.cpp @@ -100,7 +100,7 @@ bool PolygonGenerator::HasGizmos() const return true; } -void PolygonGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, const QVector2D &scale) const +void PolygonGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize &viewport) const { if (!points_input_->GetSize()) { return; @@ -112,16 +112,13 @@ void PolygonGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, cons QVector points = GetGizmoCoordinates(db, scale); QVector rects = GetGizmoRects(points); - foreach (const QRectF& r, rects) { - p->drawRect(r); - } - points.append(points.first()); p->drawPolyline(points.constData(), points.size()); + p->drawRects(rects); } -bool PolygonGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, const QVector2D &scale) +bool PolygonGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize& viewport) { QVector points = GetGizmoCoordinates(db, scale); QVector rects = GetGizmoRects(points); @@ -157,7 +154,7 @@ void PolygonGenerator::GizmoMove(const QPointF &p, const QVector2D &scale, const InvalidateVisible(gizmo_drag_, gizmo_drag_); } -void PolygonGenerator::GizmoRelease(const QPointF &p) +void PolygonGenerator::GizmoRelease() { gizmo_x_dragger_.End(); gizmo_y_dragger_.End(); diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h index 21d4e4106..01398eff4 100644 --- a/app/node/generator/polygon/polygon.h +++ b/app/node/generator/polygon/polygon.h @@ -44,11 +44,11 @@ public: virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override; virtual bool HasGizmos() const override; - virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale) const override; + virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override; - virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale) override; + virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override; virtual void GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) override; - virtual void GizmoRelease(const QPointF &p) override; + virtual void GizmoRelease() override; private: QVector GetGizmoCoordinates(const NodeValueDatabase &db, const QVector2D &scale) const; diff --git a/app/node/node.cpp b/app/node/node.cpp index 2b702bf68..90283cb96 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -287,11 +287,11 @@ bool Node::HasGizmos() const return false; } -void Node::DrawGizmos(const NodeValueDatabase &, QPainter *, const QVector2D &) const +void Node::DrawGizmos(const NodeValueDatabase &, QPainter *, const QVector2D &, const QSize &) const { } -bool Node::GizmoPress(const NodeValueDatabase &, const QPointF &, const QVector2D &) +bool Node::GizmoPress(const NodeValueDatabase &, const QPointF &, const QVector2D &, const QSize &viewport) { return false; } @@ -300,7 +300,7 @@ void Node::GizmoMove(const QPointF &, const QVector2D &, const rational &) { } -void Node::GizmoRelease(const QPointF &) +void Node::GizmoRelease() { } diff --git a/app/node/node.h b/app/node/node.h index 1f345428b..0c03c0a7d 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -383,11 +383,11 @@ public: virtual bool HasGizmos() const; - virtual void DrawGizmos(const NodeValueDatabase& db, QPainter* p, const QVector2D &scale) const; + virtual void DrawGizmos(const NodeValueDatabase& db, QPainter* p, const QVector2D &scale, const QSize& viewport) const; - virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF& p, const QVector2D &scale); + virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF& p, const QVector2D &scale, const QSize& viewport); virtual void GizmoMove(const QPointF& p, const QVector2D &scale, const rational &time); - virtual void GizmoRelease(const QPointF& p); + virtual void GizmoRelease(); const QString& GetLabel() const; void SetLabel(const QString& s); diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index 04a5dbc6f..62a551b1b 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -192,7 +192,7 @@ void ViewerDisplayWidget::SetTime(const rational &time) void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) { if (gizmos_ - && gizmos_->GizmoPress(gizmo_db_, event->pos(), QVector2D(GetTexturePosition(size())))) { + && gizmos_->GizmoPress(gizmo_db_, event->pos(), QVector2D(GetTexturePosition(size())), size())) { gizmo_click_ = true; gizmo_drag_time_ = GetGizmoTime(); return; @@ -236,7 +236,7 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event) void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event) { if (gizmo_click_) { - gizmos_->GizmoRelease(GetTexturePosition(event->pos())); + gizmos_->GizmoRelease(); gizmo_click_ = false; return; @@ -299,7 +299,7 @@ void ViewerDisplayWidget::paintGL() gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time, node_time)); QPainter p(this); - gizmos_->DrawGizmos(gizmo_db_, &p, QVector2D(GetTexturePosition(size()))); + gizmos_->DrawGizmos(gizmo_db_, &p, QVector2D(GetTexturePosition(size())), size()); } // Draw action/title safe areas