diff --git a/effects/effectrow.cpp b/effects/effectrow.cpp index 79972c30a..cf236e68c 100644 --- a/effects/effectrow.cpp +++ b/effects/effectrow.cpp @@ -60,6 +60,11 @@ void EffectRow::AddField(EffectField *field) fields_.append(field); } +void EffectRow::AddNodeInput(olive::nodes::DataType type) +{ + accepted_datatypes_.append(type); +} + bool EffectRow::IsKeyframing() { return keyframing_; } @@ -102,6 +107,11 @@ void EffectRow::SetEnabled(bool enabled) } } +bool EffectRow::CanConnectNodes() +{ + return !accepted_datatypes_.isEmpty(); +} + void EffectRow::SetKeyframingEnabled(bool enabled) { if (enabled == keyframing_) { return; diff --git a/effects/effectrow.h b/effects/effectrow.h index 7bfb4379f..bcd42f117 100644 --- a/effects/effectrow.h +++ b/effects/effectrow.h @@ -211,6 +211,17 @@ public: */ void SetEnabled(bool enabled); + /** + * @brief Check if nodes can be connected to this input. + * + * Connecting is enabled by adding an accepted node input using AddNodeInput(). + * + * @return + * + * TRUE if nodes can be connected. + */ + bool CanConnectNodes(); + protected: /** * @brief Add a field to this row @@ -224,6 +235,18 @@ protected: */ void AddField(EffectField* Field); + /** + * @brief Adds a node data type that can be accepted by this input + * + * Allows this input to take a node connection from a data type specified by type. An input can take several data + * types. + * + * @param type + * + * The data type to add + */ + void AddNodeInput(olive::nodes::DataType type); + public slots: /** * @brief Go to previous keyframe @@ -340,6 +363,11 @@ private: * get freed automatically. */ QVector fields_; + + /** + * @brief Internal array of accepted node data types + */ + QVector accepted_datatypes_; }; #endif // EFFECTROW_H diff --git a/nodes/inputs/boolinput.cpp b/nodes/inputs/boolinput.cpp index 7ae067ed0..9ef9a32ae 100644 --- a/nodes/inputs/boolinput.cpp +++ b/nodes/inputs/boolinput.cpp @@ -6,6 +6,8 @@ BoolInput::BoolInput(Effect* parent, const QString& id, const QString& name, boo BoolField* bool_field = new BoolField(this); connect(bool_field, SIGNAL(Toggled(bool)), this, SIGNAL(Toggled(bool))); AddField(bool_field); + + AddNodeInput(olive::nodes::kBoolean); } bool BoolInput::GetBoolAt(double timecode) diff --git a/nodes/inputs/colorinput.cpp b/nodes/inputs/colorinput.cpp index eab5010f4..c23d3a83d 100644 --- a/nodes/inputs/colorinput.cpp +++ b/nodes/inputs/colorinput.cpp @@ -4,6 +4,8 @@ ColorInput::ColorInput(Effect* parent, const QString& id, const QString& name, b EffectRow(parent, id, name, savable, keyframable) { AddField(new ColorField(this)); + + AddNodeInput(olive::nodes::kColor); } QColor ColorInput::GetColorAt(double timecode) diff --git a/nodes/inputs/comboinput.cpp b/nodes/inputs/comboinput.cpp index aadeeef41..d34ea7d88 100644 --- a/nodes/inputs/comboinput.cpp +++ b/nodes/inputs/comboinput.cpp @@ -6,6 +6,8 @@ ComboInput::ComboInput(Effect* parent, const QString& id, const QString& name, b ComboField* combo_field = new ComboField(this); connect(combo_field, SIGNAL(DataChanged(const QVariant&)), this, SIGNAL(DataChanged(const QVariant&))); AddField(combo_field); + + AddNodeInput(olive::nodes::kCombo); } void ComboInput::AddItem(const QString &text, const QVariant &data) diff --git a/nodes/inputs/fileinput.cpp b/nodes/inputs/fileinput.cpp index 011506747..65d872ef7 100644 --- a/nodes/inputs/fileinput.cpp +++ b/nodes/inputs/fileinput.cpp @@ -4,6 +4,8 @@ FileInput::FileInput(Effect* parent, const QString& id, const QString& name, boo EffectRow(parent, id, name, savable, keyframable) { AddField(new FileField(this)); + + AddNodeInput(olive::nodes::kFile); } QString FileInput::GetFileAt(double timecode) diff --git a/nodes/inputs/fontinput.cpp b/nodes/inputs/fontinput.cpp index 3e0041136..506a402d9 100644 --- a/nodes/inputs/fontinput.cpp +++ b/nodes/inputs/fontinput.cpp @@ -4,6 +4,8 @@ FontInput::FontInput(Effect* parent, const QString& id, const QString& name, boo EffectRow(parent, id, name, savable, keyframable) { AddField(new FontField(this)); + + AddNodeInput(olive::nodes::kFont); } QString FontInput::GetFontAt(double timecode) diff --git a/nodes/inputs/stringinput.cpp b/nodes/inputs/stringinput.cpp index 0169c3826..ea840992c 100644 --- a/nodes/inputs/stringinput.cpp +++ b/nodes/inputs/stringinput.cpp @@ -4,6 +4,8 @@ StringInput::StringInput(Effect* parent, const QString& id, const QString& name, EffectRow(parent, id, name, savable, keyframable) { AddField(new StringField(this, rich_text)); + + AddNodeInput(olive::nodes::kString); } QString StringInput::GetStringAt(double timecode) diff --git a/nodes/inputs/vecinput.cpp b/nodes/inputs/vecinput.cpp index 82e74ea60..907da26cf 100644 --- a/nodes/inputs/vecinput.cpp +++ b/nodes/inputs/vecinput.cpp @@ -14,6 +14,17 @@ VecInput::VecInput(Effect* parent, const QString& id, const QString& name, int v for (int i=0;i 1) { + AddNodeInput(olive::nodes::kVec2); + } + if (values > 2) { + AddNodeInput(olive::nodes::kVec3); + } + if (values > 3) { + AddNodeInput(olive::nodes::kVec4); + } } void VecInput::SetMinimum(double minimum) diff --git a/nodes/nodegraph.h b/nodes/nodegraph.h index 9bf6cafe2..e060dacee 100644 --- a/nodes/nodegraph.h +++ b/nodes/nodegraph.h @@ -9,7 +9,6 @@ public: NodeGraph(); private: - Effect* end_node_; }; #endif // NODEGRAPH_H diff --git a/ui/effectui.cpp b/ui/effectui.cpp index 5e31dd025..2a9e72467 100644 --- a/ui/effectui.cpp +++ b/ui/effectui.cpp @@ -202,11 +202,19 @@ int EffectUI::GetRowY(int row, QWidget* mapToWidget) { QLabel* row_label = labels_.at(row); + int mapped_coord; + if (mapToWidget == nullptr) { + mapped_coord = contents->pos().y(); + } else { + // FIXME Problematic now that EffectUIs are used outside of EffectControls + mapped_coord = mapToWidget->mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y(); + mapped_coord -= title_bar->height(); + } + // Get center point of label (label->rect()->center()->y() - instead of y()+height/2 - produces an inaccurate result) return row_label->y() + row_label->height() / 2 - + mapToWidget->mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - - title_bar->height(); + + mapped_coord; } void EffectUI::UpdateFromEffect() diff --git a/ui/effectui.h b/ui/effectui.h index 86627e96e..2888c04aa 100644 --- a/ui/effectui.h +++ b/ui/effectui.h @@ -95,7 +95,7 @@ public: * * The row's Y position. */ - int GetRowY(int row, QWidget *mapToWidget); + int GetRowY(int row, QWidget *mapToWidget = nullptr); /** * @brief Update widgets with the current Effect's values. diff --git a/ui/nodeui.cpp b/ui/nodeui.cpp index 718365c46..49eeecb25 100644 --- a/ui/nodeui.cpp +++ b/ui/nodeui.cpp @@ -10,7 +10,10 @@ #include #include +#include "ui/effectui.h" + const int kRoundedRectRadius = 5; +const int kNodePlugSize = 6; NodeUI::NodeUI() : central_widget_(nullptr) @@ -33,24 +36,29 @@ void NodeUI::AddToScene(QGraphicsScene *scene) if (central_widget_ != nullptr) { proxy_ = scene->addWidget(central_widget_); - proxy_->setPos(pos() + QPoint(kRoundedRectRadius, kRoundedRectRadius)); + proxy_->setPos(pos() + QPoint(1 + kRoundedRectRadius, 1 + kRoundedRectRadius)); proxy_->setParentItem(this); } } void NodeUI::Resize(const QSize &s) { - QRectF rectangle = rect(); - + QRectF rectangle; + rectangle.setTopLeft(pos()); rectangle.setSize(s + 2 * QSize(kRoundedRectRadius, kRoundedRectRadius)); + QRectF inner_rect = rectangle; + inner_rect.translate(kNodePlugSize / 2, 0); + + rectangle.setWidth(rectangle.width() + kNodePlugSize); + path_ = QPainterPath(); - path_.addRoundedRect(rectangle, kRoundedRectRadius, kRoundedRectRadius); + path_.addRoundedRect(inner_rect, kRoundedRectRadius, kRoundedRectRadius); setRect(rectangle); } -void NodeUI::SetWidget(QWidget *widget) +void NodeUI::SetWidget(EffectUI *widget) { central_widget_ = widget; } @@ -59,6 +67,20 @@ void NodeUI::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QW { Q_UNUSED(widget) + if (proxy_ != nullptr) { + Effect* e = central_widget_->GetEffect(); + + for (int i=0;irow_count();i++) { + if (e->row(i)->CanConnectNodes()) { + int y = central_widget_->GetRowY(i); + + painter->setPen(Qt::black); + painter->setBrush(Qt::gray); + painter->drawEllipse(QPointF(rect().x() + kNodePlugSize / 2, proxy_->pos().y() + y), kNodePlugSize, kNodePlugSize); + } + } + } + QPalette palette = qApp->palette(); if (option->state & QStyle::State_Selected) { diff --git a/ui/nodeui.h b/ui/nodeui.h index 1bde2f392..98cbe8e88 100644 --- a/ui/nodeui.h +++ b/ui/nodeui.h @@ -4,6 +4,8 @@ #include #include +class EffectUI; + class NodeUI : public QGraphicsRectItem { public: NodeUI(); @@ -11,11 +13,11 @@ public: void AddToScene(QGraphicsScene* scene); void Resize(const QSize& s); - void SetWidget(QWidget* widget); + void SetWidget(EffectUI* widget); protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; private: - QWidget* central_widget_; + EffectUI* central_widget_; QGraphicsProxyWidget* proxy_; QPainterPath path_; };