/*** Olive - Non-Linear Video Editor Copyright (C) 2020 Olive Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #include "cropdistortnode.h" #include "common/lerp.h" namespace olive { CropDistortNode::CropDistortNode() { texture_input_ = new NodeInput(this, QStringLiteral("tex_in"), NodeValue::kTexture); left_input_ = new NodeInput(this, QStringLiteral("left_in"), NodeValue::kFloat, 0.0); left_input_->setProperty("min", 0.0); left_input_->setProperty("max", 1.0); left_input_->setProperty("view", QStringLiteral("percent")); top_input_ = new NodeInput(this, QStringLiteral("top_in"), NodeValue::kFloat, 0.0); top_input_->setProperty("min", 0.0); top_input_->setProperty("max", 1.0); top_input_->setProperty("view", QStringLiteral("percent")); right_input_ = new NodeInput(this, QStringLiteral("right_in"), NodeValue::kFloat, 0.0); right_input_->setProperty("min", 0.0); right_input_->setProperty("max", 1.0); right_input_->setProperty("view", QStringLiteral("percent")); bottom_input_ = new NodeInput(this, QStringLiteral("bottom_in"), NodeValue::kFloat, 0.0); bottom_input_->setProperty("min", 0.0); bottom_input_->setProperty("max", 1.0); bottom_input_->setProperty("view", QStringLiteral("percent")); feather_input_ = new NodeInput(this, QStringLiteral("feather_in"), NodeValue::kFloat, 0.0); feather_input_->setProperty("min", 0.0); } void CropDistortNode::Retranslate() { texture_input_->set_name(tr("Texture")); left_input_->set_name(tr("Left")); top_input_->set_name(tr("Top")); right_input_->set_name(tr("Right")); bottom_input_->set_name(tr("Bottom")); feather_input_->set_name(tr("Feather")); } NodeValueTable CropDistortNode::Value(NodeValueDatabase &value) const { ShaderJob job; job.InsertValue(texture_input_, value); job.InsertValue(left_input_, value); job.InsertValue(top_input_, value); job.InsertValue(right_input_, value); job.InsertValue(bottom_input_, value); job.InsertValue(feather_input_, value); job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this)); job.SetAlphaChannelRequired(true); NodeValueTable table = value.Merge(); if (!job.GetValue(texture_input_).data().isNull()) { if (!qIsNull(job.GetValue(left_input_).data().toDouble()) || !qIsNull(job.GetValue(right_input_).data().toDouble()) || !qIsNull(job.GetValue(top_input_).data().toDouble()) || !qIsNull(job.GetValue(bottom_input_).data().toDouble())) { table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } else { table.Push(NodeValue::kTexture, job.GetValue(texture_input_).data(), this); } } return table; } ShaderCode CropDistortNode::GetShaderCode(const QString &shader_id) const { Q_UNUSED(shader_id) return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/crop.frag"))); } void CropDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) { QVector2D resolution = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); const double handle_radius = GetGizmoHandleRadius(p->transform()); p->setPen(QPen(Qt::white, 0)); double left_pt = resolution.x() * db[left_input_].Get(NodeValue::kFloat).toDouble(); double top_pt = resolution.y() * db[top_input_].Get(NodeValue::kFloat).toDouble(); double right_pt = resolution.x() * (1.0 - db[right_input_].Get(NodeValue::kFloat).toDouble()); double bottom_pt = resolution.y() * (1.0 - db[bottom_input_].Get(NodeValue::kFloat).toDouble()); double center_x_pt = lerp(left_pt, right_pt, 0.5); double center_y_pt = lerp(top_pt, bottom_pt, 0.5); gizmo_whole_rect_ = QRectF(left_pt, top_pt, right_pt - left_pt, bottom_pt - top_pt); p->drawRect(gizmo_whole_rect_); gizmo_resize_handle_[kGizmoScaleTopLeft] = CreateGizmoHandleRect(QPointF(left_pt, top_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleTopCenter] = CreateGizmoHandleRect(QPointF(center_x_pt, top_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleTopRight] = CreateGizmoHandleRect(QPointF(right_pt, top_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleBottomLeft] = CreateGizmoHandleRect(QPointF(left_pt, bottom_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleBottomCenter] = CreateGizmoHandleRect(QPointF(center_x_pt, bottom_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleBottomRight] = CreateGizmoHandleRect(QPointF(right_pt, bottom_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleCenterLeft] = CreateGizmoHandleRect(QPointF(left_pt, center_y_pt), handle_radius); gizmo_resize_handle_[kGizmoScaleCenterRight] = CreateGizmoHandleRect(QPointF(right_pt, center_y_pt), handle_radius); p->setPen(Qt::NoPen); p->setBrush(Qt::white); DrawAndExpandGizmoHandles(p, handle_radius, gizmo_resize_handle_, kGizmoScaleCount); } bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) { bool found_handle = false; bool gizmo_active[kGizmoScaleCount] = {false}; for (int i=0; i kGizmoNone) { gizmo_res_ = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); gizmo_drag_start_ = p; return true; } return false; } void CropDistortNode::GizmoMove(const QPointF &p, const rational &time) { if (gizmo_dragger_.isEmpty()) { gizmo_dragger_.resize(gizmo_start_.size()); int counter = 0; if (gizmo_drag_ & kGizmoLeft) { gizmo_dragger_[counter].Start(left_input_, time, 0); counter++; } if (gizmo_drag_ & kGizmoTop) { gizmo_dragger_[counter].Start(top_input_, time, 0); counter++; } if (gizmo_drag_ & kGizmoRight) { gizmo_dragger_[counter].Start(right_input_, time, 0); counter++; } if (gizmo_drag_ & kGizmoBottom) { gizmo_dragger_[counter].Start(bottom_input_, time, 0); counter++; } } int counter = 0; double x_diff = (p.x() - gizmo_drag_start_.x()) / gizmo_res_.x(); double y_diff = (p.y() - gizmo_drag_start_.y()) / gizmo_res_.y(); if (gizmo_drag_ & kGizmoLeft) { gizmo_dragger_[counter].Drag(gizmo_start_[counter].toDouble() + x_diff); counter++; } if (gizmo_drag_ & kGizmoTop) { gizmo_dragger_[counter].Drag(gizmo_start_[counter].toDouble() + y_diff); counter++; } if (gizmo_drag_ & kGizmoRight) { gizmo_dragger_[counter].Drag(gizmo_start_[counter].toDouble() - x_diff); counter++; } if (gizmo_drag_ & kGizmoBottom) { gizmo_dragger_[counter].Drag(gizmo_start_[counter].toDouble() - y_diff); counter++; } } void CropDistortNode::GizmoRelease() { for (NodeInputDragger& i : gizmo_dragger_) { i.End(); } gizmo_dragger_.clear(); gizmo_start_.clear(); } }