diff --git a/app/widget/keyframeview/keyframeview.cpp b/app/widget/keyframeview/keyframeview.cpp index 203a8d70a..40c604143 100644 --- a/app/widget/keyframeview/keyframeview.cpp +++ b/app/widget/keyframeview/keyframeview.cpp @@ -10,6 +10,23 @@ KeyframeView::KeyframeView(QWidget *parent) : setDragMode(QGraphicsView::RubberBandDrag); } +void KeyframeView::AddKeyframe(NodeKeyframePtr key, int y) +{ + QPoint global_pt(0, y); + QPoint local_pt = mapFromGlobal(global_pt); + QPointF scene_pt = mapToScene(local_pt); + + KeyframeViewItem* item = new KeyframeViewItem(key, scene_pt.y()); + item->SetScale(scale_); + item_map_.insert(key.get(), item); + scene()->addItem(item); +} + +void KeyframeView::RemoveKeyframe(NodeKeyframePtr key) +{ + delete item_map_.value(key.get()); +} + void KeyframeView::mousePressEvent(QMouseEvent *event) { if (PlayheadPress(event)) { @@ -36,3 +53,12 @@ void KeyframeView::mouseReleaseEvent(QMouseEvent *event) QGraphicsView::mouseReleaseEvent(event); } + +void KeyframeView::ScaleChangedEvent(double scale) +{ + QMap::const_iterator iterator; + + for (iterator=item_map_.begin();iterator!=item_map_.end();iterator++) { + iterator.value()->SetScale(scale); + } +} diff --git a/app/widget/keyframeview/keyframeview.h b/app/widget/keyframeview/keyframeview.h index cb7abc79d..db6857170 100644 --- a/app/widget/keyframeview/keyframeview.h +++ b/app/widget/keyframeview/keyframeview.h @@ -9,18 +9,24 @@ class KeyframeView : public TimelineViewBase { + Q_OBJECT public: KeyframeView(QWidget* parent = nullptr); - void AddKeyframe(const rational& time, int y); +public slots: + void AddKeyframe(NodeKeyframePtr key, int y); + + void RemoveKeyframe(NodeKeyframePtr key); protected: virtual void mousePressEvent(QMouseEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void mouseReleaseEvent(QMouseEvent *event) override; -private: + virtual void ScaleChangedEvent(double scale) override; +private: + QMap item_map_; }; #endif // KEYFRAMEVIEW_H diff --git a/app/widget/keyframeview/keyframeviewitem.cpp b/app/widget/keyframeview/keyframeviewitem.cpp index 5f724337f..7eca92dba 100644 --- a/app/widget/keyframeview/keyframeviewitem.cpp +++ b/app/widget/keyframeview/keyframeviewitem.cpp @@ -7,25 +7,18 @@ #include "common/qtversionabstraction.h" -KeyframeViewItem::KeyframeViewItem(QGraphicsItem *parent) : +KeyframeViewItem::KeyframeViewItem(NodeKeyframePtr key, qreal vcenter, QGraphicsItem *parent) : QGraphicsRectItem(parent), - key_(nullptr), - scale_(1.0) + key_(key), + scale_(1.0), + middle_(vcenter) { keyframe_size_ = QFontMetricsWidth(qApp->fontMetrics(), "Oi"); setFlag(QGraphicsItem::ItemIsSelectable); setFlag(QGraphicsItem::ItemIsMovable); -} -void KeyframeViewItem::SetKeyframe(NodeKeyframe *key) -{ - key_ = key; - UpdateRect(); -} + connect(key.get(), SIGNAL(TimeChanged(const rational&)), this, SLOT(UpdateRect())); -void KeyframeViewItem::SetVerticalCenter(int middle) -{ - middle_ = middle; UpdateRect(); } @@ -37,10 +30,6 @@ void KeyframeViewItem::SetScale(double scale) void KeyframeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - if (!key_) { - return; - } - painter->setPen(Qt::black); if (option->state & QStyle::State_Selected) { @@ -73,10 +62,6 @@ void KeyframeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * void KeyframeViewItem::UpdateRect() { - if (!key_) { - return; - } - double x_center = key_->time().toDouble() * scale_; setRect(x_center - keyframe_size_/2, middle_ - keyframe_size_/2, keyframe_size_, keyframe_size_); diff --git a/app/widget/keyframeview/keyframeviewitem.h b/app/widget/keyframeview/keyframeviewitem.h index 9c724d4e9..69390fcb7 100644 --- a/app/widget/keyframeview/keyframeviewitem.h +++ b/app/widget/keyframeview/keyframeviewitem.h @@ -5,14 +5,11 @@ #include "node/keyframe.h" -class KeyframeViewItem : public QGraphicsRectItem +class KeyframeViewItem : public QObject, public QGraphicsRectItem { + Q_OBJECT public: - KeyframeViewItem(QGraphicsItem *parent = nullptr); - - void SetKeyframe(NodeKeyframe* key); - - void SetVerticalCenter(int middle); + KeyframeViewItem(NodeKeyframePtr key, qreal vcenter, QGraphicsItem *parent = nullptr); void SetScale(double scale); @@ -20,15 +17,17 @@ protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; private: - void UpdateRect(); - - NodeKeyframe* key_; + NodeKeyframePtr key_; double scale_; - int middle_; + qreal middle_; int keyframe_size_; + +private slots: + void UpdateRect(); + }; #endif // KEYFRAMEVIEWITEM_H diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp index 205dccc0c..51d803daf 100644 --- a/app/widget/nodeparamview/nodeparamview.cpp +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -23,6 +23,7 @@ #include #include +#include "common/timecodefunctions.h" #include "node/output/viewer/viewer.h" NodeParamView::NodeParamView(QWidget *parent) : @@ -70,6 +71,8 @@ NodeParamView::NodeParamView(QWidget *parent) : // Connect ruler and keyframe view together connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), keyframe_view_, SLOT(SetTime(const int64_t&))); connect(keyframe_view_, SIGNAL(TimeChanged(const int64_t&)), ruler_, SLOT(SetTime(const int64_t&))); + connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), this, SLOT(RulerTimeChanged(const int64_t&))); + connect(keyframe_view_, SIGNAL(TimeChanged(const int64_t&)), this, SLOT(RulerTimeChanged(const int64_t&))); splitter->addWidget(keyframe_area); @@ -93,30 +96,16 @@ void NodeParamView::SetNodes(QList nodes) // For each node, create a widget foreach (Node* node, nodes_) { + NodeParamViewItem* item = new NodeParamViewItem(node); - // See if we already have an item for this node type + // Insert the widget before the stretch + param_layout_->insertWidget(param_layout_->count() - 1, item); - bool merged_node = false; + connect(item, SIGNAL(KeyframeAdded(NodeKeyframePtr, int)), keyframe_view_, SLOT(AddKeyframe(NodeKeyframePtr, int))); + connect(item, SIGNAL(KeyframeRemoved(NodeKeyframePtr)), keyframe_view_, SLOT(RemoveKeyframe(NodeKeyframePtr))); + connect(item, SIGNAL(RequestSetTime(const rational&)), this, SLOT(SetTime(const rational&))); - foreach (NodeParamViewItem* existing_item, items_) { - if (existing_item->CanAddNode(node)) { - existing_item->AttachNode(node); - merged_node = true; - break; - } - } - - // If we couldn't merge this node into the existing item, create a new one - if (!merged_node) { - NodeParamViewItem* item = new NodeParamViewItem(this); - - item->AttachNode(node); - - // Insert the widget before the stretch - param_layout_->insertWidget(param_layout_->count() - 1, item); - - items_.append(item); - } + items_.append(item); } if (!nodes_.isEmpty()) { @@ -126,6 +115,8 @@ void NodeParamView::SetNodes(QList nodes) SetTimebase(viewer->video_params().time_base()); } } + + SetTime(0); } const QList &NodeParamView::nodes() @@ -144,8 +135,32 @@ void NodeParamView::SetScale(const double& scale) keyframe_view_->SetScale(scale); } +void NodeParamView::SetTime(const rational &time) +{ + int64_t timestamp = olive::time_to_timestamp(time, keyframe_view_->timebase()); + + ruler_->SetTime(timestamp); + keyframe_view_->SetTime(timestamp); + + UpdateItemTime(time); +} + void NodeParamView::SetTimebase(const rational &timebase) { ruler_->SetTimebase(timebase); keyframe_view_->SetTimebase(timebase); } + +void NodeParamView::UpdateItemTime(const rational &time) +{ + foreach (NodeParamViewItem* item, items_) { + item->SetTime(time); + } +} + +void NodeParamView::RulerTimeChanged(const int64_t ×tamp) +{ + rational time = olive::timestamp_to_time(timestamp, keyframe_view_->timebase()); + + UpdateItemTime(time); +} diff --git a/app/widget/nodeparamview/nodeparamview.h b/app/widget/nodeparamview/nodeparamview.h index 1430d3728..ad1d11db8 100644 --- a/app/widget/nodeparamview/nodeparamview.h +++ b/app/widget/nodeparamview/nodeparamview.h @@ -31,6 +31,7 @@ class NodeParamView : public QWidget { + Q_OBJECT public: NodeParamView(QWidget* parent); @@ -40,9 +41,14 @@ public: const double& GetScale() const; void SetScale(const double &scale); +public slots: + void SetTime(const rational& time); + private: void SetTimebase(const rational& timebase); + void UpdateItemTime(const rational& time); + QVBoxLayout* param_layout_; KeyframeView* keyframe_view_; @@ -52,6 +58,10 @@ private: QList nodes_; QList items_; + +private slots: + void RulerTimeChanged(const int64_t& timestamp); + }; #endif // NODEPARAMVIEW_H diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp index 64ac571cc..50c4e7c47 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.cpp +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -26,14 +26,14 @@ #include #include -#include "nodeparamviewkeyframecontrol.h" #include "nodeparamviewundo.h" #include "project/item/sequence/sequence.h" #include "ui/icons/icons.h" #include "undo/undostack.h" -NodeParamViewItem::NodeParamViewItem(QWidget *parent) : - QWidget(parent) +NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) : + QWidget(parent), + node_(node) { QVBoxLayout* main_layout = new QVBoxLayout(this); main_layout->setSpacing(0); @@ -70,48 +70,52 @@ NodeParamViewItem::NodeParamViewItem(QWidget *parent) : // Set correct widget state SetExpanded(title_bar_collapse_btn_->isChecked()); + + SetupUI(); } -void NodeParamViewItem::AttachNode(Node *n) +void NodeParamViewItem::SetTime(const rational &time) { - // Make sure we can attach this node (CanAddNode() should be run by the caller to make sure this node is valid) - Q_ASSERT(CanAddNode(n)); + time_ = time; - // Add node to the list - nodes_.append(n); - - // If the added node was the first node, set up the UI - if (nodes_.size() == 1) { - SetupUI(); - } else { - AddAdditionalNode(n); + foreach (NodeParamViewWidgetBridge* bridge, bridges_) { + // Updates the UI widgets from the time + bridge->SetTime(time_); } -} -bool NodeParamViewItem::CanAddNode(Node* n) -{ - // Ensures that all Nodes have the same ID - return (nodes_.isEmpty() || nodes_.first()->id() == n->id()); + foreach (NodeParamViewKeyframeControl* key_control, key_control_list_) { + UpdateKeyframeControl(key_control); + } } void NodeParamViewItem::changeEvent(QEvent *e) { - if (e->type() == QEvent::LanguageChange && !nodes_.isEmpty()) { + if (e->type() == QEvent::LanguageChange) { Retranslate(); } QWidget::changeEvent(e); } +void NodeParamViewItem::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframePtr keyframe) +{ + // Find its row in the parameters + QLabel* lbl = label_map_.value(input); + + // Find label's Y position + QPoint lbl_center = lbl->rect().center(); + + // Find global position + lbl_center = lbl->mapToGlobal(lbl_center); + + emit KeyframeAdded(keyframe, lbl_center.y()); +} + void NodeParamViewItem::SetupUI() { - Q_ASSERT(!nodes_.isEmpty()); - - Node* first_node = nodes_.first(); - int row_count = 0; - foreach (NodeParam* param, first_node->parameters()) { + foreach (NodeParam* param, node_->parameters()) { // This widget only needs to show input parameters if (param->type() == NodeParam::kInput) { NodeInput* input = static_cast(param); @@ -120,11 +124,12 @@ void NodeParamViewItem::SetupUI() QLabel* param_label = new QLabel(); param_lbls_.append(param_label); + label_map_.insert(input, param_label); + content_layout_->addWidget(param_label, row_count, 0); // Create a widget/input bridge for this input - NodeParamViewWidgetBridge* bridge = new NodeParamViewWidgetBridge(this); - bridge->AddInput(input); + NodeParamViewWidgetBridge* bridge = new NodeParamViewWidgetBridge(input, this); bridges_.append(bridge); // Add widgets for this parameter ot the layout @@ -140,6 +145,15 @@ void NodeParamViewItem::SetupUI() NodeParamViewKeyframeControl* key_control = new NodeParamViewKeyframeControl(input); content_layout_->addWidget(key_control, row_count, control_column); + connect(key_control, &NodeParamViewKeyframeControl::KeyframeEnableChanged, this, &NodeParamViewItem::UserChangedKeyframeEnable); + connect(key_control, &NodeParamViewKeyframeControl::GoToPreviousKey, this, &NodeParamViewItem::GoToPreviousKey); + connect(key_control, &NodeParamViewKeyframeControl::GoToNextKey, this, &NodeParamViewItem::GoToNextKey); + connect(key_control, &NodeParamViewKeyframeControl::KeyframeToggled, this, &NodeParamViewItem::UserToggledKeyframe); + key_control_list_.append(key_control); + + connect(input, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewItem::InputKeyframeEnableChanged); + connect(input, &NodeInput::KeyframeAdded, this, &NodeParamViewItem::InputAddedKeyframe); + connect(input, &NodeInput::KeyframeRemoved, this, &NodeParamViewItem::KeyframeRemoved); } row_count++; @@ -149,30 +163,15 @@ void NodeParamViewItem::SetupUI() Retranslate(); } -void NodeParamViewItem::AddAdditionalNode(Node *n) -{ - int bridge_count = 0; - - foreach (NodeParam* param, n->parameters()) { - if (param->type() == NodeParam::kInput) { - bridges_.at(bridge_count)->AddInput(static_cast(param)); - - bridge_count++; - } - } -} - void NodeParamViewItem::Retranslate() { - Node* first_node = nodes_.first(); + node_->Retranslate(); - first_node->Retranslate(); - - title_bar_lbl_->setText(first_node->Name()); + title_bar_lbl_->setText(node_->Name()); int row_count = 0; - foreach (NodeParam* param, first_node->parameters()) { + foreach (NodeParam* param, node_->parameters()) { // This widget only needs to show input parameters if (param->type() == NodeParam::kInput) { param_lbls_.at(row_count)->setText(tr("%1:").arg(param->name())); @@ -182,6 +181,27 @@ void NodeParamViewItem::Retranslate() } } +void NodeParamViewItem::UpdateKeyframeControl(NodeParamViewKeyframeControl *key_control) +{ + NodeInput* input = key_control->GetConnectedInput(); + + // Update UI based on time + key_control->SetPreviousButtonEnabled(time_ > input->keyframes().first()->time()); + key_control->SetNextButtonEnabled(time_ < input->keyframes().last()->time()); + key_control->SetToggleButtonChecked(input->has_keyframe_at_time(time_)); +} + +NodeParamViewKeyframeControl *NodeParamViewItem::KeyframeControlFromInput(NodeInput *input) const +{ + foreach (NodeParamViewKeyframeControl* key_control, key_control_list_) { + if (key_control->GetConnectedInput() == input) { + return key_control; + } + } + + return nullptr; +} + void NodeParamViewItem::SetExpanded(bool e) { expanded_ = e; @@ -195,7 +215,7 @@ void NodeParamViewItem::SetExpanded(bool e) } } -void NodeParamViewItem::KeyframeEnableChanged(bool e) +void NodeParamViewItem::UserChangedKeyframeEnable(bool e) { NodeParamViewKeyframeControl* control = static_cast(sender()); NodeInput* input = control->GetConnectedInput(); @@ -205,15 +225,14 @@ void NodeParamViewItem::KeyframeEnableChanged(bool e) return; } + QUndoCommand* command = new QUndoCommand(); + if (e) { - QUndoCommand* command = new QUndoCommand(); - // Enable keyframing - new NodeParamSetKeyframing(input, true, command); + new NodeParamSetKeyframingCommand(input, true, command); - // FIXME: Create a keyframe at this time - - olive::undo_stack.push(command); + // NodeInputs already have one keyframe by default, we move it to the current time here + new NodeParamSetKeyframeTimeCommand(input->keyframes().first(), time_, command); } else { // Confirm the user wants to clear all keyframes if (QMessageBox::warning(this, @@ -221,21 +240,107 @@ void NodeParamViewItem::KeyframeEnableChanged(bool e) tr("Are you sure you want to disable keyframing on this value? This will clear all existing keyframes."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - // Disable keyframing - QUndoCommand* command = new QUndoCommand(); + // Store value at this time, we'll set this as the persistent value later + QVariant stored_val = input->get_value_at_time(time_); - // FIXME: Delete all keyframes + // Delete all keyframes EXCEPT ONE + for (int i=input->keyframes().size()-1;i>0;i--) { + new NodeParamRemoveKeyframeCommand(input, input->keyframes().at(i), command); + } + + // Update value with this one + new NodeParamSetKeyframeValueCommand(input->keyframes().first(), stored_val, command); // Disable keyframing - new NodeParamSetKeyframing(input, false, command); - - olive::undo_stack.push(command); + new NodeParamSetKeyframingCommand(input, false, command); } else { // Disable action has effectively been ignored control->SetKeyframeEnabled(true); } } + + olive::undo_stack.pushIfHasChildren(command); +} + +void NodeParamViewItem::UserToggledKeyframe(bool e) +{ + NodeParamViewKeyframeControl* control = static_cast(sender()); + NodeInput* input = control->GetConnectedInput(); + NodeKeyframePtr key = input->get_keyframe_at_time(time_); + + QUndoCommand* command = new QUndoCommand(); + + if (e && !key) { + // Add a keyframe here + NodeKeyframePtr closest_key = input->get_closest_keyframe_to_time(time_); + + key = std::make_shared(time_, input->get_value_at_time(time_), closest_key->type()); + + new NodeParamInsertKeyframeCommand(input, key, command); + } else if (!e && key) { + // Remove a keyframe here + new NodeParamRemoveKeyframeCommand(input, key, command); + } + + olive::undo_stack.pushIfHasChildren(command); +} + +void NodeParamViewItem::InputKeyframeEnableChanged(bool e) +{ + NodeInput* input = static_cast(sender()); + + foreach (NodeKeyframePtr key, input->keyframes()) { + if (e) { + // Add a keyframe item for each keyframe + InputAddedKeyframeInternal(input, key); + } else { + // Remove each keyframe item + emit KeyframeRemoved(key); + } + } +} + +void NodeParamViewItem::InputAddedKeyframe(NodeKeyframePtr key) +{ + // Get NodeInput that emitted this signal + NodeInput* input = static_cast(sender()); + + InputAddedKeyframeInternal(input, key); + + UpdateKeyframeControl(KeyframeControlFromInput(input)); +} + +void NodeParamViewItem::GoToPreviousKey() +{ + NodeParamViewKeyframeControl* key_control = static_cast(sender()); + NodeInput* input = key_control->GetConnectedInput(); + + for (int i=input->keyframes().size()-1;i>=0;i--) { + // Find closest keyframe that is before this time + const rational& this_key_time = input->keyframes().at(i)->time(); + + if (this_key_time < time_) { + emit RequestSetTime(this_key_time); + break; + } + } +} + +void NodeParamViewItem::GoToNextKey() +{ + NodeParamViewKeyframeControl* key_control = static_cast(sender()); + NodeInput* input = key_control->GetConnectedInput(); + + for (int i=0;ikeyframes().size();i++) { + // Find closest keyframe that is before this time + const rational& this_key_time = input->keyframes().at(i)->time(); + + if (this_key_time > time_) { + emit RequestSetTime(this_key_time); + break; + } + } } NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent) : diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h index 42923c0d9..824ddf011 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.h +++ b/app/widget/nodeparamview/nodeparamviewitem.h @@ -28,6 +28,7 @@ #include #include "node/node.h" +#include "nodeparamviewkeyframecontrol.h" #include "nodeparamviewwidgetbridge.h" class NodeParamViewItemTitleBar : public QWidget { @@ -42,22 +43,31 @@ class NodeParamViewItem : public QWidget { Q_OBJECT public: - NodeParamViewItem(QWidget* parent); + NodeParamViewItem(Node* node, QWidget* parent = nullptr); - void AttachNode(Node* n); + void SetTime(const rational& time); - bool CanAddNode(Node *n); +signals: + void KeyframeAdded(NodeKeyframePtr key, int y); + + void KeyframeRemoved(NodeKeyframePtr key); + + void RequestSetTime(const rational& time); protected: - void changeEvent(QEvent *e) override; + virtual void changeEvent(QEvent *e) override; private: + void InputAddedKeyframeInternal(NodeInput* input, NodeKeyframePtr keyframe); + void SetupUI(); - void AddAdditionalNode(Node* n); - void Retranslate(); + void UpdateKeyframeControl(NodeParamViewKeyframeControl* key_control); + + NodeParamViewKeyframeControl* KeyframeControlFromInput(NodeInput* input) const; + bool expanded_; NodeParamViewItemTitleBar* title_bar_; @@ -72,14 +82,31 @@ private: QGridLayout* content_layout_; - QList nodes_; + Node* node_; QList bridges_; + rational time_; + + QMap label_map_; + + QList key_control_list_; + private slots: void SetExpanded(bool e); - void KeyframeEnableChanged(bool e); + void UserChangedKeyframeEnable(bool e); + + void UserToggledKeyframe(bool e); + + void InputKeyframeEnableChanged(bool e); + + void InputAddedKeyframe(NodeKeyframePtr key); + + void GoToPreviousKey(); + + void GoToNextKey(); + }; #endif // NODEPARAMVIEWITEM_H diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp index e533e5b3b..bedca64c0 100644 --- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp +++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.cpp @@ -33,8 +33,12 @@ NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(NodeInput* input, QWi enable_key_btn_->setIconSize(enable_key_btn_->iconSize() / 4 * 3); layout->addWidget(enable_key_btn_); - connect(enable_key_btn_, SIGNAL(toggled(bool)), this, SLOT(ShowButtonsFromKeyframeEnable(bool))); - connect(enable_key_btn_, SIGNAL(toggled(bool)), this, SIGNAL(KeyframeEnableChanged(bool))); + connect(prev_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::GoToPreviousKey); + connect(next_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::GoToNextKey); + connect(toggle_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::KeyframeToggled); + connect(enable_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable); + connect(enable_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::KeyframeEnableChanged); + connect(input_, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::SetKeyframeEnabled); // Pick up keyframing value ShowButtonsFromKeyframeEnable(input_->is_keyframing()); @@ -45,6 +49,26 @@ NodeInput *NodeParamViewKeyframeControl::GetConnectedInput() const return input_; } +void NodeParamViewKeyframeControl::SetPreviousButtonEnabled(bool enabled) +{ + prev_key_btn_->setEnabled(enabled); +} + +void NodeParamViewKeyframeControl::SetNextButtonEnabled(bool enabled) +{ + next_key_btn_->setEnabled(enabled); +} + +void NodeParamViewKeyframeControl::SetToggleButtonChecked(bool checked) +{ + // Suppress KeyframeToggled() signal from this object + blockSignals(true); + + toggle_key_btn_->setChecked(checked); + + blockSignals(false); +} + void NodeParamViewKeyframeControl::SetKeyframeEnabled(bool e) { // Suppress KeyframeEnableChanged() signal from this object diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h index 9a71ed4b8..f3a566940 100644 --- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h +++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h @@ -14,12 +14,21 @@ public: NodeInput* GetConnectedInput() const; + void SetPreviousButtonEnabled(bool enabled); + void SetNextButtonEnabled(bool enabled); + void SetToggleButtonChecked(bool checked); + public slots: void SetKeyframeEnabled(bool e); signals: void KeyframeEnableChanged(bool); + void GoToPreviousKey(); + void GoToNextKey(); + + void KeyframeToggled(bool); + private: QPushButton* CreateNewToolButton(const QIcon &icon) const; diff --git a/app/widget/nodeparamview/nodeparamviewundo.cpp b/app/widget/nodeparamview/nodeparamviewundo.cpp index 008608fc7..8f92a5d5c 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.cpp +++ b/app/widget/nodeparamview/nodeparamviewundo.cpp @@ -1,6 +1,6 @@ #include "nodeparamviewundo.h" -NodeParamSetKeyframing::NodeParamSetKeyframing(NodeInput *input, bool setting, QUndoCommand *parent) : +NodeParamSetKeyframingCommand::NodeParamSetKeyframingCommand(NodeInput *input, bool setting, QUndoCommand *parent) : QUndoCommand(parent), input_(input), setting_(setting) @@ -8,12 +8,82 @@ NodeParamSetKeyframing::NodeParamSetKeyframing(NodeInput *input, bool setting, Q Q_ASSERT(setting != input_->is_keyframing()); } -void NodeParamSetKeyframing::redo() +void NodeParamSetKeyframingCommand::redo() { input_->set_is_keyframing(setting_); } -void NodeParamSetKeyframing::undo() +void NodeParamSetKeyframingCommand::undo() { input_->set_is_keyframing(!setting_); } + +NodeParamSetKeyframeValueCommand::NodeParamSetKeyframeValueCommand(NodeKeyframePtr key, const QVariant& value, QUndoCommand* parent) : + QUndoCommand(parent), + key_(key), + old_value_(key_->value()), + new_value_(value) +{ +} + +void NodeParamSetKeyframeValueCommand::redo() +{ + key_->set_value(new_value_); +} + +void NodeParamSetKeyframeValueCommand::undo() +{ + key_->set_value(old_value_); +} + +NodeParamInsertKeyframeCommand::NodeParamInsertKeyframeCommand(NodeInput *input, NodeKeyframePtr keyframe, QUndoCommand* parent) : + QUndoCommand(parent), + input_(input), + keyframe_(keyframe) +{ +} + +void NodeParamInsertKeyframeCommand::redo() +{ + input_->insert_keyframe(keyframe_); +} + +void NodeParamInsertKeyframeCommand::undo() +{ + input_->remove_keyframe(keyframe_); +} + +NodeParamRemoveKeyframeCommand::NodeParamRemoveKeyframeCommand(NodeInput *input, NodeKeyframePtr keyframe, QUndoCommand *parent) : + QUndoCommand(parent), + input_(input), + keyframe_(keyframe) +{ +} + +void NodeParamRemoveKeyframeCommand::redo() +{ + input_->remove_keyframe(keyframe_); +} + +void NodeParamRemoveKeyframeCommand::undo() +{ + input_->insert_keyframe(keyframe_); +} + +NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational &time, QUndoCommand *parent) : + QUndoCommand(parent), + key_(key), + old_time_(key->time()), + new_time_(time) +{ +} + +void NodeParamSetKeyframeTimeCommand::redo() +{ + key_->set_time(new_time_); +} + +void NodeParamSetKeyframeTimeCommand::undo() +{ + key_->set_time(old_time_); +} diff --git a/app/widget/nodeparamview/nodeparamviewundo.h b/app/widget/nodeparamview/nodeparamviewundo.h index e13b82b66..a4f342cf5 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.h +++ b/app/widget/nodeparamview/nodeparamviewundo.h @@ -5,9 +5,9 @@ #include "node/input.h" -class NodeParamSetKeyframing : public QUndoCommand { +class NodeParamSetKeyframingCommand : public QUndoCommand { public: - NodeParamSetKeyframing(NodeInput* input, bool setting, QUndoCommand* parent = nullptr); + NodeParamSetKeyframingCommand(NodeInput* input, bool setting, QUndoCommand* parent = nullptr); virtual void redo() override; virtual void undo() override; @@ -17,4 +17,62 @@ private: bool setting_; }; +class NodeParamInsertKeyframeCommand : public QUndoCommand { +public: + NodeParamInsertKeyframeCommand(NodeInput* input, NodeKeyframePtr keyframe, QUndoCommand *parent = nullptr); + + virtual void redo() override; + virtual void undo() override; + +private: + NodeInput* input_; + + NodeKeyframePtr keyframe_; + +}; + +class NodeParamRemoveKeyframeCommand : public QUndoCommand { +public: + NodeParamRemoveKeyframeCommand(NodeInput* input, NodeKeyframePtr keyframe, QUndoCommand *parent = nullptr); + + virtual void redo() override; + virtual void undo() override; + +private: + NodeInput* input_; + + NodeKeyframePtr keyframe_; + +}; + +class NodeParamSetKeyframeTimeCommand : public QUndoCommand { +public: + NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational& time, QUndoCommand* parent = nullptr); + + virtual void redo() override; + virtual void undo() override; + +private: + NodeKeyframePtr key_; + + rational old_time_; + rational new_time_; + +}; + +class NodeParamSetKeyframeValueCommand : public QUndoCommand { +public: + NodeParamSetKeyframeValueCommand(NodeKeyframePtr key, const QVariant& value, QUndoCommand* parent = nullptr); + + virtual void redo() override; + virtual void undo() override; + +private: + NodeKeyframePtr key_; + + QVariant old_value_; + QVariant new_value_; + +}; + #endif // NODEPARAMVIEWUNDO_H diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 27ce5beac..5ce8eb24d 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -8,27 +8,95 @@ #include #include "node/node.h" +#include "nodeparamviewundo.h" +#include "project/item/sequence/sequence.h" +#include "undo/undostack.h" #include "widget/footagecombobox/footagecombobox.h" #include "widget/slider/floatslider.h" #include "widget/slider/integerslider.h" -// FIXME: Test code only -#include "panel/panelmanager.h" -#include "panel/project/project.h" -// End test code - -NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(QObject* parent) : - QObject(parent) +NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(NodeInput *input, QObject *parent) : + QObject(parent), + input_(input) { + CreateWidgets(); } -void NodeParamViewWidgetBridge::AddInput(NodeInput *input) +void NodeParamViewWidgetBridge::SetTime(const rational &time) { - inputs_.append(input); + time_ = time; - // If this was the first input, create the widgets - if (inputs_.size() == 1) { - CreateWidgets(); + // We assume the first data type is the "primary" type + switch (input_->data_type()) { + // None of these inputs have applicable UI widgets + case NodeParam::kNone: + case NodeParam::kAny: + case NodeParam::kTexture: + case NodeParam::kMatrix: + case NodeParam::kRational: + case NodeParam::kSamples: + case NodeParam::kDecimal: + case NodeParam::kWholeNumber: + case NodeParam::kNumber: + case NodeParam::kString: + case NodeParam::kBuffer: + case NodeParam::kVector: + break; + case NodeParam::kInt: + static_cast(widgets_.first())->SetValue(input_->get_value_at_time(time).toLongLong()); + break; + case NodeParam::kFloat: + static_cast(widgets_.first())->SetValue(input_->get_value_at_time(time).toDouble()); + break; + case NodeParam::kVec2: + { + QVector2D vec2 = input_->get_value_at_time(time).value(); + + static_cast(widgets_.at(0))->SetValue(static_cast(vec2.x())); + static_cast(widgets_.at(1))->SetValue(static_cast(vec2.y())); + break; + } + case NodeParam::kVec3: + { + QVector3D vec3 = input_->get_value_at_time(time).value(); + + static_cast(widgets_.at(0))->SetValue(static_cast(vec3.x())); + static_cast(widgets_.at(1))->SetValue(static_cast(vec3.y())); + static_cast(widgets_.at(2))->SetValue(static_cast(vec3.z())); + break; + } + case NodeParam::kVec4: + { + QVector4D vec4 = input_->get_value_at_time(time).value(); + + static_cast(widgets_.at(0))->SetValue(static_cast(vec4.x())); + static_cast(widgets_.at(1))->SetValue(static_cast(vec4.y())); + static_cast(widgets_.at(2))->SetValue(static_cast(vec4.z())); + static_cast(widgets_.at(3))->SetValue(static_cast(vec4.w())); + break; + } + case NodeParam::kFile: + // FIXME: File selector + break; + case NodeParam::kColor: + // FIXME: Color selector + break; + case NodeParam::kText: + { + static_cast(widgets_.first())->setText(input_->get_value_at_time(time).toString()); + break; + } + case NodeParam::kBoolean: + static_cast(widgets_.first())->setChecked(input_->get_value_at_time(time).toBool()); + break; + case NodeParam::kFont: + { + // FIXME: Implement this + break; + } + case NodeParam::kFootage: + static_cast(widgets_.first())->SetFootage(input_->get_value_at_time(time).value()); + break; } } @@ -39,10 +107,8 @@ const QList &NodeParamViewWidgetBridge::widgets() void NodeParamViewWidgetBridge::CreateWidgets() { - NodeInput* base_input = inputs_.first(); - // We assume the first data type is the "primary" type - switch (base_input->data_type()) { + switch (input_->data_type()) { // None of these inputs have applicable UI widgets case NodeParam::kNone: case NodeParam::kAny: @@ -61,14 +127,12 @@ void NodeParamViewWidgetBridge::CreateWidgets() { IntegerSlider* slider = new IntegerSlider(); - slider->SetValue(base_input->get_value_at_time(0).toLongLong()); - - if (base_input->has_minimum()) { - slider->SetMinimum(base_input->minimum().toLongLong()); + if (input_->has_minimum()) { + slider->SetMinimum(input_->minimum().toLongLong()); } - if (base_input->has_maximum()) { - slider->SetMaximum(base_input->maximum().toLongLong()); + if (input_->has_maximum()) { + slider->SetMaximum(input_->maximum().toLongLong()); } connect(slider, SIGNAL(ValueChanged(int64_t)), this, SLOT(WidgetCallback())); @@ -80,14 +144,12 @@ void NodeParamViewWidgetBridge::CreateWidgets() { FloatSlider* slider = new FloatSlider(); - slider->SetValue(base_input->get_value_at_time(0).toDouble()); - - if (base_input->has_minimum()) { - slider->SetMinimum(base_input->minimum().toDouble()); + if (input_->has_minimum()) { + slider->SetMinimum(input_->minimum().toDouble()); } - if (base_input->has_maximum()) { - slider->SetMaximum(base_input->maximum().toDouble()); + if (input_->has_maximum()) { + slider->SetMaximum(input_->maximum().toDouble()); } connect(slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); @@ -97,60 +159,45 @@ void NodeParamViewWidgetBridge::CreateWidgets() } case NodeParam::kVec2: { - QVector2D vec2 = base_input->get_value_at_time(0).value(); - FloatSlider* x_slider = new FloatSlider(); - x_slider->SetValue(static_cast(vec2.x())); widgets_.append(x_slider); connect(x_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* y_slider = new FloatSlider(); - y_slider->SetValue(static_cast(vec2.y())); widgets_.append(y_slider); connect(y_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); break; } case NodeParam::kVec3: { - QVector3D vec3 = base_input->get_value_at_time(0).value(); - FloatSlider* x_slider = new FloatSlider(); - x_slider->SetValue(static_cast(vec3.x())); widgets_.append(x_slider); connect(x_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* y_slider = new FloatSlider(); - y_slider->SetValue(static_cast(vec3.y())); widgets_.append(y_slider); connect(y_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* z_slider = new FloatSlider(); - z_slider->SetValue(static_cast(vec3.z())); widgets_.append(z_slider); connect(z_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); break; } case NodeParam::kVec4: { - QVector4D vec4 = base_input->get_value_at_time(0).value(); - FloatSlider* x_slider = new FloatSlider(); - x_slider->SetValue(static_cast(vec4.x())); widgets_.append(x_slider); connect(x_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* y_slider = new FloatSlider(); - y_slider->SetValue(static_cast(vec4.y())); widgets_.append(y_slider); connect(y_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* z_slider = new FloatSlider(); - z_slider->SetValue(static_cast(vec4.z())); widgets_.append(z_slider); connect(z_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); FloatSlider* w_slider = new FloatSlider(); - w_slider->SetValue(static_cast(vec4.w())); widgets_.append(w_slider); connect(w_slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback())); break; @@ -171,7 +218,6 @@ void NodeParamViewWidgetBridge::CreateWidgets() case NodeParam::kBoolean: { QCheckBox* check_box = new QCheckBox(); - check_box->setChecked(base_input->get_value_at_time(0).toBool()); widgets_.append(check_box); connect(check_box, SIGNAL(toggled(bool)), this, SLOT(WidgetCallback())); break; @@ -185,17 +231,9 @@ void NodeParamViewWidgetBridge::CreateWidgets() case NodeParam::kFootage: { FootageComboBox* footage_combobox = new FootageComboBox(); - - // FIXME: Test code - // Pretty hacky way of getting the root folder for this node's sequence - ProjectPanel* pp = olive::panel_manager->MostRecentlyFocused(); - footage_combobox->SetRoot(pp->project()->root()); - - // Use multiple values - footage_combobox->SetFootage(base_input->get_value_at_time(0).value()); + footage_combobox->SetRoot(static_cast(input_->parentNode()->parent())->project()->root()); connect(footage_combobox, SIGNAL(FootageChanged(StreamPtr)), this, SLOT(WidgetCallback())); - // End test code widgets_.append(footage_combobox); @@ -204,135 +242,156 @@ void NodeParamViewWidgetBridge::CreateWidgets() } } +void NodeParamViewWidgetBridge::SetInputValue(NodeInput *input, const QVariant &value) +{ + QUndoCommand* command = new QUndoCommand(); + + if (input->is_keyframing()) { + NodeKeyframePtr existing_key = input->get_keyframe_at_time(time_); + + if (existing_key) { + new NodeParamSetKeyframeValueCommand(existing_key, value, command); + } else { + // No existing key, create a new one + NodeKeyframePtr closest_key = input->get_closest_keyframe_to_time(time_); + NodeKeyframePtr new_key = std::make_shared(time_, value, closest_key->type()); + + new NodeParamInsertKeyframeCommand(input, new_key, command); + } + } else { + new NodeParamSetKeyframeValueCommand(input->keyframes().first(), value, command); + } + + olive::undo_stack.pushIfHasChildren(command); +} + void NodeParamViewWidgetBridge::WidgetCallback() { - foreach (NodeInput* input, inputs_) { - switch (input->data_type()) { - // None of these inputs have applicable UI widgets - case NodeParam::kNone: - case NodeParam::kAny: - case NodeParam::kTexture: - case NodeParam::kMatrix: - case NodeParam::kSamples: - case NodeParam::kRational: - case NodeParam::kDecimal: - case NodeParam::kWholeNumber: - case NodeParam::kNumber: - case NodeParam::kString: - case NodeParam::kVector: - case NodeParam::kBuffer: - break; - case NodeParam::kInt: - { - // Widget is a IntegerSlider - IntegerSlider* int_slider = static_cast(sender()); - input->set_value_at_time(0, int_slider->GetValue()); - break; - } - case NodeParam::kFloat: - { - // Widget is a FloatSlider - FloatSlider* float_slider = static_cast(sender()); - input->set_value_at_time(0, float_slider->GetValue()); - break; - } - case NodeParam::kVec2: - { - // Widgets are two FloatSliders - FloatSlider* slider = static_cast(sender()); + switch (input_->data_type()) { + // None of these inputs have applicable UI widgets + case NodeParam::kNone: + case NodeParam::kAny: + case NodeParam::kTexture: + case NodeParam::kMatrix: + case NodeParam::kSamples: + case NodeParam::kRational: + case NodeParam::kDecimal: + case NodeParam::kWholeNumber: + case NodeParam::kNumber: + case NodeParam::kString: + case NodeParam::kVector: + case NodeParam::kBuffer: + break; + case NodeParam::kInt: + { + // Widget is a IntegerSlider +// IntegerSlider* int_slider = static_cast(sender()); +// input->set_default_value(time_, int_slider->GetValue()); + break; + } + case NodeParam::kFloat: + { + // Widget is a FloatSlider + FloatSlider* float_slider = static_cast(sender()); + SetInputValue(input_, float_slider->GetValue()); + break; + } + case NodeParam::kVec2: + { + // Widgets are two FloatSliders + FloatSlider* slider = static_cast(sender()); - QVector2D val = input->get_value_at_time(0).value(); + QVector2D val = input_->get_value_at_time(0).value(); - if (slider == widgets_.at(0)) { - // Slider is X slider - val.setX(static_cast(slider->GetValue())); - } else { - // Slider is Y slider - val.setY(static_cast(slider->GetValue())); - } + if (slider == widgets_.at(0)) { + // Slider is X slider + val.setX(static_cast(slider->GetValue())); + } else { + // Slider is Y slider + val.setY(static_cast(slider->GetValue())); + } - input->set_value_at_time(0, val); - break; - } - case NodeParam::kVec3: - { - // Widgets are three FloatSliders - FloatSlider* slider = static_cast(sender()); +// input->set_default_value(0, val); + break; + } + case NodeParam::kVec3: + { + // Widgets are three FloatSliders + FloatSlider* slider = static_cast(sender()); - QVector3D val = input->get_value_at_time(0).value(); + QVector3D val = input_->get_value_at_time(0).value(); - if (slider == widgets_.at(0)) { - // Slider is X slider - val.setX(static_cast(slider->GetValue())); - } else if (slider == widgets_.at(1)) { - // Slider is Y slider - val.setY(static_cast(slider->GetValue())); - } else { - // Slider is Z slider - val.setZ(static_cast(slider->GetValue())); - } + if (slider == widgets_.at(0)) { + // Slider is X slider + val.setX(static_cast(slider->GetValue())); + } else if (slider == widgets_.at(1)) { + // Slider is Y slider + val.setY(static_cast(slider->GetValue())); + } else { + // Slider is Z slider + val.setZ(static_cast(slider->GetValue())); + } - input->set_value_at_time(0, val); - break; - } - case NodeParam::kVec4: - { - // Widgets are three FloatSliders - FloatSlider* slider = static_cast(sender()); +// input->set_default_value(0, val); + break; + } + case NodeParam::kVec4: + { + // Widgets are three FloatSliders + FloatSlider* slider = static_cast(sender()); - QVector4D val = input->get_value_at_time(0).value(); + QVector4D val = input_->get_value_at_time(0).value(); - if (slider == widgets_.at(0)) { - // Slider is X slider - val.setX(static_cast(slider->GetValue())); - } else if (slider == widgets_.at(1)) { - // Slider is Y slider - val.setY(static_cast(slider->GetValue())); - } else if (slider == widgets_.at(2)) { - // Slider is Z slider - val.setZ(static_cast(slider->GetValue())); - } else { - // Slider is W slider - val.setW(static_cast(slider->GetValue())); - } + if (slider == widgets_.at(0)) { + // Slider is X slider + val.setX(static_cast(slider->GetValue())); + } else if (slider == widgets_.at(1)) { + // Slider is Y slider + val.setY(static_cast(slider->GetValue())); + } else if (slider == widgets_.at(2)) { + // Slider is Z slider + val.setZ(static_cast(slider->GetValue())); + } else { + // Slider is W slider + val.setW(static_cast(slider->GetValue())); + } - input->set_value_at_time(0, val); - break; - } - case NodeParam::kFile: - // FIXME: File selector - break; - case NodeParam::kColor: - // FIXME: Color selector - break; - case NodeParam::kText: - { - // Sender is a QLineEdit - QLineEdit* line_edit = static_cast(sender()); - input->set_value_at_time(0, line_edit->text()); - break; - } - case NodeParam::kBoolean: - { - // Widget is a QCheckBox - QCheckBox* check_box = static_cast(sender()); - input->set_value_at_time(0, check_box->isChecked()); - break; - } - case NodeParam::kFont: - { - // Widget is a QFontComboBox - QFontComboBox* font_combobox = static_cast(sender()); - input->set_value_at_time(0, font_combobox->currentFont()); - break; - } - case NodeParam::kFootage: - { - // Widget is a FootageComboBox - FootageComboBox* footage_combobox = static_cast(sender()); - input->set_value_at_time(0, QVariant::fromValue(footage_combobox->SelectedFootage())); - break; - } - } +// input->set_default_value(0, val); + break; + } + case NodeParam::kFile: + // FIXME: File selector + break; + case NodeParam::kColor: + // FIXME: Color selector + break; + case NodeParam::kText: + { + // Sender is a QLineEdit +// QLineEdit* line_edit = static_cast(sender()); +// input->set_default_value(time_, line_edit->text()); + break; + } + case NodeParam::kBoolean: + { + // Widget is a QCheckBox +// QCheckBox* check_box = static_cast(sender()); +// input->set_default_value(0, check_box->isChecked()); + break; + } + case NodeParam::kFont: + { + // Widget is a QFontComboBox +// QFontComboBox* font_combobox = static_cast(sender()); +// input->set_default_value(time_, font_combobox->currentFont()); + break; + } + case NodeParam::kFootage: + { + // Widget is a FootageComboBox +// FootageComboBox* footage_combobox = static_cast(sender()); +// input->set_default_value(time_, QVariant::fromValue(footage_combobox->SelectedFootage())); + break; + } } } diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h index d363498f1..a33baf577 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h @@ -9,18 +9,22 @@ class NodeParamViewWidgetBridge : public QObject { Q_OBJECT public: - NodeParamViewWidgetBridge(QObject* parent); + NodeParamViewWidgetBridge(NodeInput* input, QObject* parent); - void AddInput(NodeInput* input); + void SetTime(const rational& time); const QList& widgets(); private: - QList inputs_; + void CreateWidgets(); + + void SetInputValue(NodeInput* input, const QVariant& value); + + NodeInput* input_; QList widgets_; - void CreateWidgets(); + rational time_; private slots: void WidgetCallback(); diff --git a/app/widget/timelinewidget/view/timelineviewbase.cpp b/app/widget/timelinewidget/view/timelineviewbase.cpp index e7b6d4297..e7d6b536f 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.cpp +++ b/app/widget/timelinewidget/view/timelineviewbase.cpp @@ -32,6 +32,8 @@ void TimelineViewBase::SetScale(const double &scale) viewport()->update(); end_item_->SetScale(scale_); + + ScaleChangedEvent(scale_); } void TimelineViewBase::SetTimebase(const rational &timebase) @@ -146,3 +148,8 @@ void TimelineViewBase::resizeEvent(QResizeEvent *event) UpdateSceneRect(); } + +void TimelineViewBase::ScaleChangedEvent(double scale) +{ + Q_UNUSED(scale) +} diff --git a/app/widget/timelinewidget/view/timelineviewbase.h b/app/widget/timelinewidget/view/timelineviewbase.h index d3b9c2719..25c6ed539 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.h +++ b/app/widget/timelinewidget/view/timelineviewbase.h @@ -32,6 +32,8 @@ protected: virtual void resizeEvent(QResizeEvent *event) override; + virtual void ScaleChangedEvent(double scale); + rational GetPlayheadTime(); bool PlayheadPress(QMouseEvent* event);