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
|
||||
{
|
||||
|
||||
+71
-19
@@ -6,6 +6,12 @@ uniform bool vert_in;
|
||||
uniform bool repeat_edge_pixels_in;
|
||||
uniform vec2 resolution_in;
|
||||
|
||||
// Directional
|
||||
uniform float directional_degrees_in;
|
||||
|
||||
// Radial
|
||||
uniform vec2 radial_center_in;
|
||||
|
||||
uniform int ove_iteration;
|
||||
|
||||
in vec2 ove_texcoord;
|
||||
@@ -17,6 +23,8 @@ out vec4 frag_color;
|
||||
// Methods
|
||||
#define METHOD_BOX_BLUR 0
|
||||
#define METHOD_GAUSSIAN_BLUR 1
|
||||
#define METHOD_DIRECTIONAL_BLUR 2
|
||||
#define METHOD_RADIAL_BLUR 3
|
||||
|
||||
// Mode
|
||||
#define MODE_NONE 0
|
||||
@@ -60,6 +68,19 @@ int determine_mode() {
|
||||
}
|
||||
}
|
||||
|
||||
vec4 add_to_composite(vec4 composite, vec2 pixel_coord, float weight)
|
||||
{
|
||||
if (repeat_edge_pixels_in
|
||||
|| (pixel_coord.x >= 0.0
|
||||
&& pixel_coord.x < 1.0
|
||||
&& pixel_coord.y >= 0.0
|
||||
&& pixel_coord.y < 1.0)) {
|
||||
composite += texture(tex_in, pixel_coord) * weight;
|
||||
}
|
||||
|
||||
return composite;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
int mode = determine_mode();
|
||||
|
||||
@@ -75,7 +96,13 @@ void main(void) {
|
||||
|
||||
float divider, sigma;
|
||||
|
||||
if (method_in == METHOD_BOX_BLUR) {
|
||||
if (method_in == METHOD_DIRECTIONAL_BLUR || method_in == METHOD_RADIAL_BLUR) {
|
||||
// Despite similar math, these are lighter methods perceptually, so we double the radius to
|
||||
// better match box/gaussian
|
||||
real_radius *= 2.0;
|
||||
}
|
||||
|
||||
if (method_in == METHOD_BOX_BLUR || method_in == METHOD_DIRECTIONAL_BLUR) {
|
||||
|
||||
// Calculate the weight of each pixel based on the radius
|
||||
divider = 1.0 / real_radius;
|
||||
@@ -95,28 +122,53 @@ void main(void) {
|
||||
|
||||
}
|
||||
|
||||
for (float i = -real_radius + 0.5; i <= real_radius; i += 2.0) {
|
||||
float weight;
|
||||
if (method_in == METHOD_BOX_BLUR || method_in == METHOD_GAUSSIAN_BLUR) {
|
||||
for (float i = -real_radius + 0.5; i <= real_radius; i += 2.0) {
|
||||
float weight;
|
||||
|
||||
if (method_in == METHOD_BOX_BLUR) {
|
||||
weight = divider;
|
||||
} else if (method_in == METHOD_GAUSSIAN_BLUR) {
|
||||
weight = gaussian2(i, 0.0, sigma) / divider;
|
||||
if (method_in == METHOD_BOX_BLUR) {
|
||||
weight = divider;
|
||||
} else if (method_in == METHOD_GAUSSIAN_BLUR) {
|
||||
weight = gaussian2(i, 0.0, sigma) / divider;
|
||||
}
|
||||
|
||||
vec2 pixel_coord = ove_texcoord;
|
||||
if (mode == MODE_HORIZONTAL) {
|
||||
pixel_coord.x += i / resolution_in.x;
|
||||
} else if (mode == MODE_VERTICAL) {
|
||||
pixel_coord.y += i / resolution_in.y;
|
||||
}
|
||||
|
||||
composite = add_to_composite(composite, pixel_coord, weight);
|
||||
}
|
||||
} else if (method_in == METHOD_DIRECTIONAL_BLUR || method_in == METHOD_RADIAL_BLUR) {
|
||||
float angle;
|
||||
|
||||
if (method_in == METHOD_DIRECTIONAL_BLUR) {
|
||||
// Convert directional degrees to radians
|
||||
angle = (directional_degrees_in*M_PI)/180.0;
|
||||
} else {
|
||||
// Calculate angle from distance of center to current coordinate
|
||||
vec2 distance = (ove_texcoord - 0.5) * (resolution_in) - radial_center_in;
|
||||
angle = atan(distance.y/distance.x);
|
||||
|
||||
float multiplier = length(distance) / resolution_in.y * 2.0;
|
||||
|
||||
real_radius = ceil(radius_in * multiplier);
|
||||
divider = 1.0 / real_radius;
|
||||
}
|
||||
|
||||
vec2 pixel_coord = ove_texcoord;
|
||||
if (mode == MODE_HORIZONTAL) {
|
||||
pixel_coord.x += i / resolution_in.x;
|
||||
} else if (mode == MODE_VERTICAL) {
|
||||
pixel_coord.y += i / resolution_in.y;
|
||||
}
|
||||
// Get angles
|
||||
float sin_angle = sin(angle);
|
||||
float cos_angle = cos(angle);
|
||||
|
||||
if (repeat_edge_pixels_in
|
||||
|| (pixel_coord.x >= 0.0
|
||||
&& pixel_coord.x < 1.0
|
||||
&& pixel_coord.y >= 0.0
|
||||
&& pixel_coord.y < 1.0)) {
|
||||
composite += texture(tex_in, pixel_coord) * weight;
|
||||
for (float i = -real_radius + 0.5; i <= real_radius; i += 2.0) {
|
||||
vec2 pixel_coord = ove_texcoord;
|
||||
|
||||
pixel_coord.y += sin_angle * i / resolution_in.y;
|
||||
pixel_coord.x += cos_angle * i / resolution_in.x;
|
||||
|
||||
composite = add_to_composite(composite, pixel_coord, divider);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,21 +46,22 @@ const int NodeParamViewItemBody::kMaxWidgetColumn = kKeyControlColumn;
|
||||
|
||||
NodeParamViewItem::NodeParamViewItem(Node *node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget *parent) :
|
||||
super(parent),
|
||||
body_(nullptr),
|
||||
node_(node),
|
||||
create_checkboxes_(create_checkboxes),
|
||||
ctx_(nullptr)
|
||||
{
|
||||
node_->Retranslate();
|
||||
|
||||
// Create and add contents widget
|
||||
body_ = new NodeParamViewItemBody(node_, create_checkboxes);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItem::RequestSetTime);
|
||||
connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this, &NodeParamViewItem::ArrayExpandedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::InputCheckedChanged, this, &NodeParamViewItem::InputCheckedChanged);
|
||||
SetBody(body_);
|
||||
RecreateBody();
|
||||
|
||||
connect(node_, &Node::LabelChanged, this, &NodeParamViewItem::Retranslate);
|
||||
|
||||
// FIXME: Implemented to pick up when an input is set to hidden or not - DEFINITELY not a fast
|
||||
// way of doing this, but "fine" for now.
|
||||
connect(node_, &Node::InputFlagsChanged, this, &NodeParamViewItem::RecreateBody);
|
||||
|
||||
setBackgroundRole(QPalette::Window);
|
||||
|
||||
// Connect title bar enabled checkbox
|
||||
@@ -80,6 +81,23 @@ void NodeParamViewItem::Retranslate()
|
||||
body_->Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::RecreateBody()
|
||||
{
|
||||
QWidget *old_body = body_;
|
||||
|
||||
body_ = new NodeParamViewItemBody(node_, create_checkboxes_);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItem::RequestSetTime);
|
||||
connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this, &NodeParamViewItem::ArrayExpandedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::InputCheckedChanged, this, &NodeParamViewItem::InputCheckedChanged);
|
||||
body_->Retranslate();
|
||||
body_->SetTime(time_);
|
||||
body_->SetTimebase(timebase_);
|
||||
SetBody(body_);
|
||||
|
||||
old_body->deleteLater();
|
||||
}
|
||||
|
||||
int NodeParamViewItem::GetElementY(const NodeInput &c) const
|
||||
{
|
||||
if (IsExpanded()) {
|
||||
|
||||
@@ -179,6 +179,8 @@ public:
|
||||
|
||||
void SetTimebase(const rational& timebase)
|
||||
{
|
||||
timebase_ = timebase;
|
||||
|
||||
body_->SetTimebase(timebase);
|
||||
}
|
||||
|
||||
@@ -228,12 +230,18 @@ private:
|
||||
|
||||
Node* node_;
|
||||
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
|
||||
Node *ctx_;
|
||||
|
||||
rational time_;
|
||||
rational timebase_;
|
||||
|
||||
KeyframeView::NodeConnections keyframe_connections_;
|
||||
|
||||
private slots:
|
||||
void RecreateBody();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -529,7 +529,9 @@ void ViewerDisplayWidget::OnPaint()
|
||||
|
||||
gizmos_->UpdateGizmoPositions(gizmo_db_, NodeTraverser::GenerateGlobals(gizmo_params_, range));
|
||||
foreach (NodeGizmo *gizmo, gizmos_->GetGizmos()) {
|
||||
gizmo->Draw(&p);
|
||||
if (gizmo->IsVisible()) {
|
||||
gizmo->Draw(&p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,21 +750,23 @@ NodeGizmo *ViewerDisplayWidget::TryGizmoPress(const NodeValueRow &row, const QPo
|
||||
{
|
||||
for (auto it=gizmos_->GetGizmos().crbegin(); it!=gizmos_->GetGizmos().crend(); it++) {
|
||||
NodeGizmo *gizmo = *it;
|
||||
if (PointGizmo *point = dynamic_cast<PointGizmo*>(gizmo)) {
|
||||
if (point->GetClickingRect(GenerateGizmoTransform()).contains(p)) {
|
||||
return point;
|
||||
if (gizmo->IsVisible()) {
|
||||
if (PointGizmo *point = dynamic_cast<PointGizmo*>(gizmo)) {
|
||||
if (point->GetClickingRect(GenerateGizmoTransform()).contains(p)) {
|
||||
return point;
|
||||
}
|
||||
} else if (PolygonGizmo *poly = dynamic_cast<PolygonGizmo*>(gizmo)) {
|
||||
if (poly->GetPolygon().containsPoint(p, Qt::OddEvenFill)) {
|
||||
return poly;
|
||||
}
|
||||
} else if (PathGizmo *path = dynamic_cast<PathGizmo*>(gizmo)) {
|
||||
if (path->GetPath().contains(p)) {
|
||||
return path;
|
||||
}
|
||||
} else if (ScreenGizmo *screen = dynamic_cast<ScreenGizmo*>(gizmo)) {
|
||||
// NOTE: Perhaps this should limit to the actual visible screen space? We'll see.
|
||||
return screen;
|
||||
}
|
||||
} else if (PolygonGizmo *poly = dynamic_cast<PolygonGizmo*>(gizmo)) {
|
||||
if (poly->GetPolygon().containsPoint(p, Qt::OddEvenFill)) {
|
||||
return poly;
|
||||
}
|
||||
} else if (PathGizmo *path = dynamic_cast<PathGizmo*>(gizmo)) {
|
||||
if (path->GetPath().contains(p)) {
|
||||
return path;
|
||||
}
|
||||
} else if (ScreenGizmo *screen = dynamic_cast<ScreenGizmo*>(gizmo)) {
|
||||
// NOTE: Perhaps this should limit to the actual visible screen space? We'll see.
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user