diff --git a/app/panel/node/node.cpp b/app/panel/node/node.cpp index d6abc3a1d..5e694867b 100644 --- a/app/panel/node/node.cpp +++ b/app/panel/node/node.cpp @@ -31,7 +31,8 @@ NodePanel::NodePanel(QWidget *parent) : // 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::NodeGroupOpenRequested, this, &NodePanel::NodeGroupOpenRequested); + connect(node_widget_->view(), &NodeView::NodeGroupOpened, this, &NodePanel::NodeGroupOpened); + connect(node_widget_->view(), &NodeView::NodeGroupClosed, this, &NodePanel::NodeGroupClosed); // Set it as the main widget of this panel SetWidgetWithPadding(node_widget_); diff --git a/app/panel/node/node.h b/app/panel/node/node.h index f1dae048f..b9a5ebf35 100644 --- a/app/panel/node/node.h +++ b/app/panel/node/node.h @@ -40,10 +40,9 @@ public: return node_widget_; } - const QVector &GetContexts() const - { - return node_widget_->view()->GetContexts(); - } + const QVector &GetContexts() const { return node_widget_->view()->GetContexts(); } + + bool IsGroupOverlay() const { return node_widget_->view()->IsGroupOverlay(); } void SetContexts(const QVector &nodes) { @@ -55,11 +54,6 @@ public: node_widget_->view()->CloseContextsBelongingToProject(project); } - const QVector &GetCurrentContexts() const - { - return node_widget_->view()->GetCurrentContexts(); - } - virtual void SelectAll() override { node_widget_->view()->SelectAll(); @@ -122,7 +116,9 @@ signals: void NodesDeselected(const QVector& nodes); - void NodeGroupOpenRequested(NodeGroup *group); + void NodeGroupOpened(NodeGroup *group); + + void NodeGroupClosed(); private: virtual void Retranslate() override diff --git a/app/panel/param/param.cpp b/app/panel/param/param.cpp index 8504a86b4..5f51b21e7 100644 --- a/app/panel/param/param.cpp +++ b/app/panel/param/param.cpp @@ -61,9 +61,9 @@ void ParamPanel::DeselectAll() static_cast(GetTimeBasedWidget())->DeselectAll(); } -void ParamPanel::SetContexts(const QVector &contexts) +void ParamPanel::SetContexts(const QVector &contexts, bool group_mode) { - static_cast(GetTimeBasedWidget())->SetContexts(contexts); + static_cast(GetTimeBasedWidget())->SetContexts(contexts, group_mode); } void ParamPanel::Retranslate() diff --git a/app/panel/param/param.h b/app/panel/param/param.h index 9f2336eb1..c45a981cf 100644 --- a/app/panel/param/param.h +++ b/app/panel/param/param.h @@ -43,16 +43,6 @@ public: return GetParamView()->GetContexts(); } - void SetCreateCheckBoxes(NodeParamViewCheckBoxBehavior e) - { - GetParamView()->SetCreateCheckBoxes(e); - } - - void SetIgnoreNodeFlags(bool e) - { - GetParamView()->SetIgnoreNodeFlags(e); - } - void CloseContextsBelongingToProject(Project *p) { GetParamView()->CloseContextsBelongingToProject(p); @@ -68,7 +58,7 @@ public slots: virtual void DeselectAll() override; - void SetContexts(const QVector &contexts); + void SetContexts(const QVector &contexts, bool group_mode); signals: void RequestSelectNode(const QVector& target); diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp index 48339d4a3..865ab2982 100644 --- a/app/widget/nodeparamview/nodeparamview.cpp +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -37,9 +37,8 @@ NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) : super(true, false, parent), last_scroll_val_(0), focused_node_(nullptr), - create_checkboxes_(kNoCheckBoxes), time_target_(nullptr), - ignore_flags_(false) + group_mode_(false) { // Create horizontal layout to place scroll area in (and keyframe editing eventually) QHBoxLayout* layout = new QHBoxLayout(this); @@ -174,7 +173,7 @@ void NodeParamView::CloseContextsBelongingToProject(Project *p) } } - SetContexts(new_contexts); + SetContexts(new_contexts, group_mode_); } /*void NodeParamView::SelectNodes(const QVector &nodes) @@ -236,15 +235,7 @@ void NodeParamView::DeselectNodes(const QVector &nodes) } }*/ -void NodeParamView::SetInputChecked(const NodeInput &input, bool e) -{ - input_checked_.insert(input, e); - foreach (NodeParamViewContext *ctx, context_items_) { - ctx->SetInputChecked(input, e); - } -} - -void NodeParamView::SetContexts(const QVector &contexts) +void NodeParamView::SetContexts(const QVector &contexts, bool group_mode) { //TIME_THIS_FUNCTION; @@ -258,6 +249,9 @@ void NodeParamView::SetContexts(const QVector &contexts) } contexts_ = contexts; + group_mode_ = group_mode; + + Q_ASSERT((contexts_.size() == 1 && dynamic_cast(contexts_.first())) || !group_mode_ || contexts_.isEmpty()); foreach (Node *ctx, contexts_) { // Queued so that if any further work is done in connecting this node to the context, it'll be @@ -285,6 +279,17 @@ void NodeParamView::SetContexts(const QVector &contexts) } } + if (group_mode_) { + // Check inputs that have been passed through + NodeGroup *group = static_cast(contexts_.first()); + for (auto it=group->GetInputPassthroughs().cbegin(); it!=group->GetInputPassthroughs().cend(); it++) { + GroupInputPassthroughAdded(group, it->second); + } + + connect(group, &NodeGroup::InputPassthroughAdded, this, &NodeParamView::GroupInputPassthroughAdded); + connect(group, &NodeGroup::InputPassthroughRemoved, this, &NodeParamView::GroupInputPassthroughRemoved); + } + foreach (NodeParamViewContext *ctx, context_items_) { SortItemsInContext(ctx); } @@ -386,24 +391,16 @@ void NodeParamView::QueueKeyframePositionUpdate() void NodeParamView::AddNode(Node *n, NodeParamViewContext *context) { - if ((n->GetFlags() & Node::kDontShowInParamView) && !ignore_flags_) { + if ((n->GetFlags() & Node::kDontShowInParamView) && !group_mode_) { return; } - NodeParamViewItem* item = new NodeParamViewItem(n, create_checkboxes_, context); + NodeParamViewItem* item = new NodeParamViewItem(n, group_mode_ ? kCheckBoxesOnNonConnected : kNoCheckBoxes, context); connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::SetTimeAndSignal); connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode); connect(item, &NodeParamViewItem::PinToggled, this, &NodeParamView::PinNode); - connect(item, &NodeParamViewItem::InputCheckedChanged, this, &NodeParamView::SetInputChecked); - - if (create_checkboxes_) { - for (auto it=input_checked_.cbegin(); it!=input_checked_.cend(); it++) { - if (it.key().node() == n) { - item->SetInputChecked(it.key(), it.value()); - } - } - } + connect(item, &NodeParamViewItem::InputCheckedChanged, this, &NodeParamView::InputCheckBoxChanged); item->SetTimeTarget(GetTimeTarget()); item->SetTimebase(timebase()); @@ -616,4 +613,35 @@ void NodeParamView::NodeAddedToContext(Node *n) SortItemsInContext(item); } +void NodeParamView::InputCheckBoxChanged(const NodeInput &input, bool e) +{ + NodeGroup *group = static_cast(contexts_.first()); + + if (e) { + group->AddInputPassthrough(input); + } else { + group->RemoveInputPassthrough(input); + } +} + +void NodeParamView::GroupInputPassthroughAdded(NodeGroup *group, const NodeInput &input) +{ + foreach (NodeParamViewContext *pvctx, context_items_) { + NodeParamViewItem *item = pvctx->GetItems().value(input.node()); + if (item) { + item->SetInputChecked(input, true); + } + } +} + +void NodeParamView::GroupInputPassthroughRemoved(NodeGroup *group, const NodeInput &input) +{ + foreach (NodeParamViewContext *pvctx, context_items_) { + NodeParamViewItem *item = pvctx->GetItems().value(input.node()); + if (item) { + item->SetInputChecked(input, false); + } + } +} + } diff --git a/app/widget/nodeparamview/nodeparamview.h b/app/widget/nodeparamview/nodeparamview.h index 6a00883fc..ceceb58a5 100644 --- a/app/widget/nodeparamview/nodeparamview.h +++ b/app/widget/nodeparamview/nodeparamview.h @@ -45,16 +45,6 @@ public: virtual ~NodeParamView() override; - void SetCreateCheckBoxes(NodeParamViewCheckBoxBehavior e) - { - create_checkboxes_ = e; - } - - bool IsInputChecked(const NodeInput &input) const - { - return input_checked_.value(input); - } - void CloseContextsBelongingToProject(Project *p); Node* GetTimeTarget() const; @@ -71,11 +61,6 @@ public: keyframe_view_->DeselectAll(); } - void SetIgnoreNodeFlags(bool e) - { - ignore_flags_ = e; - } - void SelectNodes(const QVector &nodes); void DeselectNodes(const QVector &nodes); @@ -85,9 +70,7 @@ public: } public slots: - void SetInputChecked(const NodeInput &input, bool e); - - void SetContexts(const QVector &contexts); + void SetContexts(const QVector &contexts, bool group_mode); void UpdateElementY(); @@ -136,16 +119,12 @@ private: NodeParamViewItem* focused_node_; - NodeParamViewCheckBoxBehavior create_checkboxes_; - Node *time_target_; - QHash input_checked_; - - bool ignore_flags_; - QVector contexts_; + bool group_mode_; + private slots: void UpdateGlobalScrollBar(); @@ -157,6 +136,12 @@ private slots: void NodeAddedToContext(Node *n); + void InputCheckBoxChanged(const NodeInput &input, bool e); + + void GroupInputPassthroughAdded(olive::NodeGroup *group, const olive::NodeInput &input); + + void GroupInputPassthroughRemoved(olive::NodeGroup *group, const olive::NodeInput &input); + }; } diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 2c1ffb3e5..044fd7a15 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ #include "node/factory.h" #include "node/group/group.h" #include "node/traverser.h" +#include "ui/icons/icons.h" #include "widget/menu/menushared.h" #include "widget/timebased/timebasedview.h" @@ -47,6 +49,7 @@ NodeView::NodeView(QWidget *parent) : create_edge_(nullptr), create_edge_output_item_(nullptr), create_edge_input_item_(nullptr), + overlay_view_(nullptr), scale_(1.0) { setScene(&scene_); @@ -83,6 +86,10 @@ NodeView::~NodeView() void NodeView::SetContexts(const QVector &nodes) { + if (overlay_view_) { + CloseOverlay(); + } + // Remove contexts that are no longer in the list foreach (Node *n, contexts_) { if (!nodes.contains(n)) { @@ -350,6 +357,8 @@ void NodeView::keyPressEvent(QKeyEvent *event) break; } + emit EscPressed(); + /* fall through */ default: super::keyPressEvent(event); @@ -657,6 +666,10 @@ void NodeView::resizeEvent(QResizeEvent *event) super::resizeEvent(event); RepositionMiniMap(); + + if (overlay_view_) { + ResizeOverlay(); + } } void NodeView::UpdateSelectionCache() @@ -1284,7 +1297,37 @@ void NodeView::ShowNodeProperties() Node *first_node = selected_nodes_.first(); if (NodeGroup *group = dynamic_cast(first_node)) { - emit NodeGroupOpenRequested(group); + if (!overlay_view_) { + overlay_view_ = new NodeView(this); + overlay_view_->show(); + + QPushButton *overlay_close_btn = new QPushButton(overlay_view_); + overlay_close_btn->setIcon(icon::Error); + int offset = overlay_close_btn->sizeHint().width()/2; + overlay_close_btn->move(offset, offset); + overlay_close_btn->show(); + + connect(overlay_view_, &NodeView::NodesSelected, this, &NodeView::NodesSelected); + connect(overlay_view_, &NodeView::NodesDeselected, this, &NodeView::NodesDeselected); + connect(overlay_view_, &NodeView::NodeGroupOpened, this, &NodeView::NodeGroupOpened); + connect(overlay_view_, &NodeView::NodeGroupClosed, this, &NodeView::NodeGroupClosed); + connect(overlay_view_, &NodeView::EscPressed, this, &NodeView::CloseOverlay); + connect(overlay_close_btn, &QPushButton::clicked, this, &NodeView::CloseOverlay); + + const QColor &bgcol = overlay_view_->palette().base().color(); + overlay_view_->setStyleSheet(QStringLiteral("QGraphicsView { background: rgba(%1, %2, %3, 0.8); }").arg(QString::number(bgcol.red()), QString::number(bgcol.green()), QString::number(bgcol.blue()))); + + overlay_close_btn->setStyleSheet(QStringLiteral("background: transparent; border: none;")); + } + overlay_view_->SetContexts({group}); + ResizeOverlay(); + QMetaObject::invokeMethod(overlay_view_, &NodeView::CenterOnItemsBoundingRect, Qt::QueuedConnection); + overlay_view_->setFocus(); + + emit NodesDeselected(selected_nodes_); + overlay_view_->SelectAll(); + + emit NodeGroupOpened(group); } else { LabelSelectedNodes(); } @@ -1320,6 +1363,17 @@ void NodeView::ItemAboutToBeDeleted(NodeViewItem *item) } } +void NodeView::CloseOverlay() +{ + if (overlay_view_->overlay_view_) { + overlay_view_->CloseOverlay(); + } + + overlay_view_->deleteLater(); + overlay_view_ = nullptr; + emit NodeGroupClosed(); +} + void NodeView::AddContext(Node *n) { NodeViewContext *ctx = scene_.AddContext(n); @@ -1477,6 +1531,11 @@ void NodeView::PostPaste(const QVector &new_nodes, const Node::PositionM SetAttachedItems(new_attached); } +void NodeView::ResizeOverlay() +{ + overlay_view_->resize(this->size()); +} + void NodeView::SetAttachedItems(const QVector &items) { // Detach anything currently attached diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index 79964a998..887e52cb7 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -54,7 +54,16 @@ public: const QVector &GetContexts() const { - return contexts_; + if (overlay_view_) { + return overlay_view_->GetContexts(); + } else { + return contexts_; + } + } + + bool IsGroupOverlay() const + { + return overlay_view_; } void CloseContextsBelongingToProject(Project *project); @@ -109,7 +118,10 @@ signals: void NodesDeselected(const QVector& nodes); - void NodeGroupOpenRequested(NodeGroup *group); + void NodeGroupOpened(NodeGroup *group); + void NodeGroupClosed(); + + void EscPressed(); protected: virtual void keyPressEvent(QKeyEvent *event) override; @@ -169,6 +181,8 @@ private: void PostPaste(const QVector &new_nodes, const Node::PositionMap &map); + void ResizeOverlay(); + NodeViewMiniMap *minimap_; struct AttachedItem { @@ -202,6 +216,8 @@ private: QMap dragging_items_; + NodeView* overlay_view_; + double scale_; static const double kMinimumScale; @@ -252,6 +268,8 @@ private slots: void ItemAboutToBeDeleted(NodeViewItem *item); + void CloseOverlay(); + }; } diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index a05d9e52e..e8d5b700b 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -94,7 +94,8 @@ MainWindow::MainWindow(QWidget *parent) : // 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::NodeGroupOpenRequested, this, &MainWindow::NodeGroupRequested); + 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& target){ node_panel_->Select(target, true); }); @@ -455,15 +456,10 @@ void MainWindow::StatusBarDoubleClicked() task_man_panel_->raise(); } -void MainWindow::NodeGroupRequested(NodeGroup *group) +void MainWindow::NodePanelGroupOpenedOrClosed() { - NodePanel *panel = new NodePanel(this); - panel->setFloating(true); - panel->setVisible(true); - panel->SetContexts({group}); - panel->SetSignalInsteadOfClose(true); - addDockWidget(Qt::LeftDockWidgetArea, panel); - connect(panel, &NodePanel::CloseRequested, panel, &NodePanel::deleteLater); + NodePanel *p = static_cast(sender()); + param_panel_->SetContexts(p->GetContexts(), p->IsGroupOverlay()); } void MainWindow::TimelinePanelSelectionChanged(const QVector &blocks) @@ -732,7 +728,7 @@ void MainWindow::UpdateNodePanelContextFromTimelinePanel(TimelinePanel *panel) } node_panel_->SetContexts(context); - param_panel_->SetContexts(context); + param_panel_->SetContexts(context, false); } void MainWindow::FocusedPanelChanged(PanelWidget *panel) @@ -747,10 +743,7 @@ void MainWindow::FocusedPanelChanged(PanelWidget *panel) const QVector &new_ctxs = node_panel->GetContexts(); if (new_ctxs != param_panel_->GetContexts()) { - bool is_default_node_panel = node_panel == node_panel_; - param_panel_->SetIgnoreNodeFlags(!is_default_node_panel); - param_panel_->SetCreateCheckBoxes(is_default_node_panel ? kNoCheckBoxes : kCheckBoxesOnNonConnected); - param_panel_->SetContexts(node_panel->GetContexts()); + param_panel_->SetContexts(new_ctxs, node_panel->IsGroupOverlay()); } } else if (TimelinePanel* timeline = dynamic_cast(panel)) { // Signal timeline focus diff --git a/app/window/mainwindow/mainwindow.h b/app/window/mainwindow/mainwindow.h index 1bcd5f10c..e027e08e6 100644 --- a/app/window/mainwindow/mainwindow.h +++ b/app/window/mainwindow/mainwindow.h @@ -185,7 +185,7 @@ private slots: void StatusBarDoubleClicked(); - void NodeGroupRequested(NodeGroup *group); + void NodePanelGroupOpenedOrClosed(); #ifdef Q_OS_LINUX void ShowNouveauWarning();