blur: implement radial and directional blur methods
This commit is contained in:
+108
-11
@@ -29,25 +29,50 @@ const QString BlurFilterNode::kHorizInput = QStringLiteral("horiz_in");
|
||||
const QString BlurFilterNode::kVertInput = QStringLiteral("vert_in");
|
||||
const QString BlurFilterNode::kRepeatEdgePixelsInput = QStringLiteral("repeat_edge_pixels_in");
|
||||
|
||||
const QString BlurFilterNode::kDirectionalDegreesInput = QStringLiteral("directional_degrees_in");
|
||||
|
||||
const QString BlurFilterNode::kRadialCenterInput = QStringLiteral("radial_center_in");
|
||||
|
||||
#define super Node
|
||||
|
||||
BlurFilterNode::BlurFilterNode()
|
||||
{
|
||||
AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kMethodInput, NodeValue::kCombo, 1); // Default to gaussian
|
||||
Method default_method = kGaussian;
|
||||
|
||||
AddInput(kMethodInput, NodeValue::kCombo, default_method, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
|
||||
|
||||
AddInput(kRadiusInput, NodeValue::kFloat, 10.0);
|
||||
SetInputProperty(kRadiusInput, QStringLiteral("min"), 0.0);
|
||||
|
||||
AddInput(kHorizInput, NodeValue::kBoolean, true);
|
||||
{
|
||||
// Box and gaussian only
|
||||
AddInput(kHorizInput, NodeValue::kBoolean, true);
|
||||
AddInput(kVertInput, NodeValue::kBoolean, true);
|
||||
}
|
||||
|
||||
AddInput(kVertInput, NodeValue::kBoolean, true);
|
||||
{
|
||||
// Directional only
|
||||
AddInput(kDirectionalDegreesInput, NodeValue::kFloat, 0.0);
|
||||
}
|
||||
|
||||
{
|
||||
// Radial only
|
||||
AddInput(kRadialCenterInput, NodeValue::kVec2, QVector2D(0, 0));
|
||||
}
|
||||
|
||||
UpdateInputs(default_method);
|
||||
|
||||
AddInput(kRepeatEdgePixelsInput, NodeValue::kBoolean, true);
|
||||
|
||||
SetFlags(kVideoEffect);
|
||||
SetEffectInput(kTextureInput);
|
||||
|
||||
radial_center_gizmo_ = AddDraggableGizmo<PointGizmo>();
|
||||
radial_center_gizmo_->SetShape(PointGizmo::kAnchorPoint);
|
||||
radial_center_gizmo_->AddInput(NodeKeyframeTrackReference(NodeInput(this, kRadialCenterInput), 0));
|
||||
radial_center_gizmo_->AddInput(NodeKeyframeTrackReference(NodeInput(this, kRadialCenterInput), 1));
|
||||
}
|
||||
|
||||
QString BlurFilterNode::Name() const
|
||||
@@ -76,11 +101,14 @@ void BlurFilterNode::Retranslate()
|
||||
|
||||
SetInputName(kTextureInput, tr("Input"));
|
||||
SetInputName(kMethodInput, tr("Method"));
|
||||
SetComboBoxStrings(kMethodInput, { tr("Box"), tr("Gaussian") });
|
||||
SetComboBoxStrings(kMethodInput, { tr("Box"), tr("Gaussian"), tr("Directional"), tr("Radial") });
|
||||
SetInputName(kRadiusInput, tr("Radius"));
|
||||
SetInputName(kHorizInput, tr("Horizontal"));
|
||||
SetInputName(kVertInput, tr("Vertical"));
|
||||
SetInputName(kRepeatEdgePixelsInput, tr("Repeat Edge Pixels"));
|
||||
|
||||
SetInputName(kDirectionalDegreesInput, tr("Direction"));
|
||||
SetInputName(kRadialCenterInput, tr("Center"));
|
||||
}
|
||||
|
||||
ShaderCode BlurFilterNode::GetShaderCode(const ShaderRequest &request) const
|
||||
@@ -96,25 +124,47 @@ void BlurFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
|
||||
Method method = static_cast<Method>(job.GetValue(kMethodInput).data().toInt());
|
||||
|
||||
// If there's no texture, no need to run an operation
|
||||
if (!job.GetValue(kTextureInput).data().isNull()) {
|
||||
|
||||
// Check if radius > 0, and both "horiz" and/or "vert" are enabled
|
||||
if ((job.GetValue(kHorizInput).data().toBool() || job.GetValue(kVertInput).data().toBool())
|
||||
&& job.GetValue(kRadiusInput).data().toDouble() > 0.0) {
|
||||
bool can_push_job = true;
|
||||
|
||||
// Set iteration count to 2 if we're blurring both horizontally and vertically
|
||||
if (job.GetValue(kHorizInput).data().toBool() && job.GetValue(kVertInput).data().toBool()) {
|
||||
job.SetIterations(2, kTextureInput);
|
||||
// Check if radius is > 0
|
||||
if (job.GetValue(kRadiusInput).data().toDouble() > 0.0) {
|
||||
// Method-specific considerations
|
||||
switch (method) {
|
||||
case kBox:
|
||||
case kGaussian:
|
||||
{
|
||||
bool horiz = job.GetValue(kHorizInput).data().toBool();
|
||||
bool vert = job.GetValue(kVertInput).data().toBool();
|
||||
|
||||
if (!horiz && !vert) {
|
||||
// Disable job if horiz and vert are unchecked
|
||||
can_push_job = false;
|
||||
} else if (horiz && vert) {
|
||||
// Set iteration count to 2 if we're blurring both horizontally and vertically
|
||||
job.SetIterations(2, kTextureInput);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kDirectional:
|
||||
case kRadial:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
can_push_job = false;
|
||||
}
|
||||
|
||||
if (can_push_job) {
|
||||
// If we're not repeating pixels, expect an alpha channel to appear
|
||||
if (!job.GetValue(kRepeatEdgePixelsInput).data().toBool()) {
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
}
|
||||
|
||||
table->Push(NodeValue::kTexture, QVariant::fromValue(job), this);
|
||||
|
||||
} else {
|
||||
// If we're not performing the blur job, just push the texture
|
||||
table->Push(job.GetValue(kTextureInput));
|
||||
@@ -123,4 +173,51 @@ void BlurFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals
|
||||
}
|
||||
}
|
||||
|
||||
void BlurFilterNode::UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals)
|
||||
{
|
||||
if (row[kMethodInput].data().toInt() == kRadial) {
|
||||
const QVector2D &sequence_res = globals.resolution();
|
||||
QVector2D sequence_half_res = sequence_res * 0.5;
|
||||
|
||||
radial_center_gizmo_->SetVisible(true);
|
||||
radial_center_gizmo_->SetPoint(sequence_half_res.toPointF() + row[kRadialCenterInput].value<QVector2D>().toPointF());
|
||||
|
||||
SetInputProperty(kRadialCenterInput, QStringLiteral("offset"), sequence_half_res);
|
||||
} else{
|
||||
radial_center_gizmo_->SetVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void BlurFilterNode::GizmoDragMove(double x, double y, const Qt::KeyboardModifiers &modifiers)
|
||||
{
|
||||
DraggableGizmo *gizmo = static_cast<DraggableGizmo*>(sender());
|
||||
|
||||
if (gizmo == radial_center_gizmo_) {
|
||||
|
||||
NodeInputDragger &x_drag = gizmo->GetDraggers()[0];
|
||||
NodeInputDragger &y_drag = gizmo->GetDraggers()[1];
|
||||
|
||||
x_drag.Drag(x_drag.GetStartValue().toDouble() + x);
|
||||
y_drag.Drag(y_drag.GetStartValue().toDouble() + y);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BlurFilterNode::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
if (input == kMethodInput) {
|
||||
UpdateInputs(GetMethod());
|
||||
}
|
||||
|
||||
super::InputValueChangedEvent(input, element);
|
||||
}
|
||||
|
||||
void BlurFilterNode::UpdateInputs(Method method)
|
||||
{
|
||||
SetInputFlags(kHorizInput, (method == kBox || method == kGaussian) ? InputFlags() : InputFlags(kInputFlagHidden));
|
||||
SetInputFlags(kVertInput, (method == kBox || method == kGaussian) ? InputFlags() : InputFlags(kInputFlagHidden));
|
||||
SetInputFlags(kDirectionalDegreesInput, (method == kDirectional) ? InputFlags() : InputFlags(kInputFlagHidden));
|
||||
SetInputFlags(kRadialCenterInput, (method == kRadial) ? InputFlags() : InputFlags(kInputFlagHidden));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef BLURFILTERNODE_H
|
||||
#define BLURFILTERNODE_H
|
||||
|
||||
#include "node/gizmo/point.h"
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -31,6 +32,13 @@ class BlurFilterNode : public Node
|
||||
public:
|
||||
BlurFilterNode();
|
||||
|
||||
enum Method {
|
||||
kBox,
|
||||
kGaussian,
|
||||
kDirectional,
|
||||
kRadial
|
||||
};
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(BlurFilterNode)
|
||||
|
||||
virtual QString Name() const override;
|
||||
@@ -43,6 +51,13 @@ public:
|
||||
virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override;
|
||||
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
Method GetMethod() const
|
||||
{
|
||||
return static_cast<Method>(GetStandardValue(kMethodInput).toInt());
|
||||
}
|
||||
|
||||
virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals) override;
|
||||
|
||||
static const QString kTextureInput;
|
||||
static const QString kMethodInput;
|
||||
static const QString kRadiusInput;
|
||||
@@ -50,6 +65,21 @@ public:
|
||||
static const QString kVertInput;
|
||||
static const QString kRepeatEdgePixelsInput;
|
||||
|
||||
static const QString kDirectionalDegreesInput;
|
||||
|
||||
static const QString kRadialCenterInput;
|
||||
|
||||
protected slots:
|
||||
virtual void GizmoDragMove(double x, double y, const Qt::KeyboardModifiers &modifiers) override;
|
||||
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
|
||||
private:
|
||||
void UpdateInputs(Method method);
|
||||
|
||||
PointGizmo *radial_center_gizmo_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeGizmo::NodeGizmo(QObject *parent)
|
||||
NodeGizmo::NodeGizmo(QObject *parent) :
|
||||
visible_(true)
|
||||
{
|
||||
setParent(parent);
|
||||
}
|
||||
|
||||
@@ -39,11 +39,16 @@ public:
|
||||
const NodeGlobals &GetGlobals() const { return globals_; }
|
||||
void SetGlobals(const NodeGlobals &globals) { globals_ = globals; }
|
||||
|
||||
bool IsVisible() const { return visible_; }
|
||||
void SetVisible(bool e) { visible_ = e; }
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
NodeGlobals globals_;
|
||||
|
||||
bool visible_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -917,6 +917,7 @@ void Node::SetInputFlags(const QString &input, const InputFlags &f)
|
||||
|
||||
if (i) {
|
||||
i->flags = f;
|
||||
emit InputFlagsChanged(input, i->flags);
|
||||
} else {
|
||||
ReportInvalidInput("set flags of", input);
|
||||
}
|
||||
|
||||
@@ -1168,6 +1168,8 @@ signals:
|
||||
|
||||
void NodeRemovedFromContext(Node *node);
|
||||
|
||||
void InputFlagsChanged(const QString &input, const InputFlags &flags);
|
||||
|
||||
private:
|
||||
class ArrayInsertCommand : public UndoCommand
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user