diff --git a/app/widget/curvewidget/curveview.cpp b/app/widget/curvewidget/curveview.cpp index b2dee4cff..9aa0e3750 100644 --- a/app/widget/curvewidget/curveview.cpp +++ b/app/widget/curvewidget/curveview.cpp @@ -102,6 +102,34 @@ void CurveView::DisconnectInput(NodeInput *input, int element, int track) connected_inputs_.removeOne(ref); } +void CurveView::SelectKeyframesOf(NodeInput *input, int element, int track) +{ + DeselectAll(); + + for (auto it=item_map().cbegin(); it!=item_map().cend(); it++) { + if (it.key()->parent() == input + && it.key()->element() == element + && it.key()->track() == track) { + it.value()->setSelected(true); + } + } +} + +void CurveView::ZoomToFitInput(NodeInput *input, int element, int track) +{ + QList keys; + + for (auto it=item_map().cbegin(); it!=item_map().cend(); it++) { + if (it.key()->parent() == input + && it.key()->element() == element + && it.key()->track() == track) { + keys.append(it.key()); + } + } + + ZoomToFitInternal(keys); +} + void CurveView::drawBackground(QPainter *painter, const QRectF &rect) { if (timebase().isNull()) { @@ -293,7 +321,48 @@ void CurveView::ContextMenuEvent(Menu &m) QAction* zoom_fit_action = m.addAction(tr("Zoom to Fit")); connect(zoom_fit_action, &QAction::triggered, this, &CurveView::ZoomToFit); - //QAction* reset_zoom_action = m.addAction(tr("Reset Zoom")); + QAction* zoom_fit_selected_action = m.addAction(tr("Zoom to Fit Selected")); + connect(zoom_fit_selected_action, &QAction::triggered, this, &CurveView::ZoomToFitSelected); + + QAction* reset_zoom_action = m.addAction(tr("Reset Zoom")); + connect(reset_zoom_action, &QAction::triggered, this, &CurveView::ResetZoom); +} + +void CurveView::ZoomToFitInternal(const QList &keys) +{ + if (keys.isEmpty()) { + // Prevent scaling to DBL_MIN/DBL_MAX + return; + } + + rational min_time = RATIONAL_MAX; + rational max_time = RATIONAL_MIN; + + double min_val = DBL_MAX; + double max_val = DBL_MIN; + + for (auto i=item_map().constBegin(); i!=item_map().constEnd(); i++) { + rational transformed_time = GetAdjustedTime(i.key()->parent()->parent(), + GetTimeTarget(), + i.key()->time(), + false); + + min_time = qMin(transformed_time, min_time); + max_time = qMax(transformed_time, max_time); + + min_val = qMin(i.key()->value().toDouble(), min_val); + max_val = qMax(i.key()->value().toDouble(), max_val); + } + + double time_range = max_time.toDouble() - min_time.toDouble(); + double new_x_scale = CalculateScaleFromDimensions(this->width(), time_range); + double new_y_scale = CalculateScaleFromDimensions(this->height(), max_val - min_val); + + emit ScaleChanged(new_x_scale); + SetYScale(new_y_scale); + + horizontalScrollBar()->setValue(TimeToScene(min_time) - CalculatePaddingFromDimensionScale(this->width())); + verticalScrollBar()->setValue(GetItemYFromKeyframeValue(max_val) - CalculatePaddingFromDimensionScale(this->height())); } qreal CurveView::GetItemYFromKeyframeValue(NodeKeyframe *key) @@ -377,39 +446,26 @@ void CurveView::BezierControlPointDestroyed() void CurveView::ZoomToFit() { - if (item_map().isEmpty()) { - // Prevent scaling to DBL_MIN/DBL_MAX - return; + ZoomToFitInternal(item_map().keys()); +} + +void CurveView::ZoomToFitSelected() +{ + QList selected_keys; + + for (auto it=item_map().cbegin(); it!=item_map().cend(); it++) { + if (it.value()->isSelected()) { + selected_keys.append(it.key()); + } } - rational min_time = RATIONAL_MAX; - rational max_time = RATIONAL_MIN; + ZoomToFitInternal(selected_keys); +} - double min_val = DBL_MAX; - double max_val = DBL_MIN; - - for (auto i=item_map().constBegin(); i!=item_map().constEnd(); i++) { - rational transformed_time = GetAdjustedTime(i.key()->parent()->parent(), - GetTimeTarget(), - i.key()->time(), - false); - - min_time = qMin(transformed_time, min_time); - max_time = qMax(transformed_time, max_time); - - min_val = qMin(i.key()->value().toDouble(), min_val); - max_val = qMax(i.key()->value().toDouble(), max_val); - } - - double time_range = max_time.toDouble() - min_time.toDouble(); - double new_x_scale = CalculateScaleFromDimensions(this->width(), time_range); - double new_y_scale = CalculateScaleFromDimensions(this->height(), max_val - min_val); - - emit ScaleChanged(new_x_scale); - SetYScale(new_y_scale); - - horizontalScrollBar()->setValue(TimeToScene(min_time) - CalculatePaddingFromDimensionScale(this->width())); - verticalScrollBar()->setValue(GetItemYFromKeyframeValue(max_val) - CalculatePaddingFromDimensionScale(this->height())); +void CurveView::ResetZoom() +{ + SetScale(1.0); + SetYScale(1.0); } void CurveView::AddKeyframe(NodeKeyframe* key) diff --git a/app/widget/curvewidget/curveview.h b/app/widget/curvewidget/curveview.h index 72c0e01e4..8df0136fb 100644 --- a/app/widget/curvewidget/curveview.h +++ b/app/widget/curvewidget/curveview.h @@ -42,11 +42,19 @@ public: void DisconnectInput(NodeInput* input, int element, int track); + void SelectKeyframesOf(NodeInput* input, int element, int track); + + void ZoomToFitInput(NodeInput* input, int element, int track); + public slots: void AddKeyframe(NodeKeyframe* key); void ZoomToFit(); + void ZoomToFitSelected(); + + void ResetZoom(); + protected: virtual void drawBackground(QPainter* painter, const QRectF& rect) override; @@ -61,6 +69,8 @@ protected: virtual void ContextMenuEvent(Menu &m) override; private: + void ZoomToFitInternal(const QList &keys); + qreal GetItemYFromKeyframeValue(NodeKeyframe* key); qreal GetItemYFromKeyframeValue(double value); diff --git a/app/widget/curvewidget/curvewidget.cpp b/app/widget/curvewidget/curvewidget.cpp index 847b57001..0589876d6 100644 --- a/app/widget/curvewidget/curvewidget.cpp +++ b/app/widget/curvewidget/curvewidget.cpp @@ -48,6 +48,7 @@ CurveWidget::CurveWidget(QWidget *parent) : connect(tree_view_, &NodeTreeView::NodeEnableChanged, this, &CurveWidget::NodeEnabledChanged); connect(tree_view_, &NodeTreeView::InputEnableChanged, this, &CurveWidget::InputEnabledChanged); connect(tree_view_, &NodeTreeView::InputSelectionChanged, this, &CurveWidget::InputSelectionChanged); + connect(tree_view_, &NodeTreeView::InputDoubleClicked, this, &CurveWidget::InputDoubleClicked); splitter->addWidget(tree_view_); QWidget* workarea = new QWidget(); @@ -359,9 +360,16 @@ void CurveWidget::RemoveKeyframe(NodeKeyframe *key) void CurveWidget::InputSelectionChanged(NodeInput *input, int element, int track) { - Q_UNUSED(track) - key_control_->SetInput(input, element); + + if (input) { + view_->SelectKeyframesOf(input, element, track); + } +} + +void CurveWidget::InputDoubleClicked(NodeInput *input, int element, int track) +{ + view_->ZoomToFitInput(input, element, track); } } diff --git a/app/widget/curvewidget/curvewidget.h b/app/widget/curvewidget/curvewidget.h index 0011546bc..3f310f746 100644 --- a/app/widget/curvewidget/curvewidget.h +++ b/app/widget/curvewidget/curvewidget.h @@ -104,6 +104,8 @@ private slots: void InputSelectionChanged(NodeInput* input, int element, int track); + void InputDoubleClicked(NodeInput* input, int element, int track); + }; } diff --git a/app/widget/nodetreeview/nodetreeview.cpp b/app/widget/nodetreeview/nodetreeview.cpp index 41a6a3c87..467a022d0 100644 --- a/app/widget/nodetreeview/nodetreeview.cpp +++ b/app/widget/nodetreeview/nodetreeview.cpp @@ -82,11 +82,43 @@ void NodeTreeView::changeEvent(QEvent *e) } } +void NodeTreeView::mouseDoubleClickEvent(QMouseEvent *e) +{ + QTreeWidget::mouseDoubleClickEvent(e); + + NodeInput::KeyframeTrackReference ref = GetSelectedInput(); + + if (ref.input) { + emit InputDoubleClicked(ref.input, ref.element, ref.track); + } +} + void NodeTreeView::Retranslate() { setHeaderLabel(tr("Nodes")); } +NodeInput::KeyframeTrackReference NodeTreeView::GetSelectedInput() +{ + QList sel = selectedItems(); + + NodeInput* selected_input = nullptr; + int selected_element = -1; + int selected_track = -1; + + if (!sel.isEmpty()) { + QTreeWidgetItem* item = sel.first(); + + if (item->data(0, kItemType).toInt() == kItemTypeInput) { + selected_input = reinterpret_cast(item->data(0, kItemPointer).value()); + selected_element = item->data(0, kItemElement).toInt(); + selected_track = item->data(0, kItemTrack).toInt(); + } + } + + return {selected_input, selected_element, selected_track}; +} + QTreeWidgetItem* NodeTreeView::CreateItem(QTreeWidgetItem *parent, NodeInput *input, int element, int track) { QTreeWidgetItem* input_item = new QTreeWidgetItem(parent); @@ -166,23 +198,9 @@ void NodeTreeView::ItemCheckStateChanged(QTreeWidgetItem *item, int column) void NodeTreeView::SelectionChanged() { - QList sel = selectedItems(); + NodeInput::KeyframeTrackReference ref = GetSelectedInput(); - NodeInput* selected_input = nullptr; - int selected_element = -1; - int selected_track = -1; - - if (!sel.isEmpty()) { - QTreeWidgetItem* item = sel.first(); - - if (item->data(0, kItemType).toInt() == kItemTypeInput) { - selected_input = reinterpret_cast(item->data(0, kItemPointer).value()); - selected_element = item->data(0, kItemElement).toInt(); - selected_track = item->data(0, kItemTrack).toInt(); - } - } - - emit InputSelectionChanged(selected_input, selected_element, selected_track); + emit InputSelectionChanged(ref.input, ref.element, ref.track); } } diff --git a/app/widget/nodetreeview/nodetreeview.h b/app/widget/nodetreeview/nodetreeview.h index 9da7979fa..b91187ede 100644 --- a/app/widget/nodetreeview/nodetreeview.h +++ b/app/widget/nodetreeview/nodetreeview.h @@ -37,12 +37,18 @@ signals: void InputSelectionChanged(NodeInput* input, int element, int track); + void InputDoubleClicked(NodeInput* input, int element, int track); + protected: virtual void changeEvent(QEvent* e) override; + virtual void mouseDoubleClickEvent(QMouseEvent* e) override; + private: void Retranslate(); + NodeInput::KeyframeTrackReference GetSelectedInput(); + QTreeWidgetItem *CreateItem(QTreeWidgetItem* parent, NodeInput* input, int element, int track); enum ItemType {