diff --git a/app/node/distort/crop/cropdistortnode.cpp b/app/node/distort/crop/cropdistortnode.cpp index a55993ff8..5b52df6b1 100644 --- a/app/node/distort/crop/cropdistortnode.cpp +++ b/app/node/distort/crop/cropdistortnode.cpp @@ -79,10 +79,12 @@ void CropDistortNode::Value(const NodeValueRow &value, const NodeGlobals &global { ShaderJob job; job.Insert(value); - job.Insert(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); + job.SetWillChangeImageSize(false); + + if (TexturePtr texture = job.Get(kTextureInput).toTexture()) { + job.Insert(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, QVector2D(texture->params().width(), texture->params().height()), this)); - if (job.Get(kTextureInput).toTexture()) { if (!qIsNull(job.Get(kLeftInput).toDouble()) || !qIsNull(job.Get(kRightInput).toDouble()) || !qIsNull(job.Get(kTopInput).toDouble()) diff --git a/app/node/distort/transform/transformdistortnode.cpp b/app/node/distort/transform/transformdistortnode.cpp index d8cc8ecd9..3743698c1 100644 --- a/app/node/distort/transform/transformdistortnode.cpp +++ b/app/node/distort/transform/transformdistortnode.cpp @@ -84,7 +84,7 @@ void TransformDistortNode::Retranslate() void TransformDistortNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { // Generate matrix - QMatrix4x4 generated_matrix = GenerateMatrix(value, true, false, false, false); + QMatrix4x4 generated_matrix = GenerateMatrix(value, false, false, false); // Pop texture NodeValue texture_meta = value[kTextureInput]; @@ -143,7 +143,7 @@ void TransformDistortNode::Hash(QCryptographicHash &hash, const NodeGlobals &glo TexturePtr tex = db[kTextureInput].toTexture(); if (tex) { VideoParams tex_params = tex->params(); - QMatrix4x4 matrix = GenerateMatrix(db, true, false, false, false); + QMatrix4x4 matrix = GenerateMatrix(db, false, false, false); matrix = GenerateAutoScaledMatrix(matrix, db, globals, tex_params); if (!matrix.isIdentity()) { @@ -162,7 +162,7 @@ void TransformDistortNode::GizmoDragStart(const NodeValueRow &row, double x, dou if (gizmo == anchor_gizmo_) { - gizmo_inverted_transform_ = GenerateMatrix(row, false, true, true, false).toTransform().inverted(); + gizmo_inverted_transform_ = GenerateMatrix(row, true, true, false).toTransform().inverted(); } else if (IsAScaleGizmo(gizmo)) { @@ -204,7 +204,7 @@ void TransformDistortNode::GizmoDragStart(const NodeValueRow &row, double x, dou } // Store current matrix - gizmo_inverted_transform_ = GenerateMatrix(row, false, true, true, true).toTransform().inverted(); + gizmo_inverted_transform_ = GenerateMatrix(row, true, true, true).toTransform().inverted(); } else if (gizmo == rotation_gizmo_) { @@ -389,7 +389,7 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N // Fold values into a matrix for the rectangle QMatrix4x4 rectangle_matrix; rectangle_matrix.scale(sequence_half_res); - rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false, false), + rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false), sequence_res, tex_sz, tex_offset, @@ -409,7 +409,7 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N // Draw anchor point QMatrix4x4 anchor_matrix; anchor_matrix.scale(sequence_half_res); - anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, true, false, false), + anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, true, false, false), sequence_res, tex_sz, tex_offset, @@ -432,6 +432,15 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N SetInputProperty(kAnchorInput, QStringLiteral("offset"), tex_sz * 0.5); } +QTransform TransformDistortNode::GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const +{ + if (TexturePtr texture = row[kTextureInput].toTexture()) { + auto m = GenerateMatrix(row, false, false, false); + return GenerateAutoScaledMatrix(m, row, globals, texture->params()).toTransform(); + } + return super::GizmoTransformation(row, globals); +} + QPointF TransformDistortNode::CreateScalePoint(double x, double y, const QPointF &half_res, const QMatrix4x4 &mat) { return mat.map(QPointF(x, y)) + half_res; diff --git a/app/node/distort/transform/transformdistortnode.h b/app/node/distort/transform/transformdistortnode.h index 7d1aa1b3b..b8bbf6c73 100644 --- a/app/node/distort/transform/transformdistortnode.h +++ b/app/node/distort/transform/transformdistortnode.h @@ -82,6 +82,7 @@ public: AutoScaleType autoscale_type = kAutoScaleNone); virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals) override; + virtual QTransform GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const override; static const QString kTextureInput; static const QString kAutoscaleInput; diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp index 7dcaf49c0..81e43c4ea 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -90,63 +90,33 @@ void MatrixGenerator::Retranslate() void MatrixGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { // Push matrix output - QMatrix4x4 mat = GenerateMatrix(value, true, false, false, false); + QMatrix4x4 mat = GenerateMatrix(value, false, false, false); table->Push(NodeValue::kMatrix, mat, this); } -QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const +QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool ignore_anchor, bool ignore_position, bool ignore_scale) const { QVector2D anchor; QVector2D position; QVector2D scale; if (!ignore_anchor) { - if (take) { - // Take and store - anchor = value[kAnchorInput].toVec2(); - } else { - // Get and store - anchor = value[kAnchorInput].toVec2(); - } - } else if (take) { - // Just take - value[kAnchorInput].toVec2(); + anchor = value[kAnchorInput].toVec2(); } if (!ignore_scale) { - if (take) { - scale = value[kScaleInput].toVec2(); - } else { - scale = value[kScaleInput].toVec2(); - } - } else if (take) { - value[kScaleInput].toVec2(); + scale = value[kScaleInput].toVec2(); } if (!ignore_position) { - if (take) { - position = value[kPositionInput].toVec2(); - } else { - position = value[kPositionInput].toVec2(); - } - } else if (take) { - value[kPositionInput].toVec2(); + position = value[kPositionInput].toVec2(); } - if (take) { - return GenerateMatrix(position, - value[kRotationInput].toDouble(), - scale, - value[kUniformScaleInput].toBool(), - anchor); - } else { - return GenerateMatrix(position, - value[kRotationInput].toDouble(), - scale, - value[kUniformScaleInput].toBool(), - anchor); - - } + return GenerateMatrix(position, + value[kRotationInput].toDouble(), + scale, + value[kUniformScaleInput].toBool(), + anchor); } QMatrix4x4 MatrixGenerator::GenerateMatrix(const QVector2D& pos, diff --git a/app/node/generator/matrix/matrix.h b/app/node/generator/matrix/matrix.h index 62ed196c4..5d93cb51d 100644 --- a/app/node/generator/matrix/matrix.h +++ b/app/node/generator/matrix/matrix.h @@ -53,7 +53,7 @@ public: static const QString kAnchorInput; protected: - QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const; + QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool ignore_anchor, bool ignore_position, bool ignore_scale) const; static QMatrix4x4 GenerateMatrix(const QVector2D &pos, const float &rot, const QVector2D &scale, diff --git a/app/node/hashtraverser.cpp b/app/node/hashtraverser.cpp index ad4e8df60..1422df346 100644 --- a/app/node/hashtraverser.cpp +++ b/app/node/hashtraverser.cpp @@ -50,7 +50,7 @@ QByteArray HashTraverser::GetHash(const Node *node, const Node::ValueHint &hint, //Hash(reference); // Our overrides will generate a hash from this - NodeValueTable table = GenerateTable(node, hint, range); + NodeValueTable table = GenerateTable(node, range); NodeValue final_value = GenerateRowValueElement(hint, NodeValue::kTexture, &table); HashNodeValue(final_value); diff --git a/app/node/node.h b/app/node/node.h index 74ef7a484..47cdeaa1d 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -889,6 +889,8 @@ public: return gizmos_; } + virtual QTransform GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const { return QTransform(); } + virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals){} const QString& GetLabel() const; diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index 536d6de39..57767b6b1 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -381,7 +381,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const switch (type) { case Track::kVideo: if (IsInputConnected(kTextureInput)) { - NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), GetValueHintForInput(kTextureInput), TimeRange(0, 0)); + NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), TimeRange(0, 0)); rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value(); if (!r.isNaN()) { return r; @@ -390,7 +390,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const break; case Track::kAudio: if (IsInputConnected(kSamplesInput)) { - NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), GetValueHintForInput(kSamplesInput), TimeRange(0, 0)); + NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), TimeRange(0, 0)); rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value();; if (!r.isNaN()) { return r; diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index 9cdce106b..75ff4b3a8 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -141,6 +141,16 @@ int NodeTraverser::GenerateRowValueElementIndex(const Node *node, const QString return GenerateRowValueElementIndex(node->GetValueHintForInput(input, element), node->GetInputDataType(input), table); } +void NodeTraverser::Transform(QTransform *transform, const Node *start, const Node *end, const TimeRange &range) +{ + transform_ = transform; + transform_start_ = start; + + GenerateTable(end, range); + + transform_ = nullptr; +} + NodeGlobals NodeTraverser::GenerateGlobals(const VideoParams ¶ms, const TimeRange &time) { return NodeGlobals(QVector2D(params.width(), params.height()), params.pixel_aspect_ratio(), time); @@ -179,6 +189,20 @@ int NodeTraverser::GetChannelCountFromJob(const GenerateJob &job) return VideoParams::kRGBAChannelCount; } +TexturePtr NodeTraverser::GetMainTextureFromJob(const GenerateJob &job) +{ + // FIXME: Should probably take Node::GetEffectInput into account here + for (auto it=job.GetValues().cbegin(); it!=job.GetValues().cend(); it++) { + if (it.value().type() == NodeValue::kTexture) { + if (TexturePtr t = it.value().toTexture()) { + return t; + } + } + } + + return nullptr; +} + NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& input, const TimeRange& range) { // If input is connected, retrieve value directly @@ -187,7 +211,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu TimeRange adjusted_range = node->InputTimeAdjustment(input, -1, range); // Value will equal something from the connected node, follow it - return GenerateTable(node->GetConnectedOutput(input), node->GetValueHintForInput(input), adjusted_range); + return GenerateTable(node->GetConnectedOutput(input), adjusted_range); } else { @@ -205,7 +229,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu TimeRange adjusted_range = node->InputTimeAdjustment(input, i, range); if (node->IsInputConnected(input, i)) { - sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), node->GetValueHintForInput(input, i), adjusted_range); + sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), adjusted_range); } else { QVariant input_value = node->GetValueAtTime(input, adjusted_range.in(), i); sub_tbl.Push(node->GetInputDataType(input), input_value, node); @@ -231,11 +255,12 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu } NodeTraverser::NodeTraverser() : - cancel_(nullptr) + cancel_(nullptr), + transform_(nullptr) { } -NodeValueTable NodeTraverser::GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange& range) +NodeValueTable NodeTraverser::GenerateTable(const Node *n, const TimeRange& range) { const Track* track = dynamic_cast(n); if (track) { @@ -264,7 +289,24 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const Node::ValueHint NodeValueTable table = database.Merge(); // By this point, the node should have all the inputs it needs to render correctly - n->Value(row, GenerateGlobals(video_params_, range), &table); + NodeGlobals globals = GenerateGlobals(video_params_, range); + n->Value(row, globals, &table); + + if (transform_) { + if (!transform_start_) { + if (!transform_ignore_.contains(n)) { + QTransform t = n->GizmoTransformation(row, globals); + if (!t.isIdentity()) { + qDebug() << "transforming" << n; + (*transform_) *= t; + } + + transform_ignore_.append(n); + } + } else if (transform_start_ == n) { + transform_start_ = nullptr; + } + } return table; } else { @@ -288,7 +330,7 @@ NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeR NodeValueTable table; if (active_block) { - table = GenerateTable(active_block, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(active_block)), Track::TransformRangeForBlock(active_block, range)); + table = GenerateTable(active_block, Track::TransformRangeForBlock(active_block, range)); } return table; @@ -307,12 +349,21 @@ void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range) ShaderJob job = val.value(); + PreProcessRow(range, job.GetValues()); + VideoParams tex_params = GetCacheVideoParams(); tex_params.set_channel_count(GetChannelCountFromJob(job)); + if (!job.GetWillChangeImageSize()) { + if (TexturePtr texture = GetMainTextureFromJob(job)) { + tex_params.set_width(texture->params().width()); + tex_params.set_height(texture->params().height()); + tex_params.set_divider(texture->params().divider()); + } + } + TexturePtr tex = CreateTexture(tex_params); - PreProcessRow(range, job.GetValues()); ProcessShader(tex, val.source(), range, job); val.set_value(tex); diff --git a/app/node/traverser.h b/app/node/traverser.h index ac770dc19..9471fec0f 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -37,7 +37,7 @@ class NodeTraverser public: NodeTraverser(); - NodeValueTable GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange &range); + NodeValueTable GenerateTable(const Node *n, const TimeRange &range); NodeValueDatabase GenerateDatabase(const Node *node, const TimeRange &range); @@ -50,6 +50,8 @@ public: int GenerateRowValueElementIndex(const Node::ValueHint &hint, NodeValue::Type preferred_type, const NodeValueTable *table); int GenerateRowValueElementIndex(const Node *node, const QString &input, int element, const NodeValueTable *table); + void Transform(QTransform *transform, const Node *start, const Node *end, const TimeRange &range); + static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time); static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time) { @@ -78,6 +80,8 @@ public: static int GetChannelCountFromJob(const GenerateJob& job); + static TexturePtr GetMainTextureFromJob(const GenerateJob& job); + protected: NodeValueTable ProcessInput(const Node *node, const QString &input, const TimeRange &range); @@ -152,6 +156,10 @@ private: const QAtomicInt *cancel_; + const Node *transform_start_; + QTransform *transform_; + QVector transform_ignore_; + }; } diff --git a/app/render/job/shaderjob.h b/app/render/job/shaderjob.h index 4ee789a98..0669e0c42 100644 --- a/app/render/job/shaderjob.h +++ b/app/render/job/shaderjob.h @@ -36,6 +36,7 @@ public: { iterations_ = 1; iterative_input_ = nullptr; + will_change_image_size_ = true; } const QString& GetShaderID() const @@ -99,6 +100,9 @@ public: return vertex_overrides_; } + bool GetWillChangeImageSize() const { return will_change_image_size_; } + void SetWillChangeImageSize(bool e) { will_change_image_size_ = e; } + private: QString shader_id_; @@ -110,6 +114,8 @@ private: QVector vertex_overrides_; + bool will_change_image_size_; + }; } diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 598fe75e9..ab33e7522 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -52,7 +52,7 @@ TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational NodeValueTable table; if (Node *texture_output = viewer->GetConnectedTextureOutput()) { - table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kTextureInput), range); + table = GenerateTable(texture_output, range); } NodeValue tex_val = table.Get(NodeValue::kTexture); @@ -193,7 +193,7 @@ void RenderProcessor::Run() NodeValueTable table; if (Node *texture_output = viewer->GetConnectedSampleOutput()) { - table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kSamplesInput),time); + table = GenerateTable(texture_output, time); } NodeValue sample_val = table.Get(NodeValue::kSamples); @@ -290,7 +290,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim int max_dest_sz = audio_params.time_to_samples(range_for_block.length()); // Destination buffer - NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block)); + NodeValueTable table = GenerateTable(b, Track::TransformRangeForBlock(b, range_for_block)); SampleBuffer samples_from_this_block = table.Take(NodeValue::kSamples).toSamples(); ClipBlock *clip_cast = dynamic_cast(b); diff --git a/app/widget/nodevaluetree/nodevaluetree.cpp b/app/widget/nodevaluetree/nodevaluetree.cpp index 2f263b125..d980d57a1 100644 --- a/app/widget/nodevaluetree/nodevaluetree.cpp +++ b/app/widget/nodevaluetree/nodevaluetree.cpp @@ -31,9 +31,8 @@ void NodeValueTree::SetNode(const NodeInput &input, const rational &time) NodeTraverser traverser; Node *connected_node = input.GetConnectedOutput(); - Node::ValueHint value_hint = input.node()->GetValueHintForInput(input.input(), input.element()); - NodeValueTable table = traverser.GenerateTable(connected_node, value_hint, TimeRange(time, time)); + NodeValueTable table = traverser.GenerateTable(connected_node, TimeRange(time, time)); int index = traverser.GenerateRowValueElementIndex(input.node(), input.input(), input.element(), &table); diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index bc5ab4450..1b15a5b0a 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -45,7 +45,6 @@ #include "node/gizmo/point.h" #include "node/gizmo/polygon.h" #include "node/gizmo/screen.h" -#include "node/traverser.h" #include "viewertexteditor.h" #include "window/mainwindow/mainwindow.h" @@ -221,7 +220,7 @@ QPointF ViewerDisplayWidget::TransformViewerSpaceToBufferSpace(const QPointF &po * Inversion will only fail if the viewer has been scaled by 0 in any direction * which I think should never happen. */ - return pos * GenerateGizmoTransform().inverted(); + return pos * GenerateDisplayTransform().inverted(); } void ViewerDisplayWidget::ResetFPSTimer() @@ -253,7 +252,8 @@ void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) add_band_->show(); } else if (event->button() == Qt::LeftButton && gizmos_ - && (current_gizmo_ = TryGizmoPress(gizmo_db_, TransformViewerSpaceToBufferSpace(event->pos())))) { + && (gizmo_last_draw_transform_inverted_ = gizmo_last_draw_transform_.inverted(), + current_gizmo_ = TryGizmoPress(gizmo_db_, event->pos() * gizmo_last_draw_transform_inverted_))) { // Handle gizmo click gizmo_start_drag_ = event->pos(); @@ -300,7 +300,7 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event) // Signal movement if (DraggableGizmo *draggable = dynamic_cast(current_gizmo_)) { if (!gizmo_drag_started_) { - QPointF start = TransformViewerSpaceToBufferSpace(gizmo_start_drag_); + QPointF start = gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; rational gizmo_time = GetGizmoTime(); NodeTraverser t; @@ -311,17 +311,17 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event) gizmo_drag_started_ = true; } - QPointF v = TransformViewerSpaceToBufferSpace(event->pos()); + QPointF v = event->pos() * gizmo_last_draw_transform_inverted_; switch (draggable->GetDragValueBehavior()) { case DraggableGizmo::kAbsolute: // Above value is correct break; case DraggableGizmo::kDeltaFromPrevious: - v -= TransformViewerSpaceToBufferSpace(gizmo_last_drag_); + v -= gizmo_last_drag_ * gizmo_last_draw_transform_inverted_; gizmo_last_drag_ = event->pos(); break; case DraggableGizmo::kDeltaFromStart: - v -= TransformViewerSpaceToBufferSpace(gizmo_start_drag_); + v -= gizmo_start_drag_ * gizmo_last_draw_transform_inverted_; break; } @@ -349,7 +349,7 @@ void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event) const QRect &band_rect = add_band_->geometry(); if (band_rect.width() > 1 && band_rect.height() > 1) { - QRectF r = GenerateGizmoTransform().inverted().mapRect(add_band_->geometry()); + QRectF r = GenerateDisplayTransform().inverted().mapRect(add_band_->geometry()); emit CreateAddableAt(r); } @@ -510,7 +510,8 @@ void ViewerDisplayWidget::OnPaint() gizmo_db_ = gt.GenerateRow(gizmos_, range); QPainter p(inner_widget()); - p.setWorldTransform(GenerateGizmoTransform()); + gizmo_last_draw_transform_ = GenerateGizmoTransform(gt, range); + p.setWorldTransform(gizmo_last_draw_transform_); gizmos_->UpdateGizmoPositions(gizmo_db_, NodeTraverser::GenerateGlobals(gizmo_params_, range)); foreach (NodeGizmo *gizmo, gizmos_->GetGizmos()) { @@ -722,7 +723,7 @@ QTransform ViewerDisplayWidget::GenerateWorldTransform() return world; } -QTransform ViewerDisplayWidget::GenerateGizmoTransform() +QTransform ViewerDisplayWidget::GenerateDisplayTransform() { QVector2D viewer_scale(GetTexturePosition(size())); QTransform gizmo_transform = GenerateWorldTransform(); @@ -731,13 +732,37 @@ QTransform ViewerDisplayWidget::GenerateGizmoTransform() return gizmo_transform; } +QTransform ViewerDisplayWidget::GenerateGizmoTransform(NodeTraverser >, const TimeRange &range) +{ + QTransform t = GenerateDisplayTransform(); + if (GetTimeTarget()) { + t.translate(gizmo_params_.width()*0.5, gizmo_params_.height()*0.5); + + Node *target = GetTimeTarget(); + if (ViewerOutput *v = dynamic_cast(target)) { + if (Node *n = v->GetConnectedTextureOutput()) { + target = n; + } + } + + QTransform nt; + gt.Transform(&nt, gizmos_, target, range); + + t = nt * t; + + t.translate(-gizmo_params_.width()*0.5, -gizmo_params_.height()*0.5); + } + + return t; +} + NodeGizmo *ViewerDisplayWidget::TryGizmoPress(const NodeValueRow &row, const QPointF &p) { for (auto it=gizmos_->GetGizmos().crbegin(); it!=gizmos_->GetGizmos().crend(); it++) { NodeGizmo *gizmo = *it; if (gizmo->IsVisible()) { if (PointGizmo *point = dynamic_cast(gizmo)) { - if (point->GetClickingRect(GenerateGizmoTransform()).contains(p)) { + if (point->GetClickingRect(GenerateDisplayTransform()).contains(p)) { return point; } } else if (PolygonGizmo *poly = dynamic_cast(gizmo)) { @@ -760,7 +785,7 @@ NodeGizmo *ViewerDisplayWidget::TryGizmoPress(const NodeValueRow &row, const QPo void ViewerDisplayWidget::OpenTextGizmo(TextGizmo *text, QMouseEvent *event) { - QTransform gizmo_transform = GenerateGizmoTransform(); + QTransform gizmo_transform = GenerateDisplayTransform(); ViewerTextEditor *text_edit = new ViewerTextEditor(gizmo_transform.m11(), this); Html::HtmlToDoc(text_edit->document(), text->GetHtml()); @@ -821,7 +846,7 @@ void ViewerDisplayWidget::EmitColorAtCursor(QMouseEvent *e) Color reference, display; if (texture_) { - QPointF pixel_pos = GenerateGizmoTransform().inverted().map(e->pos()); + QPointF pixel_pos = GenerateDisplayTransform().inverted().map(e->pos()); pixel_pos /= texture_->params().divider(); reference = renderer()->GetPixelFromTexture(texture_.get(), pixel_pos); diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index 54320d33f..cc2a4b0e9 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -29,6 +29,7 @@ #include "node/gizmo/text.h" #include "node/node.h" #include "node/output/track/tracklist.h" +#include "node/traverser.h" #include "render/color.h" #include "tool/tool.h" #include "viewerplaybacktimer.h" @@ -262,7 +263,9 @@ private: QTransform GenerateWorldTransform(); - QTransform GenerateGizmoTransform(); + QTransform GenerateDisplayTransform(); + + QTransform GenerateGizmoTransform(NodeTraverser >, const TimeRange &range); TimeRange GenerateGizmoTime() { @@ -326,6 +329,8 @@ private: QPoint gizmo_last_drag_; NodeGizmo *current_gizmo_; bool gizmo_drag_started_; + QTransform gizmo_last_draw_transform_; + QTransform gizmo_last_draw_transform_inverted_; bool show_subtitles_; Sequence *subtitle_tracks_;