various node UI improvements
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
#include "solid.h"
|
||||
|
||||
SolidGenerator::SolidGenerator(QObject *parent) :
|
||||
Node(parent),
|
||||
SolidGenerator::SolidGenerator() :
|
||||
texture_(nullptr)
|
||||
{
|
||||
texture_output_ = new NodeOutput(this);
|
||||
color_input_ = new NodeInput();
|
||||
color_input_->add_data_input(NodeParam::kColor);
|
||||
AddParameter(color_input_);
|
||||
|
||||
texture_output_ = new NodeOutput();
|
||||
texture_output_->set_data_type(NodeOutput::kTexture);
|
||||
AddParameter(texture_output_);
|
||||
}
|
||||
|
||||
QString SolidGenerator::Name()
|
||||
|
||||
@@ -9,7 +9,7 @@ class SolidGenerator : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SolidGenerator(QObject* parent = nullptr);
|
||||
SolidGenerator();
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
@@ -21,6 +21,8 @@ public slots:
|
||||
virtual void Process(const rational &time) override;
|
||||
|
||||
private:
|
||||
NodeInput* color_input_;
|
||||
|
||||
NodeOutput* texture_output_;
|
||||
|
||||
QOpenGLTexture* texture_;
|
||||
|
||||
@@ -27,6 +27,14 @@ NodeGraph::NodeGraph()
|
||||
|
||||
}
|
||||
|
||||
void NodeGraph::AddNode(Node *node)
|
||||
{
|
||||
node->setParent(this);
|
||||
|
||||
connect(node, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr)));
|
||||
connect(node, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr)));
|
||||
}
|
||||
|
||||
const QString &NodeGraph::name()
|
||||
{
|
||||
return name_;
|
||||
|
||||
@@ -27,14 +27,21 @@
|
||||
|
||||
class NodeGraph : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeGraph();
|
||||
|
||||
void AddNode(Node* node);
|
||||
|
||||
const QString& name();
|
||||
void set_name(const QString& name);
|
||||
|
||||
QList<Node*> nodes();
|
||||
|
||||
signals:
|
||||
void EdgeAdded(NodeEdgePtr edge);
|
||||
void EdgeRemoved(NodeEdgePtr edge);
|
||||
|
||||
private:
|
||||
QString name_;
|
||||
};
|
||||
|
||||
+6
-2
@@ -22,8 +22,7 @@
|
||||
|
||||
#include "output.h"
|
||||
|
||||
NodeInput::NodeInput(Node* parent) :
|
||||
NodeParam(parent),
|
||||
NodeInput::NodeInput() :
|
||||
can_accept_multiple_inputs_(false)
|
||||
{
|
||||
// Have at least one keyframe/value active at any time
|
||||
@@ -97,3 +96,8 @@ void NodeInput::set_keyframing(bool k)
|
||||
{
|
||||
keyframing_ = k;
|
||||
}
|
||||
|
||||
const QList<NodeParam::DataType> &NodeInput::inputs()
|
||||
{
|
||||
return inputs_;
|
||||
}
|
||||
|
||||
+3
-1
@@ -27,7 +27,7 @@
|
||||
class NodeInput : public NodeParam
|
||||
{
|
||||
public:
|
||||
NodeInput(Node *parent);
|
||||
NodeInput();
|
||||
|
||||
virtual Type type() override;
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
bool keyframing();
|
||||
void set_keyframing(bool k);
|
||||
|
||||
const QList<DataType>& inputs();
|
||||
|
||||
private:
|
||||
QList<DataType> inputs_;
|
||||
|
||||
|
||||
+9
-2
@@ -22,8 +22,7 @@
|
||||
|
||||
#include "common/qobjectlistcast.h"
|
||||
|
||||
Node::Node(QObject *parent) :
|
||||
QObject(parent)
|
||||
Node::Node()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -39,6 +38,14 @@ QString Node::Description()
|
||||
return QString();
|
||||
}
|
||||
|
||||
void Node::AddParameter(NodeParam *param)
|
||||
{
|
||||
param->setParent(this);
|
||||
|
||||
connect(param, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr)));
|
||||
connect(param, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr)));
|
||||
}
|
||||
|
||||
void Node::InvalidateCache(const rational &start_range, const rational &end_range)
|
||||
{
|
||||
QList<NodeParam *> params = parameters();
|
||||
|
||||
+7
-1
@@ -31,12 +31,14 @@ class Node : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Node(QObject* parent = nullptr);
|
||||
Node();
|
||||
|
||||
virtual QString Name() = 0;
|
||||
virtual QString Category();
|
||||
virtual QString Description();
|
||||
|
||||
void AddParameter(NodeParam* param);
|
||||
|
||||
/**
|
||||
* @brief Signal all dependent Nodes that anything cached between start_range and end_range is now invalid and
|
||||
* requires re-rendering
|
||||
@@ -71,6 +73,10 @@ public:
|
||||
|
||||
public slots:
|
||||
virtual void Process(const rational& time) = 0;
|
||||
|
||||
signals:
|
||||
void EdgeAdded(NodeEdgePtr edge);
|
||||
void EdgeRemoved(NodeEdgePtr edge);
|
||||
};
|
||||
|
||||
#endif // NODE_H
|
||||
|
||||
+1
-2
@@ -22,8 +22,7 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
NodeOutput::NodeOutput(Node *parent) :
|
||||
NodeParam(parent)
|
||||
NodeOutput::NodeOutput()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
class NodeOutput : public NodeParam
|
||||
{
|
||||
public:
|
||||
NodeOutput(Node* parent);
|
||||
NodeOutput();
|
||||
|
||||
virtual Type type() override;
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
#include "panel/panelfocusmanager.h"
|
||||
|
||||
ViewerOutput::ViewerOutput(QObject* parent) :
|
||||
Node(parent),
|
||||
ViewerOutput::ViewerOutput() :
|
||||
attached_viewer_(nullptr)
|
||||
{
|
||||
texture_input_ = new NodeInput(this);
|
||||
texture_input_ = new NodeInput();
|
||||
texture_input_->add_data_input(NodeInput::kTexture);
|
||||
AddParameter(texture_input_);
|
||||
}
|
||||
|
||||
QString ViewerOutput::Name()
|
||||
|
||||
@@ -8,7 +8,7 @@ class ViewerOutput : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerOutput(QObject* parent = nullptr);
|
||||
ViewerOutput();
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
|
||||
+37
-2
@@ -20,12 +20,13 @@
|
||||
|
||||
#include "param.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "node/input.h"
|
||||
#include "node/output.h"
|
||||
|
||||
NodeParam::NodeParam(Node *parent) :
|
||||
QObject(parent)
|
||||
NodeParam::NodeParam()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,6 +55,28 @@ const QVector<NodeEdgePtr> &NodeParam::edges()
|
||||
return edges_;
|
||||
}
|
||||
|
||||
bool NodeParam::AreDataTypesCompatible(NodeParam *a, NodeParam *b)
|
||||
{
|
||||
// Make sure one is an input and one is an output
|
||||
if (a->type() == b->type()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NodeInput* input;
|
||||
NodeOutput* output;
|
||||
|
||||
// Work out which parameter is which
|
||||
if (a->type() == NodeParam::kInput) {
|
||||
input = static_cast<NodeInput*>(a);
|
||||
output = static_cast<NodeOutput*>(b);
|
||||
} else {
|
||||
input = static_cast<NodeInput*>(b);
|
||||
output = static_cast<NodeOutput*>(a);
|
||||
}
|
||||
|
||||
return AreDataTypesCompatible(output->data_type(), input->inputs());
|
||||
}
|
||||
|
||||
bool NodeParam::AreDataTypesCompatible(const NodeParam::DataType &output_type, const NodeParam::DataType &input_type)
|
||||
{
|
||||
if (input_type == output_type) {
|
||||
@@ -94,11 +117,21 @@ NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input)
|
||||
DisconnectEdge(input->edges_.first());
|
||||
}
|
||||
|
||||
// Make sure it's not a duplicate of an edge that already exists
|
||||
foreach (NodeEdgePtr existing, input->edges()) {
|
||||
if (existing->output() == output) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NodeEdgePtr edge = std::make_shared<NodeEdge>(output, input);
|
||||
|
||||
output->edges_.append(edge);
|
||||
input->edges_.append(edge);
|
||||
|
||||
// Emit a signal than an edge was added (only one signal needs emitting)
|
||||
emit output->EdgeAdded(edge);
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
@@ -109,6 +142,8 @@ void NodeParam::DisconnectEdge(NodeEdgePtr edge)
|
||||
|
||||
output->edges_.removeAll(edge);
|
||||
input->edges_.removeAll(edge);
|
||||
|
||||
emit output->EdgeRemoved(edge);
|
||||
}
|
||||
|
||||
QString NodeParam::GetDefaultDataTypeName(const DataType& type)
|
||||
|
||||
+7
-1
@@ -31,6 +31,7 @@ class Node;
|
||||
|
||||
class NodeParam : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Type {
|
||||
kInput,
|
||||
@@ -52,7 +53,7 @@ public:
|
||||
kAny
|
||||
};
|
||||
|
||||
NodeParam(Node* parent);
|
||||
NodeParam();
|
||||
|
||||
virtual Type type() = 0;
|
||||
|
||||
@@ -65,6 +66,7 @@ public:
|
||||
|
||||
const QVector<NodeEdgePtr>& edges();
|
||||
|
||||
static bool AreDataTypesCompatible(NodeParam* a, NodeParam* b);
|
||||
static bool AreDataTypesCompatible(const DataType& output_type, const DataType& input_type);
|
||||
static bool AreDataTypesCompatible(const DataType& output_type, const QList<DataType>& input_types);
|
||||
|
||||
@@ -73,6 +75,10 @@ public:
|
||||
|
||||
static QString GetDefaultDataTypeName(const DataType &type);
|
||||
|
||||
signals:
|
||||
void EdgeAdded(NodeEdgePtr edge);
|
||||
void EdgeRemoved(NodeEdgePtr edge);
|
||||
|
||||
protected:
|
||||
QVector<NodeEdgePtr> edges_;
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
RendererProcessor::RendererProcessor(QObject *parent) :
|
||||
Node(parent),
|
||||
RendererProcessor::RendererProcessor() :
|
||||
started_(false)
|
||||
{
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
* Constructing a Renderer object will not start any threads/backend on its own. Use Start() to do this and Stop()
|
||||
* when the Renderer is about to be destroyed.
|
||||
*/
|
||||
RendererProcessor(QObject* parent = nullptr);
|
||||
RendererProcessor();
|
||||
|
||||
virtual QString Name() override;
|
||||
virtual QString Category() override;
|
||||
|
||||
@@ -18,9 +18,11 @@ set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/nodeview/nodeview.h
|
||||
widget/nodeview/nodeview.cpp
|
||||
widget/nodeview/nodeviewitem.h
|
||||
widget/nodeview/nodeviewitem.cpp
|
||||
widget/nodeview/nodeviewedge.h
|
||||
widget/nodeview/nodeviewedge.cpp
|
||||
widget/nodeview/nodeviewitem.h
|
||||
widget/nodeview/nodeviewitem.cpp
|
||||
widget/nodeview/nodeviewitemwidgetproxy.h
|
||||
widget/nodeview/nodeviewitemwidgetproxy.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
@@ -33,6 +33,11 @@ NodeView::NodeView(QWidget *parent) :
|
||||
|
||||
void NodeView::SetGraph(NodeGraph *graph)
|
||||
{
|
||||
if (graph_ != nullptr) {
|
||||
disconnect(graph_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(AddEdge(NodeEdgePtr)));
|
||||
disconnect(graph_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(RemoveEdge(NodeEdgePtr)));
|
||||
}
|
||||
|
||||
// Clear the scene of all UI objects
|
||||
scene_.clear();
|
||||
|
||||
@@ -41,6 +46,9 @@ void NodeView::SetGraph(NodeGraph *graph)
|
||||
|
||||
// If the graph is valid, add UI objects for each of its Nodes
|
||||
if (graph_ != nullptr) {
|
||||
connect(graph_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(AddEdge(NodeEdgePtr)));
|
||||
connect(graph_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(RemoveEdge(NodeEdgePtr)));
|
||||
|
||||
QList<Node*> graph_nodes = graph_->nodes();
|
||||
|
||||
foreach (Node* node, graph_nodes) {
|
||||
@@ -61,11 +69,7 @@ void NodeView::SetGraph(NodeGraph *graph)
|
||||
const QVector<NodeEdgePtr>& edges = param->edges();
|
||||
|
||||
foreach(NodeEdgePtr edge, edges) {
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge();
|
||||
|
||||
edge_ui->SetEdge(edge);
|
||||
|
||||
scene_.addItem(edge_ui);
|
||||
AddEdge(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,6 +111,22 @@ NodeViewEdge *NodeView::EdgeToUIObject(QGraphicsScene *scene, NodeEdgePtr n)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeView::AddEdge(NodeEdgePtr edge)
|
||||
{
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge();
|
||||
|
||||
edge_ui->SetEdge(edge);
|
||||
|
||||
scene_.addItem(edge_ui);
|
||||
}
|
||||
|
||||
void NodeView::RemoveEdge(NodeEdgePtr edge)
|
||||
{
|
||||
NodeViewEdge* edge_ui = EdgeToUIObject(scene(), edge);
|
||||
|
||||
scene_.removeItem(edge_ui);
|
||||
}
|
||||
|
||||
void NodeView::ItemsChanged()
|
||||
{
|
||||
QList<QGraphicsItem*> items = scene_.items();
|
||||
|
||||
@@ -44,6 +44,10 @@ private:
|
||||
QGraphicsScene scene_;
|
||||
|
||||
private slots:
|
||||
void AddEdge(NodeEdgePtr edge);
|
||||
|
||||
void RemoveEdge(NodeEdgePtr edge);
|
||||
|
||||
void ItemsChanged();
|
||||
|
||||
};
|
||||
|
||||
@@ -27,23 +27,20 @@
|
||||
#include "common/lerp.h"
|
||||
#include "nodeview.h"
|
||||
|
||||
const int kNodeEdgeWidth = 2;
|
||||
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
|
||||
QGraphicsLineItem(parent),
|
||||
edge_(nullptr),
|
||||
moving_(false),
|
||||
connected_(false)
|
||||
{
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
|
||||
setAcceptHoverEvents(true);
|
||||
// Use font metrics to set edge width for basic high DPI support
|
||||
edge_width_ = QFontMetrics(QFont()).height() / 12;
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetEdge(NodeEdgePtr edge)
|
||||
{
|
||||
SetMoving(false);
|
||||
SetConnected(true);
|
||||
|
||||
// Set the new edge pointer
|
||||
@@ -78,7 +75,7 @@ qreal CalculateEdgeYPoint(NodeViewItem *item, int param_index, NodeViewItem *opp
|
||||
|
||||
void NodeViewEdge::Adjust()
|
||||
{
|
||||
if (edge_ == nullptr || scene() == nullptr || moving_) {
|
||||
if (edge_ == nullptr || scene() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,11 +98,6 @@ void NodeViewEdge::Adjust()
|
||||
));
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetMoving(bool m)
|
||||
{
|
||||
moving_ = m;
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetConnected(bool c)
|
||||
{
|
||||
connected_ = c;
|
||||
@@ -121,7 +113,7 @@ void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
color_mode = QPalette::Disabled;
|
||||
}
|
||||
|
||||
setPen(QPen(widget->palette().color(color_mode, QPalette::Text), kNodeEdgeWidth));
|
||||
setPen(QPen(widget->palette().color(color_mode, QPalette::Text), edge_width_));
|
||||
|
||||
QGraphicsLineItem::paint(painter, option, widget);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
|
||||
void Adjust();
|
||||
|
||||
void SetMoving(bool m);
|
||||
void SetConnected(bool c);
|
||||
|
||||
protected:
|
||||
@@ -44,7 +43,8 @@ protected:
|
||||
private:
|
||||
NodeEdgePtr edge_;
|
||||
|
||||
bool moving_;
|
||||
int edge_width_;
|
||||
|
||||
bool connected_;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,11 +31,6 @@
|
||||
#include "ui/icons/icons.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
|
||||
const int kNodeViewItemBorderWidth = 2;
|
||||
const int kNodeViewItemWidth = 200;
|
||||
const int kNodeViewItemTextPadding = 4;
|
||||
const int kNodeViewItemIconPadding = 12;
|
||||
|
||||
NodeViewItem::NodeViewItem(QGraphicsItem *parent) :
|
||||
QGraphicsRectItem(parent),
|
||||
node_(nullptr),
|
||||
@@ -48,13 +43,31 @@ NodeViewItem::NodeViewItem(QGraphicsItem *parent) :
|
||||
setFlag(QGraphicsItem::ItemIsMovable);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
|
||||
// Use the current default font height to size this widget
|
||||
// Set default "collapsed" size
|
||||
title_bar_rect_ = QRectF(0, 0, kNodeViewItemWidth, font_metrics.height() + kNodeViewItemTextPadding * 2);
|
||||
setRect(title_bar_rect_);
|
||||
//
|
||||
// We use font metrics to set all the UI measurements for DPI-awareness
|
||||
//
|
||||
|
||||
// Not particularly great way of using text scaling to set the width (DPI-awareness, etc.)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
int widget_width = font_metrics.width("HHHHHHHHHHHHHHHH");
|
||||
#else
|
||||
int widget_width = font_metrics.horizontalAdvance("HHHHHHHHHHHHHHHH");
|
||||
#endif
|
||||
|
||||
// Set border width
|
||||
node_border_width_ = font_metrics.height() / 12;
|
||||
|
||||
// Set default node connector size
|
||||
node_connector_size_ = font_metrics.height() / 3;
|
||||
|
||||
// Set text and icon padding
|
||||
node_text_padding_ = font_metrics.height() / 6;
|
||||
node_icon_padding_ = node_text_padding_ * 3;
|
||||
|
||||
// Use the current default font height to size this widget
|
||||
// Set default "collapsed" size
|
||||
title_bar_rect_ = QRectF(0, 0, widget_width, font_metrics.height() + node_text_padding_ * 2);
|
||||
setRect(title_bar_rect_);
|
||||
}
|
||||
|
||||
void NodeViewItem::SetNode(Node *n)
|
||||
@@ -85,7 +98,7 @@ void NodeViewItem::SetExpanded(bool e)
|
||||
|
||||
// If a node is connected, use its parameter count to set the height
|
||||
if (node_ != nullptr) {
|
||||
full_size_rect.adjust(0, 0, 0, kNodeViewItemTextPadding*2 + font_metrics.height() * node_->ParameterCount());
|
||||
full_size_rect.adjust(0, 0, 0, node_text_padding_*2 + font_metrics.height() * node_->ParameterCount());
|
||||
}
|
||||
|
||||
// Store content_rect (the rect without the titlebar)
|
||||
@@ -110,10 +123,14 @@ QRectF NodeViewItem::GetParameterConnectorRect(int index)
|
||||
NodeParam* param = node_->ParamAt(index);
|
||||
|
||||
QRectF connector_rect(rect().x(),
|
||||
content_rect_.y() + kNodeViewItemTextPadding + font_metrics.height() / 2 - node_connector_size_ / 2,
|
||||
content_rect_.y() + node_text_padding_ + font_metrics.height() / 2 - node_connector_size_ / 2,
|
||||
node_connector_size_,
|
||||
node_connector_size_);
|
||||
|
||||
if (index > 0) {
|
||||
connector_rect.translate(0, font_metrics.height() * index);
|
||||
}
|
||||
|
||||
// FIXME: I don't know how this will work with NodeParam::kBidirectional
|
||||
if (param->type() == NodeParam::kOutput) {
|
||||
connector_rect.translate(rect().width() - node_connector_size_, 0);
|
||||
@@ -132,11 +149,11 @@ QPointF NodeViewItem::GetParameterTextPoint(int index)
|
||||
|
||||
// FIXME: I don't know how this will work with NodeParam::kBidirectional
|
||||
if (param->type() == NodeParam::kOutput) {
|
||||
return content_rect_.topRight() + QPointF(-(node_connector_size_ + kNodeViewItemTextPadding),
|
||||
kNodeViewItemTextPadding + font_metrics.ascent() + font_metrics.height()*index);
|
||||
return content_rect_.topRight() + QPointF(-(node_connector_size_ + node_text_padding_),
|
||||
node_text_padding_ + font_metrics.ascent() + font_metrics.height()*index);
|
||||
} else {
|
||||
return content_rect_.topLeft() + QPointF(node_connector_size_ + kNodeViewItemTextPadding,
|
||||
kNodeViewItemTextPadding + font_metrics.ascent() + font_metrics.height()*index);
|
||||
return content_rect_.topLeft() + QPointF(node_connector_size_ + node_text_padding_,
|
||||
node_text_padding_ + font_metrics.ascent() + font_metrics.height()*index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +164,7 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
QPalette app_pal = olive::core.main_window()->palette();
|
||||
|
||||
// Set up border, which will change color if selected
|
||||
QPen border_pen(obj_proxy_.BorderColor(), kNodeViewItemBorderWidth);
|
||||
QPen border_pen(css_proxy_.BorderColor(), node_border_width_);
|
||||
|
||||
QPen text_pen(app_pal.color(QPalette::Text));
|
||||
|
||||
@@ -157,7 +174,7 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
|
||||
if (expanded_ && node_ != nullptr) {
|
||||
|
||||
|
||||
// Use main widget color for node contents
|
||||
painter->setBrush(app_pal.window());
|
||||
|
||||
// Draw background rect
|
||||
@@ -197,7 +214,7 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
}
|
||||
|
||||
// Draw rect
|
||||
painter->setBrush(obj_proxy_.TitleBarColor());
|
||||
painter->setBrush(css_proxy_.TitleBarColor());
|
||||
painter->drawRect(title_bar_rect_);
|
||||
|
||||
// If selected, draw selection outline
|
||||
@@ -216,10 +233,10 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
painter->setPen(text_pen);
|
||||
|
||||
// Draw the expand icon
|
||||
expand_hitbox_ = title_bar_rect_.adjusted(kNodeViewItemIconPadding,
|
||||
kNodeViewItemIconPadding,
|
||||
-kNodeViewItemIconPadding,
|
||||
-kNodeViewItemIconPadding);
|
||||
expand_hitbox_ = title_bar_rect_.adjusted(node_icon_padding_,
|
||||
node_icon_padding_,
|
||||
-node_icon_padding_,
|
||||
-node_icon_padding_);
|
||||
|
||||
// Make the icon rect a square
|
||||
expand_hitbox_.setWidth(expand_hitbox_.height());
|
||||
@@ -232,10 +249,10 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
}
|
||||
|
||||
// Draw the text in a rect (the rect is sized around text already in the constructor)
|
||||
QRectF text_rect = title_bar_rect_.adjusted(kNodeViewItemIconPadding + expand_hitbox_.width() + kNodeViewItemTextPadding,
|
||||
kNodeViewItemTextPadding,
|
||||
-kNodeViewItemTextPadding,
|
||||
-kNodeViewItemTextPadding);
|
||||
QRectF text_rect = title_bar_rect_.adjusted(node_icon_padding_ + expand_hitbox_.width() + node_text_padding_,
|
||||
node_text_padding_,
|
||||
-node_text_padding_,
|
||||
-node_text_padding_);
|
||||
painter->drawText(text_rect, Qt::AlignVCenter | Qt::AlignLeft, node_->Name());
|
||||
}
|
||||
}
|
||||
@@ -261,42 +278,43 @@ void NodeViewItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
NodeParam* param = node_->ParamAt(i);
|
||||
|
||||
// Create draggable object
|
||||
dragging_edge_ = new NodeViewEdge();
|
||||
|
||||
if (param->type() == NodeParam::kOutput || param->edges().isEmpty()) {
|
||||
// For an output param (or an input param with no connections), we default to creating a new edge
|
||||
|
||||
// Create new NodeViewEdge object for the user to create an edge
|
||||
dragging_edge_ = new NodeViewEdge();
|
||||
dragging_edge_->SetMoving(true);
|
||||
|
||||
drag_source_ = this;
|
||||
drag_src_param_ = param;
|
||||
|
||||
// Set the starting position to the current param's connector
|
||||
dragging_edge_start_ = pos() + GetParameterConnectorRect(i).center();
|
||||
dragging_edge_->setLine(QLineF(dragging_edge_start_, dragging_edge_start_));
|
||||
|
||||
// Add it to the scene
|
||||
scene()->addItem(dragging_edge_);
|
||||
dragging_edge_start_ = mapToScene(GetParameterConnectorRect(i).center());
|
||||
|
||||
} else if (param->type() == NodeParam::kInput) {
|
||||
// For an input param, we default to moving an existing edge
|
||||
// (here we use the last one, which will usually also be the first)
|
||||
NodeEdgePtr edge = param->edges().last();
|
||||
|
||||
dragging_edge_ = NodeView::EdgeToUIObject(scene(), edge);
|
||||
dragging_edge_->SetMoving(true);
|
||||
// Remove old edge
|
||||
NodeParam::DisconnectEdge(edge);
|
||||
|
||||
// The starting position will be the OPPOSING param's rect
|
||||
NodeOutput* opposing_param = edge->output();
|
||||
Node* opposing_node = opposing_param->parent();
|
||||
NodeViewItem* opposing_node_view_item = NodeView::NodeToUIObject(scene(), opposing_node);
|
||||
dragging_edge_start_ = opposing_node_view_item->pos() + opposing_node_view_item->GetParameterConnectorRect(opposing_param->index()).center();
|
||||
// The starting position will be the OPPOSING parameter's rectangle
|
||||
|
||||
drag_source_ = opposing_node_view_item;
|
||||
drag_src_param_ = opposing_param;
|
||||
// Get the opposing parameter
|
||||
drag_src_param_ = edge->output();
|
||||
|
||||
// Get its Node UI object
|
||||
drag_source_ = NodeView::NodeToUIObject(scene(), drag_src_param_->parent());
|
||||
|
||||
// Get the opposing parameter's rect center
|
||||
dragging_edge_start_ = drag_source_->mapToScene(drag_source_->GetParameterConnectorRect(drag_src_param_->index()).center());
|
||||
}
|
||||
|
||||
// Add it to the scene
|
||||
scene()->addItem(dragging_edge_);
|
||||
|
||||
// Trigger initial line setting
|
||||
mouseMoveEvent(event);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -324,15 +342,18 @@ void NodeViewItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
// See if the mouse is currently inside a connector rect
|
||||
for (int i=0;i<drop_item->node()->ParameterCount();i++) {
|
||||
QRectF comp_rect = drop_item->GetParameterConnectorRect(i).adjusted(-node_connector_size_,
|
||||
-node_connector_size_,
|
||||
node_connector_size_,
|
||||
node_connector_size_);
|
||||
|
||||
// Make a larger "hitbox" rect to make it easier to drag into
|
||||
QRectF param_hitbox = drop_item->GetParameterConnectorRect(i).adjusted(-node_connector_size_,
|
||||
-node_connector_size_,
|
||||
node_connector_size_,
|
||||
node_connector_size_);
|
||||
|
||||
// Get the parameter we're dragging into
|
||||
NodeParam* comp_param = drop_item->node()->ParamAt(i);
|
||||
|
||||
// If so, we snap inside it
|
||||
if (comp_rect.contains(drop_item->mapFromScene(event->scenePos()))) {
|
||||
if (param_hitbox.contains(drop_item->mapFromScene(event->scenePos())) // See if we're dragging inside the hitbox
|
||||
&& NodeParam::AreDataTypesCompatible(drag_src_param_, comp_param)) { // Make sure the types are compatible
|
||||
|
||||
drag_dest_param_ = comp_param;
|
||||
end_point = drop_item->mapToScene(drop_item->GetParameterConnectorRect(i).center());
|
||||
@@ -361,18 +382,11 @@ void NodeViewItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
// FIXME: Make this undoable
|
||||
|
||||
// If this edge had an edge, we should disconnect it now
|
||||
if (dragging_edge_->edge() != nullptr) {
|
||||
NodeParam::DisconnectEdge(dragging_edge_->edge());
|
||||
scene()->removeItem(dragging_edge_);
|
||||
|
||||
dragging_edge_->SetEdge(nullptr);
|
||||
}
|
||||
if (drag_dest_param_ != nullptr) {
|
||||
// We dragged to somewhere, so we'll make a new connection
|
||||
|
||||
if (drag_dest_param_ == nullptr) {
|
||||
// If we didn't drag to anywhere, just get rid of this edge
|
||||
scene()->removeItem(dragging_edge_);
|
||||
} else {
|
||||
// If we did, create a new edge now
|
||||
NodeEdgePtr new_edge;
|
||||
|
||||
if (drag_dest_param_->type() == NodeParam::kOutput) {
|
||||
@@ -380,8 +394,6 @@ void NodeViewItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
} else {
|
||||
new_edge = NodeParam::ConnectEdge(static_cast<NodeOutput*>(drag_src_param_), static_cast<NodeInput*>(drag_dest_param_));
|
||||
}
|
||||
|
||||
dragging_edge_->SetEdge(new_edge);
|
||||
}
|
||||
|
||||
dragging_edge_ = nullptr;
|
||||
@@ -397,27 +409,3 @@ void NodeViewItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
QGraphicsRectItem::mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
NodeViewItemWidget::NodeViewItemWidget()
|
||||
{
|
||||
}
|
||||
|
||||
QColor NodeViewItemWidget::TitleBarColor()
|
||||
{
|
||||
return title_bar_color_;
|
||||
}
|
||||
|
||||
void NodeViewItemWidget::SetTitleBarColor(QColor color)
|
||||
{
|
||||
title_bar_color_ = color;
|
||||
}
|
||||
|
||||
QColor NodeViewItemWidget::BorderColor()
|
||||
{
|
||||
return border_color_;
|
||||
}
|
||||
|
||||
void NodeViewItemWidget::SetBorderColor(QColor color)
|
||||
{
|
||||
border_color_ = color;
|
||||
}
|
||||
|
||||
@@ -28,26 +28,7 @@
|
||||
|
||||
#include "node/node.h"
|
||||
#include "nodeviewedge.h"
|
||||
|
||||
/**
|
||||
* @brief A proxy object to allow NodeViewItem access to CSS functions
|
||||
*/
|
||||
class NodeViewItemWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor titlebarColor READ TitleBarColor WRITE SetTitleBarColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor borderColor READ BorderColor WRITE SetBorderColor DESIGNABLE true)
|
||||
public:
|
||||
NodeViewItemWidget();
|
||||
|
||||
QColor TitleBarColor();
|
||||
void SetTitleBarColor(QColor color);
|
||||
|
||||
QColor BorderColor();
|
||||
void SetBorderColor(QColor color);
|
||||
private:
|
||||
QColor title_bar_color_;
|
||||
QColor border_color_;
|
||||
};
|
||||
#include "nodeviewitemwidgetproxy.h"
|
||||
|
||||
class NodeViewItem : public QGraphicsRectItem
|
||||
{
|
||||
@@ -76,7 +57,7 @@ private:
|
||||
|
||||
Node* node_;
|
||||
|
||||
NodeViewItemWidget obj_proxy_;
|
||||
NodeViewItemWidget css_proxy_;
|
||||
|
||||
QRectF title_bar_rect_;
|
||||
|
||||
@@ -94,6 +75,9 @@ private:
|
||||
NodeViewItem* drag_source_;
|
||||
|
||||
int node_connector_size_;
|
||||
int node_text_padding_;
|
||||
int node_icon_padding_;
|
||||
int node_border_width_;
|
||||
|
||||
bool expanded_;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "nodeviewitemwidgetproxy.h"
|
||||
|
||||
NodeViewItemWidget::NodeViewItemWidget()
|
||||
{
|
||||
}
|
||||
|
||||
QColor NodeViewItemWidget::TitleBarColor()
|
||||
{
|
||||
return title_bar_color_;
|
||||
}
|
||||
|
||||
void NodeViewItemWidget::SetTitleBarColor(QColor color)
|
||||
{
|
||||
title_bar_color_ = color;
|
||||
}
|
||||
|
||||
QColor NodeViewItemWidget::BorderColor()
|
||||
{
|
||||
return border_color_;
|
||||
}
|
||||
|
||||
void NodeViewItemWidget::SetBorderColor(QColor color)
|
||||
{
|
||||
border_color_ = color;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef NODEVIEWITEMWIDGETPROXY_H
|
||||
#define NODEVIEWITEMWIDGETPROXY_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
/**
|
||||
* @brief A proxy object to allow NodeViewItem access to CSS functions
|
||||
*
|
||||
* QGraphicsItems can't take Q_PROPERTYs for CSS stylesheet input, but QWidgets can. This is a hack to allow CSS
|
||||
* properties to be set from CSS and then read by NodeViewItem.
|
||||
*/
|
||||
class NodeViewItemWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor titlebarColor READ TitleBarColor WRITE SetTitleBarColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor borderColor READ BorderColor WRITE SetBorderColor DESIGNABLE true)
|
||||
public:
|
||||
NodeViewItemWidget();
|
||||
|
||||
QColor TitleBarColor();
|
||||
void SetTitleBarColor(QColor color);
|
||||
|
||||
QColor BorderColor();
|
||||
void SetBorderColor(QColor color);
|
||||
private:
|
||||
QColor title_bar_color_;
|
||||
QColor border_color_;
|
||||
};
|
||||
|
||||
#endif // NODEVIEWITEMWIDGETPROXY_H
|
||||
@@ -83,10 +83,12 @@ void olive::MainWindow::ProjectOpen(Project* p)
|
||||
NodeGraph* graph = new NodeGraph();
|
||||
graph->setParent(this);
|
||||
graph->set_name("New Graph");
|
||||
ViewerOutput* vo = new ViewerOutput(graph);
|
||||
ViewerOutput* vo = new ViewerOutput();
|
||||
vo->AttachViewer(viewer_panel2);
|
||||
SolidGenerator* sg = new SolidGenerator(graph);
|
||||
graph->AddNode(vo);
|
||||
SolidGenerator* sg = new SolidGenerator();
|
||||
NodeInput::ConnectEdge(sg->texture_output(), vo->texture_input());
|
||||
graph->AddNode(sg);
|
||||
task_panel->SetGraph(graph);
|
||||
// End test code
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user