nodeparamview/nodeview: connect selections and enable multi-select in npv
This commit is contained in:
@@ -104,6 +104,11 @@ public:
|
||||
kAudioEffect = 0x4
|
||||
};
|
||||
|
||||
struct ContextPair {
|
||||
Node *node;
|
||||
Node *context;
|
||||
};
|
||||
|
||||
Node();
|
||||
|
||||
virtual ~Node() override;
|
||||
|
||||
@@ -28,9 +28,10 @@ NodePanel::NodePanel(QWidget *parent) :
|
||||
node_widget_ = new NodeWidget();
|
||||
connect(this, &NodePanel::visibilityChanged, node_widget_->view(), &NodeView::CenterOnItemsBoundingRect);
|
||||
|
||||
// Connect node view signals to this panel - MAY REMOVE
|
||||
connect(node_widget_->view(), &NodeView::NodesSelected, this, &NodePanel::NodesSelected);
|
||||
connect(node_widget_->view(), &NodeView::NodesDeselected, this, &NodePanel::NodesDeselected);
|
||||
connect(node_widget_->view(), &NodeView::NodeSelectionChanged, this, &NodePanel::NodeSelectionChanged);
|
||||
connect(node_widget_->view(), &NodeView::NodeSelectionChangedWithContexts, this, &NodePanel::NodeSelectionChangedWithContexts);
|
||||
connect(node_widget_->view(), &NodeView::NodeGroupOpened, this, &NodePanel::NodeGroupOpened);
|
||||
connect(node_widget_->view(), &NodeView::NodeGroupClosed, this, &NodePanel::NodeGroupClosed);
|
||||
|
||||
|
||||
@@ -105,10 +105,9 @@ public:
|
||||
}
|
||||
|
||||
public slots:
|
||||
void Select(const QVector<Node*>& nodes, bool center_view_on_item)
|
||||
void Select(const QVector<Node::ContextPair> &p)
|
||||
{
|
||||
node_widget_->view()->Select(nodes, center_view_on_item);
|
||||
this->raise();
|
||||
node_widget_->view()->Select(p, true);
|
||||
}
|
||||
|
||||
signals:
|
||||
@@ -116,6 +115,9 @@ signals:
|
||||
|
||||
void NodesDeselected(const QVector<Node*>& nodes);
|
||||
|
||||
void NodeSelectionChanged(const QVector<Node*>& nodes);
|
||||
void NodeSelectionChangedWithContexts(const QVector<Node::ContextPair>& nodes);
|
||||
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
|
||||
void NodeGroupClosed();
|
||||
|
||||
@@ -28,24 +28,14 @@ ParamPanel::ParamPanel(QWidget* parent) :
|
||||
TimeBasedPanel(QStringLiteral("ParamPanel"), parent)
|
||||
{
|
||||
NodeParamView* view = new NodeParamView();
|
||||
connect(view, &NodeParamView::RequestSelectNode, this, &ParamPanel::RequestSelectNode);
|
||||
connect(view, &NodeParamView::FocusedNodeChanged, this, &ParamPanel::FocusedNodeChanged);
|
||||
connect(view, &NodeParamView::SelectedNodesChanged, this, &ParamPanel::SelectedNodesChanged);
|
||||
connect(this, &ParamPanel::visibilityChanged, view, &NodeParamView::UpdateElementY);
|
||||
SetTimeBasedWidget(view);
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void ParamPanel::SelectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->SelectNodes(nodes);
|
||||
}
|
||||
|
||||
void ParamPanel::DeselectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->DeselectNodes(nodes);
|
||||
}
|
||||
|
||||
void ParamPanel::DeleteSelected()
|
||||
{
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->DeleteSelected();
|
||||
|
||||
@@ -49,8 +49,10 @@ public:
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SelectNodes(const QVector<Node*>& nodes);
|
||||
void DeselectNodes(const QVector<Node*>& nodes);
|
||||
void SetSelectedNodes(const QVector<Node::ContextPair> &nodes)
|
||||
{
|
||||
GetParamView()->SetSelectedNodes(nodes, false);
|
||||
}
|
||||
|
||||
virtual void DeleteSelected() override;
|
||||
|
||||
@@ -61,10 +63,10 @@ public slots:
|
||||
void SetContexts(const QVector<Node*> &contexts);
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(const QVector<Node*>& target);
|
||||
|
||||
void FocusedNodeChanged(Node* n);
|
||||
|
||||
void SelectedNodesChanged(const QVector<Node::ContextPair> &nodes);
|
||||
|
||||
protected:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
@@ -155,10 +155,11 @@ NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) :
|
||||
SetScale(120);
|
||||
|
||||
// Pickup on widget focus changes
|
||||
connect(qApp,
|
||||
// DISABLED - we now just handle this with item/titlebar clicking (see ToggleSelect)
|
||||
/*connect(qApp,
|
||||
&QApplication::focusChanged,
|
||||
this,
|
||||
&NodeParamView::FocusChanged);
|
||||
&NodeParamView::FocusChanged);*/
|
||||
}
|
||||
|
||||
NodeParamView::~NodeParamView()
|
||||
@@ -297,12 +298,25 @@ void NodeParamView::ItemAboutToBeRemoved(NodeParamViewItem *item)
|
||||
}
|
||||
}
|
||||
|
||||
if (focused_node_ == item) {
|
||||
focused_node_ = nullptr;
|
||||
emit FocusedNodeChanged(nullptr);
|
||||
QVector<NodeParamViewItem *> copy = selected_nodes_;
|
||||
if (copy.removeOne(item)) {
|
||||
SetSelectedNodes(copy);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::ItemClicked()
|
||||
{
|
||||
ToggleSelect(static_cast<NodeParamViewItem*>(sender()));
|
||||
}
|
||||
|
||||
void NodeParamView::SelectNodeFromConnectedLink(Node *node)
|
||||
{
|
||||
NodeParamViewItem *item = static_cast<NodeParamViewItem *>(sender());
|
||||
|
||||
Node::ContextPair p = {node, item->GetContext()};
|
||||
SetSelectedNodes({p});
|
||||
}
|
||||
|
||||
void NodeParamView::SetContexts(const QVector<Node *> &contexts)
|
||||
{
|
||||
// Setting contexts is expensive, so we queue it here to prevent multiple calls in a short timespan
|
||||
@@ -371,41 +385,138 @@ Node *NodeParamView::GetTimeTarget() const
|
||||
return time_target_;
|
||||
}
|
||||
|
||||
void ReconnectOutputsIfNotDeletingNode(MultiUndoCommand *c, NodeViewDeleteCommand *dc, Node *output, Node *deleting, Node *context)
|
||||
{
|
||||
for (auto it=deleting->output_connections().cbegin(); it!=deleting->output_connections().cend(); it++) {
|
||||
const NodeInput &proposed_reconnect = it->second;
|
||||
|
||||
if (dc->ContainsNode(proposed_reconnect.node(), context)) {
|
||||
// Uh-oh we're deleting this node too, instead connect to its outputs
|
||||
ReconnectOutputsIfNotDeletingNode(c, dc, output, proposed_reconnect.node(), context);
|
||||
} else {
|
||||
c->add_child(new NodeEdgeAddCommand(output, it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::DeleteSelected()
|
||||
{
|
||||
if (keyframe_view_ && keyframe_view_->hasFocus()) {
|
||||
keyframe_view_->DeleteSelected();
|
||||
} else if (focused_node_) {
|
||||
} else if (!selected_nodes_.isEmpty()) {
|
||||
MultiUndoCommand *c = new MultiUndoCommand();
|
||||
Node *n = focused_node_->GetNode();
|
||||
|
||||
// Create command to delete node from context and/or graph
|
||||
NodeViewDeleteCommand *dc = new NodeViewDeleteCommand();
|
||||
dc->AddNode(n, focused_node_->GetContext());
|
||||
c->add_child(dc);
|
||||
|
||||
// Copy any outputs that were connected
|
||||
if (n->GetEffectInput().IsValid()) {
|
||||
if (Node *out = n->GetEffectInput().GetConnectedOutput()) {
|
||||
for (auto it=n->output_connections().cbegin(); it!=n->output_connections().cend(); it++) {
|
||||
c->add_child(new NodeEdgeAddCommand(out, it->second));
|
||||
}
|
||||
}
|
||||
// Add all nodes
|
||||
foreach (NodeParamViewItem *item, selected_nodes_) {
|
||||
Node *n = item->GetNode();
|
||||
dc->AddNode(n, item->GetContext());
|
||||
}
|
||||
|
||||
// Make reconnections where possible
|
||||
foreach (NodeParamViewItem *item, selected_nodes_) {
|
||||
Node *n = item->GetNode();
|
||||
|
||||
Node *node_being_deleted = n;
|
||||
Node *connected_to_effect_input = n;
|
||||
|
||||
while (true) {
|
||||
if (node_being_deleted->GetEffectInput().IsValid()) {
|
||||
if ((connected_to_effect_input = node_being_deleted->GetEffectInput().GetConnectedOutput())) {
|
||||
if (dc->ContainsNode(connected_to_effect_input, item->GetContext())) {
|
||||
// Node's getting deleted, recurse
|
||||
node_being_deleted = connected_to_effect_input;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (connected_to_effect_input) {
|
||||
ReconnectOutputsIfNotDeletingNode(c, dc, connected_to_effect_input, n, item->GetContext());
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(c);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::SelectNodes(const QVector<Node *> &nodes)
|
||||
void NodeParamView::SetSelectedNodes(const QVector<NodeParamViewItem *> &nodes, bool handle_focused_node, bool emit_signal)
|
||||
{
|
||||
// Do nothing, this is a placeholder if we ever need this to do anything in the future
|
||||
if (handle_focused_node) {
|
||||
handle_focused_node = !focused_node_ || selected_nodes_.contains(focused_node_);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItem *n, selected_nodes_) {
|
||||
n->SetHighlighted(false);
|
||||
}
|
||||
|
||||
selected_nodes_ = nodes;
|
||||
|
||||
QVector<Node::ContextPair> p;
|
||||
if (emit_signal) {
|
||||
p.resize(selected_nodes_.size());
|
||||
}
|
||||
|
||||
for (int i=0; i<selected_nodes_.size(); i++) {
|
||||
NodeParamViewItem *n = selected_nodes_.at(i);
|
||||
n->SetHighlighted(true);
|
||||
|
||||
if (emit_signal) {
|
||||
p[i] = {n->GetNode(), n->GetContext()};
|
||||
}
|
||||
}
|
||||
|
||||
if (handle_focused_node) {
|
||||
focused_node_ = nullptr;
|
||||
|
||||
foreach (NodeParamViewItem *n, selected_nodes_) {
|
||||
if (n->GetNode()->HasGizmos()) {
|
||||
focused_node_ = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Node *n = focused_node_ ? focused_node_->GetNode() : nullptr;
|
||||
emit FocusedNodeChanged(n);
|
||||
}
|
||||
|
||||
if (emit_signal) {
|
||||
emit SelectedNodesChanged(p);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::DeselectNodes(const QVector<Node *> &nodes)
|
||||
void NodeParamView::SetSelectedNodes(const QVector<Node::ContextPair> &nodes, bool emit_signal)
|
||||
{
|
||||
// Do nothing, this is a placeholder if we ever need this to do anything in the future
|
||||
QVector<NodeParamViewItem*> items;
|
||||
|
||||
foreach (const Node::ContextPair &n, nodes) {
|
||||
for (auto it=context_items_.cbegin(); it!=context_items_.cend(); it++) {
|
||||
NodeParamViewContext *ctx = *it;
|
||||
|
||||
NodeParamViewItem *item = ctx->GetItem(n.node, n.context);
|
||||
|
||||
if (item) {
|
||||
items.append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetSelectedNodes(items, true, emit_signal);
|
||||
|
||||
if (!selected_nodes_.empty()) {
|
||||
NodeParamViewItem *scrolled_to = selected_nodes_.front();
|
||||
param_scroll_area_->ensureWidgetVisible(scrolled_to, 0, 0);
|
||||
|
||||
QPoint viewport_pos = scrolled_to->mapTo(param_scroll_area_, scrolled_to->geometry().topLeft());
|
||||
|
||||
param_scroll_area_->verticalScrollBar()->setValue(viewport_pos.y());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::UpdateItemTime(const rational &time)
|
||||
@@ -461,9 +572,10 @@ void NodeParamView::AddNode(Node *n, Node *ctx, NodeParamViewContext *context)
|
||||
NodeParamViewItem* item = new NodeParamViewItem(n, IsGroupMode() ? kCheckBoxesOnNonConnected : kNoCheckBoxes, context);
|
||||
|
||||
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::SetTimeAndSignal);
|
||||
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode);
|
||||
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::SelectNodeFromConnectedLink);
|
||||
connect(item, &NodeParamViewItem::PinToggled, this, &NodeParamView::PinNode);
|
||||
connect(item, &NodeParamViewItem::InputCheckedChanged, this, &NodeParamView::InputCheckBoxChanged);
|
||||
connect(item, &NodeParamViewItem::Clicked, this, &NodeParamView::ItemClicked);
|
||||
|
||||
item->SetContext(ctx);
|
||||
item->SetTimeTarget(GetTimeTarget());
|
||||
@@ -474,9 +586,7 @@ void NodeParamView::AddNode(Node *n, Node *ctx, NodeParamViewContext *context)
|
||||
|
||||
if (!focused_node_ && n->HasGizmos()) {
|
||||
// We'll focus this node now
|
||||
item->SetHighlighted(true);
|
||||
focused_node_ = item;
|
||||
emit FocusedNodeChanged(n);
|
||||
SetSelectedNodes({item});
|
||||
}
|
||||
|
||||
if (keyframe_view_) {
|
||||
@@ -561,6 +671,36 @@ NodeParamViewContext *NodeParamView::GetContextItemFromContext(Node *ctx)
|
||||
return context_items_.at(ctx_type);
|
||||
}
|
||||
|
||||
void NodeParamView::ToggleSelect(NodeParamViewItem *item)
|
||||
{
|
||||
QVector<NodeParamViewItem*> new_sel;
|
||||
|
||||
if (qApp->keyboardModifiers() & Qt::ShiftModifier) {
|
||||
new_sel = selected_nodes_;
|
||||
}
|
||||
|
||||
if (selected_nodes_.contains(item)) {
|
||||
// De-select this node
|
||||
if (qApp->keyboardModifiers() & Qt::ShiftModifier) {
|
||||
new_sel.removeOne(item);
|
||||
SetSelectedNodes(new_sel, true);
|
||||
}
|
||||
} else {
|
||||
new_sel.append(item);
|
||||
SetSelectedNodes(new_sel, false);
|
||||
|
||||
if (item->GetNode()->HasGizmos() || !new_sel.contains(focused_node_)) {
|
||||
if (item->GetNode()->HasGizmos()) {
|
||||
focused_node_ = item;
|
||||
} else {
|
||||
focused_node_ = nullptr;
|
||||
}
|
||||
|
||||
emit FocusedNodeChanged(focused_node_ ? focused_node_->GetNode() : nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::UpdateGlobalScrollBar()
|
||||
{
|
||||
if (keyframe_view_) {
|
||||
@@ -584,7 +724,7 @@ void NodeParamView::PinNode(bool pin)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::FocusChanged(QWidget* old, QWidget* now)
|
||||
/*void NodeParamView::FocusChanged(QWidget* old, QWidget* now)
|
||||
{
|
||||
Q_UNUSED(old)
|
||||
|
||||
@@ -592,39 +732,28 @@ void NodeParamView::FocusChanged(QWidget* old, QWidget* now)
|
||||
|
||||
while (parent) {
|
||||
if (NodeParamViewItem* item = dynamic_cast<NodeParamViewItem*>(parent)) {
|
||||
if (item != focused_node_) {
|
||||
// Found a NodeParamViewItem that isn't already focused, see if it belongs to us
|
||||
bool ours = false;
|
||||
// Found a NodeParamViewItem that isn't already focused, see if it belongs to us
|
||||
bool ours = false;
|
||||
|
||||
do {
|
||||
parent = parent->parent();
|
||||
do {
|
||||
parent = parent->parent();
|
||||
|
||||
if (parent == this) {
|
||||
ours = true;
|
||||
break;
|
||||
}
|
||||
} while (parent);
|
||||
|
||||
if (ours) {
|
||||
// This item is ours,
|
||||
if (focused_node_) {
|
||||
// De-focus current node
|
||||
focused_node_->SetHighlighted(false);
|
||||
}
|
||||
|
||||
focused_node_ = item;
|
||||
|
||||
item->SetHighlighted(true);
|
||||
|
||||
emit FocusedNodeChanged(item->GetNode());
|
||||
if (parent == this) {
|
||||
ours = true;
|
||||
break;
|
||||
}
|
||||
} while (parent);
|
||||
|
||||
if (ours) {
|
||||
//ToggleSelect(item);
|
||||
Q_UNUSED(item)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
parent = parent->parent();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
void NodeParamView::KeyframeViewDragged(int x, int y)
|
||||
{
|
||||
|
||||
@@ -61,8 +61,8 @@ public:
|
||||
keyframe_view_->DeselectAll();
|
||||
}
|
||||
|
||||
void SelectNodes(const QVector<Node*> &nodes);
|
||||
void DeselectNodes(const QVector<Node*> &nodes);
|
||||
void SetSelectedNodes(const QVector<NodeParamViewItem *> &nodes, bool handle_focused_node = true, bool emit_signal = true);
|
||||
void SetSelectedNodes(const QVector<Node::ContextPair> &nodes, bool emit_signal = true);
|
||||
|
||||
const QVector<Node*> &GetContexts() const
|
||||
{
|
||||
@@ -75,10 +75,10 @@ public slots:
|
||||
void UpdateElementY();
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(const QVector<Node*>& target);
|
||||
|
||||
void FocusedNodeChanged(Node* n);
|
||||
|
||||
void SelectedNodesChanged(const QVector<Node::ContextPair> &nodes);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
@@ -118,6 +118,8 @@ private:
|
||||
return contexts_.size() == 1 && dynamic_cast<NodeGroup*>(contexts_.first());
|
||||
}
|
||||
|
||||
void ToggleSelect(NodeParamViewItem *item);
|
||||
|
||||
KeyframeView* keyframe_view_;
|
||||
|
||||
QVector<NodeParamViewContext*> context_items_;
|
||||
@@ -137,6 +139,7 @@ private:
|
||||
QVector<Node*> active_nodes_;
|
||||
|
||||
NodeParamViewItem* focused_node_;
|
||||
QVector<NodeParamViewItem*> selected_nodes_;
|
||||
|
||||
Node *time_target_;
|
||||
|
||||
@@ -150,7 +153,7 @@ private slots:
|
||||
|
||||
void PinNode(bool pin);
|
||||
|
||||
void FocusChanged(QWidget *old, QWidget *now);
|
||||
//void FocusChanged(QWidget *old, QWidget *now);
|
||||
|
||||
void KeyframeViewDragged(int x, int y);
|
||||
|
||||
@@ -168,6 +171,10 @@ private slots:
|
||||
|
||||
void ItemAboutToBeRemoved(NodeParamViewItem *item);
|
||||
|
||||
void ItemClicked();
|
||||
|
||||
void SelectNodeFromConnectedLink(Node *node);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ void NodeParamViewConnectedLabel::ShowLabelContextMenu()
|
||||
void NodeParamViewConnectedLabel::ConnectionClicked()
|
||||
{
|
||||
if (connected_node_) {
|
||||
emit RequestSelectNode({connected_node_});
|
||||
emit RequestSelectNode(connected_node_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
void SetTime(const rational &time);
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(const QVector<Node*>& node);
|
||||
void RequestSelectNode(Node *n);
|
||||
|
||||
private slots:
|
||||
void InputConnected(Node *output, const NodeInput &input);
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
signals:
|
||||
void RequestSetTime(const rational& time);
|
||||
|
||||
void RequestSelectNode(const QVector<Node*>& node);
|
||||
void RequestSelectNode(Node *node);
|
||||
|
||||
void ArrayExpandedChanged(bool e);
|
||||
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
signals:
|
||||
void RequestSetTime(const rational& time);
|
||||
|
||||
void RequestSelectNode(const QVector<Node*>& node);
|
||||
void RequestSelectNode(Node *node);
|
||||
|
||||
void ArrayExpandedChanged(bool e);
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ NodeParamViewItemBase::NodeParamViewItemBase(QWidget *parent) :
|
||||
// Connect title bar to this
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::ExpandedStateChanged, this, &NodeParamViewItemBase::SetExpanded);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::PinToggled, this, &NodeParamViewItemBase::PinToggled);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::Clicked, this, &NodeParamViewItemBase::Clicked);
|
||||
|
||||
// Use dummy QWidget to retain width when not expanded (QDockWidget seems to ignore the titlebar
|
||||
// size hints and will shrink as small as possible if the body is hidden)
|
||||
@@ -115,4 +116,11 @@ void NodeParamViewItemBase::moveEvent(QMoveEvent *event)
|
||||
emit Moved();
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
super::mousePressEvent(e);
|
||||
|
||||
emit Clicked();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ signals:
|
||||
|
||||
void Moved();
|
||||
|
||||
void Clicked();
|
||||
|
||||
protected:
|
||||
void SetBody(QWidget *body);
|
||||
|
||||
@@ -74,6 +76,8 @@ protected:
|
||||
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Retranslate(){}
|
||||
|
||||
|
||||
@@ -85,6 +85,13 @@ void NodeParamViewItemTitleBar::paintEvent(QPaintEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mousePressEvent(event);
|
||||
|
||||
emit Clicked();
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
|
||||
@@ -79,9 +79,12 @@ signals:
|
||||
|
||||
void EnabledCheckBoxClicked(bool e);
|
||||
|
||||
void Clicked();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -51,7 +51,8 @@ NodeView::NodeView(QWidget *parent) :
|
||||
create_edge_output_item_(nullptr),
|
||||
create_edge_input_item_(nullptr),
|
||||
overlay_view_(nullptr),
|
||||
scale_(1.0)
|
||||
scale_(1.0),
|
||||
dont_emit_selection_signals_(false)
|
||||
{
|
||||
setScene(&scene_);
|
||||
SetDefaultDragMode(RubberBandDrag);
|
||||
@@ -171,9 +172,11 @@ void NodeView::DeselectAll()
|
||||
// Just emit all the nodes that are currently selected as no longer selected
|
||||
emit NodesDeselected(selected_nodes_);
|
||||
selected_nodes_.clear();
|
||||
emit NodeSelectionChanged(selected_nodes_);
|
||||
emit NodeSelectionChangedWithContexts(QVector<Node::ContextPair>());
|
||||
}
|
||||
|
||||
void NodeView::Select(const QVector<Node *> &nodes, bool center_view_on_item)
|
||||
void NodeView::Select(const QVector<Node::ContextPair> &nodes, bool center_view_on_item)
|
||||
{
|
||||
// Optimization: rather than respond to every single item being selected, ignore the signal and
|
||||
// then handle them all at the end.
|
||||
@@ -184,18 +187,27 @@ void NodeView::Select(const QVector<Node *> &nodes, bool center_view_on_item)
|
||||
|
||||
scene_.DeselectAll();
|
||||
|
||||
foreach (NodeViewContext *context, scene_.context_map()) {
|
||||
context->Select(nodes);
|
||||
foreach (const Node::ContextPair &p, nodes) {
|
||||
NodeViewContext *ctx = scene_.context_map().value(p.context);
|
||||
if (ctx) {
|
||||
NodeViewItem *item = ctx->GetItemFromMap(p.node);
|
||||
if (item) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Center on something
|
||||
if (center_view_on_item && !nodes.isEmpty()) {
|
||||
QMetaObject::invokeMethod(this, "CenterOnNode", Qt::QueuedConnection, OLIVE_NS_ARG(Node*, nodes.first()));
|
||||
QMetaObject::invokeMethod(this, "CenterOnNode", Qt::QueuedConnection, OLIVE_NS_ARG(Node*, nodes.first().node));
|
||||
}
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
|
||||
// Don't signal when this function was likely triggered from another widget's signal anyway
|
||||
dont_emit_selection_signals_ = true;
|
||||
UpdateSelectionCache();
|
||||
dont_emit_selection_signals_ = false;
|
||||
}
|
||||
|
||||
void NodeView::CopySelected(bool cut)
|
||||
@@ -734,13 +746,18 @@ void NodeView::UpdateSelectionCache()
|
||||
QVector<Node*> selected;
|
||||
QVector<Node*> deselected;
|
||||
|
||||
QVector<Node::ContextPair> sel_with_ctx(current_selection.size());
|
||||
|
||||
// Determine which nodes are newly selected
|
||||
foreach (NodeViewItem* i, current_selection) {
|
||||
for (int j=0; j<current_selection.size(); j++) {
|
||||
NodeViewItem *i = current_selection.at(j);
|
||||
Node *n = i->GetNode();
|
||||
if (!selected_nodes_.contains(n)) {
|
||||
selected.append(n);
|
||||
selected_nodes_.append(n);
|
||||
}
|
||||
|
||||
sel_with_ctx[j] = {n, i->GetContext()};
|
||||
}
|
||||
|
||||
// Determine which nodes are newly deselected
|
||||
@@ -773,6 +790,11 @@ void NodeView::UpdateSelectionCache()
|
||||
if (!selected.isEmpty()) {
|
||||
emit NodesSelected(selected);
|
||||
}
|
||||
|
||||
if (!dont_emit_selection_signals_) {
|
||||
emit NodeSelectionChanged(selected_nodes_);
|
||||
emit NodeSelectionChangedWithContexts(sel_with_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::ShowContextMenu(const QPoint &pos)
|
||||
@@ -1344,6 +1366,8 @@ void NodeView::ShowNodeProperties()
|
||||
overlay_view_->setFocus();
|
||||
|
||||
emit NodesDeselected(selected_nodes_);
|
||||
emit NodeSelectionChanged(QVector<Node*>());
|
||||
emit NodeSelectionChangedWithContexts(QVector<Node::ContextPair>());
|
||||
overlay_view_->SelectAll();
|
||||
|
||||
emit NodeGroupOpened(group);
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void Select(const QVector<Node *> &nodes, bool center_view_on_item);
|
||||
void Select(const QVector<Node::ContextPair> &nodes, bool center_view_on_item);
|
||||
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
@@ -117,6 +117,9 @@ signals:
|
||||
|
||||
void NodesDeselected(const QVector<Node*>& nodes);
|
||||
|
||||
void NodeSelectionChanged(const QVector<Node*>& nodes);
|
||||
void NodeSelectionChangedWithContexts(const QVector<Node::ContextPair>& nodes);
|
||||
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
void NodeGroupClosed();
|
||||
|
||||
@@ -218,6 +221,8 @@ private:
|
||||
|
||||
double scale_;
|
||||
|
||||
bool dont_emit_selection_signals_;
|
||||
|
||||
static const double kMinimumScale;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -199,13 +199,12 @@ NodeViewDeleteCommand::NodeViewDeleteCommand()
|
||||
|
||||
void NodeViewDeleteCommand::AddNode(Node *node, Node *context)
|
||||
{
|
||||
foreach (const NodePair &pair, nodes_) {
|
||||
if (pair.first == node && pair.second == context) {
|
||||
return;
|
||||
}
|
||||
if (ContainsNode(node, context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nodes_.append(NodePair({node, context}));
|
||||
Node::ContextPair p = {node, context};
|
||||
nodes_.append(p);
|
||||
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (context->ContextContainsNode(it->second)) {
|
||||
@@ -231,10 +230,21 @@ void NodeViewDeleteCommand::AddEdge(Node *output, const NodeInput &input)
|
||||
edges_.append({output, input});
|
||||
}
|
||||
|
||||
bool NodeViewDeleteCommand::ContainsNode(Node *node, Node *context)
|
||||
{
|
||||
foreach (const Node::ContextPair &pair, nodes_) {
|
||||
if (pair.node == node && pair.context == context) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Project *NodeViewDeleteCommand::GetRelevantProject() const
|
||||
{
|
||||
if (!nodes_.isEmpty()) {
|
||||
return nodes_.first().first->project();
|
||||
return nodes_.first().node->project();
|
||||
}
|
||||
|
||||
if (!edges_.isEmpty()) {
|
||||
@@ -250,11 +260,11 @@ void NodeViewDeleteCommand::redo()
|
||||
Node::DisconnectEdge(edge.first, edge.second);
|
||||
}
|
||||
|
||||
foreach (const NodePair &pair, nodes_) {
|
||||
foreach (const Node::ContextPair &pair, nodes_) {
|
||||
RemovedNode rn;
|
||||
|
||||
rn.node = pair.first;
|
||||
rn.context = pair.second;
|
||||
rn.node = pair.node;
|
||||
rn.context = pair.context;
|
||||
rn.pos = rn.context->GetNodePositionInContext(rn.node);
|
||||
|
||||
rn.context->RemoveNodeFromContext(rn.node);
|
||||
|
||||
@@ -372,6 +372,8 @@ public:
|
||||
|
||||
void AddEdge(Node *output, const NodeInput &input);
|
||||
|
||||
bool ContainsNode(Node *node, Node *context);
|
||||
|
||||
virtual Project * GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
@@ -380,9 +382,7 @@ protected:
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
using NodePair = QPair<Node *, Node*>;
|
||||
|
||||
QVector<NodePair> nodes_;
|
||||
QVector<Node::ContextPair> nodes_;
|
||||
|
||||
QVector<Node::OutputConnection> edges_;
|
||||
|
||||
|
||||
@@ -92,15 +92,12 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
scope_panel_ = new ScopePanel(this);
|
||||
|
||||
// Make node-related connections
|
||||
connect(node_panel_, &NodePanel::NodesSelected, param_panel_, &ParamPanel::SelectNodes);
|
||||
connect(node_panel_, &NodePanel::NodesDeselected, param_panel_, &ParamPanel::DeselectNodes);
|
||||
connect(node_panel_, &NodePanel::NodeSelectionChangedWithContexts, param_panel_, &ParamPanel::SetSelectedNodes);
|
||||
connect(node_panel_, &NodePanel::NodeGroupOpened, this, &MainWindow::NodePanelGroupOpenedOrClosed);
|
||||
connect(node_panel_, &NodePanel::NodeGroupClosed, this, &MainWindow::NodePanelGroupOpenedOrClosed);
|
||||
connect(param_panel_, &ParamPanel::RequestSelectNode, this, [this](const QVector<Node*>& target){
|
||||
node_panel_->Select(target, true);
|
||||
});
|
||||
connect(param_panel_, &ParamPanel::FocusedNodeChanged, sequence_viewer_panel_, &ViewerPanel::SetGizmos);
|
||||
connect(param_panel_, &ParamPanel::FocusedNodeChanged, curve_panel_, &CurvePanel::SetNode);
|
||||
connect(param_panel_, &ParamPanel::SelectedNodesChanged, node_panel_, &NodePanel::Select);
|
||||
|
||||
// Connect time signals together
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
|
||||
|
||||
Reference in New Issue
Block a user