curveview: finished rework

This commit is contained in:
itsmattkc
2020-09-29 16:41:12 +10:00
parent 610f4c54fe
commit fec9774935
5 changed files with 71 additions and 164 deletions
+69 -123
View File
@@ -60,21 +60,6 @@ void CurveView::Clear()
lines_.clear(); lines_.clear();
} }
void CurveView::SetTrackCount(int count)
{
track_count_ = count;
track_visible_.resize(track_count_);
track_visible_.fill(true);
}
void CurveView::SetTrackVisible(int track, bool visible)
{
track_visible_[track] = visible;
SetKeyframeTrackVisible(track, visible);
}
void CurveView::ConnectInput(NodeInput *input) void CurveView::ConnectInput(NodeInput *input)
{ {
if (connected_inputs_.contains(input)) { if (connected_inputs_.contains(input)) {
@@ -87,6 +72,11 @@ void CurveView::ConnectInput(NodeInput *input)
foreach (NodeKeyframePtr key, track) { foreach (NodeKeyframePtr key, track) {
this->AddKeyframe(key); this->AddKeyframe(key);
} }
if (!keyframe_colors_.contains(&track)) {
// Generate a random color for this input
keyframe_colors_.insert(&track, QColor::fromHsv(std::rand()%360, std::rand()%255, 255));
}
} }
// Append to the list // Append to the list
@@ -175,87 +165,85 @@ void CurveView::drawBackground(QPainter *painter, const QRectF &rect)
painter->drawLines(lines); painter->drawLines(lines);
// Draw keyframe lines // Draw keyframe lines
foreach (NodeInput* input, connected_inputs_) {
if (input->is_keyframing()) {
foreach (const NodeInput::KeyframeTrack& track, input->keyframe_tracks()) {
if (!track.isEmpty()) {
painter->setPen(QPen(keyframe_colors_.value(&track), qMax(1, fontMetrics().height() / 4)));
for (int j=0;j<track_count_;j++) { QVector<QLineF> keyframe_lines;
if (!track_visible_.at(j)) {
continue;
}
painter->setPen(QPen(GetKeyframeColor(j), qMax(1, fontMetrics().height() / 4))); // Draw straight line leading to first keyframe
QList<NodeKeyframe*> keys = GetKeyframesSortedByTime(j); QPointF first_key_pos = item_map().value(track.first().get())->pos();
keyframe_lines.append(QLineF(QPointF(scene_bottom_left.x(), first_key_pos.y()), first_key_pos));
if (!keys.isEmpty()) { // Draw lines between each keyframe
QVector<QLineF> keyframe_lines; for (int i=1;i<track.size();i++) {
NodeKeyframePtr before = track.at(i-1);
NodeKeyframePtr after = track.at(i);
// Draw straight line leading to first keyframe KeyframeViewItem* before_item = item_map().value(before.get());
QPointF first_key_pos = item_map().value(keys.first())->pos(); KeyframeViewItem* after_item = item_map().value(after.get());
keyframe_lines.append(QLineF(QPointF(scene_bottom_left.x(), first_key_pos.y()), first_key_pos));
// Draw lines between each keyframe if (before->type() == NodeKeyframe::kHold) {
for (int i=1;i<keys.size();i++) { // Draw a hold keyframe (basically a right angle)
NodeKeyframe* before = keys.at(i-1); keyframe_lines.append(QLineF(before_item->pos().x(),
NodeKeyframe* after = keys.at(i); before_item->pos().y(),
after_item->pos().x(),
before_item->pos().y()));
keyframe_lines.append(QLineF(after_item->pos().x(),
before_item->pos().y(),
after_item->pos().x(),
after_item->pos().y()));
} else if (before->type() == NodeKeyframe::kBezier && after->type() == NodeKeyframe::kBezier) {
// Draw a cubic bezier
KeyframeViewItem* before_item = item_map().value(before); // Cubic beziers have two control points, so we can just use both
KeyframeViewItem* after_item = item_map().value(after); QPointF before_control_point = before_item->pos() + ScalePoint(before->bezier_control_out());
QPointF after_control_point = after_item->pos() + ScalePoint(after->bezier_control_in());
if (before->type() == NodeKeyframe::kHold) { QPainterPath path;
// Draw a hold keyframe (basically a right angle) path.moveTo(before_item->pos());
keyframe_lines.append(QLineF(before_item->pos().x(), path.cubicTo(before_control_point, after_control_point, after_item->pos());
before_item->pos().y(), painter->drawPath(path);
after_item->pos().x(),
before_item->pos().y()));
keyframe_lines.append(QLineF(after_item->pos().x(),
before_item->pos().y(),
after_item->pos().x(),
after_item->pos().y()));
} else if (before->type() == NodeKeyframe::kBezier && after->type() == NodeKeyframe::kBezier) {
// Draw a cubic bezier
// Cubic beziers have two control points, so we can just use both } else if (before->type() == NodeKeyframe::kBezier || after->type() == NodeKeyframe::kBezier) {
QPointF before_control_point = before_item->pos() + ScalePoint(before->bezier_control_out()); // Draw a quadratic bezier
QPointF after_control_point = after_item->pos() + ScalePoint(after->bezier_control_in());
QPainterPath path; // Quadratic beziers have a single control point, we just have to determine which it is
path.moveTo(before_item->pos()); QPointF key_anchor;
path.cubicTo(before_control_point, after_control_point, after_item->pos()); QPointF control_point;
painter->drawPath(path);
} else if (before->type() == NodeKeyframe::kBezier || after->type() == NodeKeyframe::kBezier) { if (before->type() == NodeKeyframe::kBezier) {
// Draw a quadratic bezier key_anchor = before_item->pos();
control_point = before->bezier_control_out();
} else {
key_anchor = after_item->pos();
control_point = after->bezier_control_in();
}
// Quadratic beziers have a single control point, we just have to determine which it is // Scale control point
QPointF key_anchor; control_point = key_anchor + ScalePoint(control_point);
QPointF control_point;
if (before->type() == NodeKeyframe::kBezier) { // Create the path from both keyframes
key_anchor = before_item->pos(); QPainterPath path;
control_point = before->bezier_control_out(); path.moveTo(before_item->pos());
} else { path.quadTo(control_point, after_item->pos());
key_anchor = after_item->pos(); painter->drawPath(path);
control_point = after->bezier_control_in();
} else {
// Linear to linear
keyframe_lines.append(QLineF(before_item->pos(), after_item->pos()));
}
} }
// Scale control point // Draw straight line leading from end keyframe
control_point = key_anchor + ScalePoint(control_point); QPointF last_key_pos = item_map().value(track.last().get())->pos();
keyframe_lines.append(QLineF(last_key_pos, QPointF(scene_top_right.x(), last_key_pos.y())));
// Create the path from both keyframes painter->drawLines(keyframe_lines);
QPainterPath path;
path.moveTo(before_item->pos());
path.quadTo(control_point, after_item->pos());
painter->drawPath(path);
} else {
// Linear to linear
keyframe_lines.append(QLineF(before_item->pos(), after_item->pos()));
} }
} }
// Draw straight line leading from end keyframe
QPointF last_key_pos = item_map().value(keys.last())->pos();
keyframe_lines.append(QLineF(last_key_pos, QPointF(scene_top_right.x(), last_key_pos.y())));
painter->drawLines(keyframe_lines);
} }
} }
@@ -318,35 +306,6 @@ void CurveView::ContextMenuEvent(Menu &m)
//QAction* reset_zoom_action = m.addAction(tr("Reset Zoom")); //QAction* reset_zoom_action = m.addAction(tr("Reset Zoom"));
} }
QList<NodeKeyframe *> CurveView::GetKeyframesSortedByTime(int track)
{
QList<NodeKeyframe *> sorted;
for (auto it=item_map().cbegin();it!=item_map().cend();it++) {
NodeKeyframe* key = it.key();
if (key->track() != track) {
continue;
}
bool inserted = false;
for (int i=0;i<sorted.size();i++) {
if (sorted.at(i)->time() > key->time()) {
sorted.insert(i, key);
inserted = true;
break;
}
}
if (!inserted) {
sorted.append(key);
}
}
return sorted;
}
qreal CurveView::GetItemYFromKeyframeValue(NodeKeyframe *key) qreal CurveView::GetItemYFromKeyframeValue(NodeKeyframe *key)
{ {
return GetItemYFromKeyframeValue(key->value().toDouble()); return GetItemYFromKeyframeValue(key->value().toDouble());
@@ -381,17 +340,6 @@ void CurveView::CreateBezierControlPoints(KeyframeViewItem* item)
connect(bezier_out_pt, &QObject::destroyed, this, &CurveView::BezierControlPointDestroyed, Qt::DirectConnection); connect(bezier_out_pt, &QObject::destroyed, this, &CurveView::BezierControlPointDestroyed, Qt::DirectConnection);
} }
QColor CurveView::GetKeyframeColor(int track) const
{
if (track_count_) {
QColor c;
c.setHsvF(static_cast<double>(track) / static_cast<double>(track_count_), 0.5, 1.0);
return c;
}
return palette().text().color();
}
void CurveView::KeyframeValueChanged() void CurveView::KeyframeValueChanged()
{ {
NodeKeyframe* key = static_cast<NodeKeyframe*>(sender()); NodeKeyframe* key = static_cast<NodeKeyframe*>(sender());
@@ -443,15 +391,13 @@ void CurveView::ZoomToFit()
return; return;
} }
QMap<NodeKeyframe *, KeyframeViewItem *>::const_iterator i;
rational min_time = RATIONAL_MAX; rational min_time = RATIONAL_MAX;
rational max_time = RATIONAL_MIN; rational max_time = RATIONAL_MIN;
double min_val = DBL_MAX; double min_val = DBL_MAX;
double max_val = DBL_MIN; double max_val = DBL_MIN;
for (i=item_map().constBegin(); i!=item_map().constEnd(); i++) { for (auto i=item_map().constBegin(); i!=item_map().constEnd(); i++) {
rational transformed_time = GetAdjustedTime(i.key()->parent()->parentNode(), rational transformed_time = GetAdjustedTime(i.key()->parent()->parentNode(),
GetTimeTarget(), GetTimeTarget(),
i.key()->time(), i.key()->time(),
@@ -479,7 +425,7 @@ void CurveView::AddKeyframe(NodeKeyframePtr key)
{ {
KeyframeViewItem* item = AddKeyframeInternal(key); KeyframeViewItem* item = AddKeyframeInternal(key);
SetItemYFromKeyframeValue(key.get(), item); SetItemYFromKeyframeValue(key.get(), item);
item->SetOverrideBrush(GetKeyframeColor(key->track())); item->SetOverrideBrush(keyframe_colors_.value(&key->parent()->keyframe_tracks().at(key->track())));
connect(key.get(), &NodeKeyframe::ValueChanged, this, &CurveView::KeyframeValueChanged); connect(key.get(), &NodeKeyframe::ValueChanged, this, &CurveView::KeyframeValueChanged);
connect(key.get(), &NodeKeyframe::TypeChanged, this, &CurveView::KeyframeTypeChanged); connect(key.get(), &NodeKeyframe::TypeChanged, this, &CurveView::KeyframeTypeChanged);
+1 -11
View File
@@ -38,10 +38,6 @@ public:
virtual void Clear() override; virtual void Clear() override;
void SetTrackCount(int count);
void SetTrackVisible(int track, bool visible);
void ConnectInput(NodeInput* input); void ConnectInput(NodeInput* input);
void DisconnectNode(Node* node); void DisconnectNode(Node* node);
@@ -67,8 +63,6 @@ protected:
virtual void ContextMenuEvent(Menu &m) override; virtual void ContextMenuEvent(Menu &m) override;
private: private:
QList<NodeKeyframe*> GetKeyframesSortedByTime(int track);
qreal GetItemYFromKeyframeValue(NodeKeyframe* key); qreal GetItemYFromKeyframeValue(NodeKeyframe* key);
qreal GetItemYFromKeyframeValue(double value); qreal GetItemYFromKeyframeValue(double value);
@@ -80,7 +74,7 @@ private:
void CreateBezierControlPoints(KeyframeViewItem *item); void CreateBezierControlPoints(KeyframeViewItem *item);
QColor GetKeyframeColor(int track) const; QMap<const NodeInput::KeyframeTrack*, QColor> keyframe_colors_;
int text_padding_; int text_padding_;
@@ -90,12 +84,8 @@ private:
QList<BezierControlPointItem*> bezier_control_points_; QList<BezierControlPointItem*> bezier_control_points_;
QVector<bool> track_visible_;
QList<NodeInput*> connected_inputs_; QList<NodeInput*> connected_inputs_;
int track_count_;
private slots: private slots:
void KeyframeValueChanged(); void KeyframeValueChanged();
@@ -109,10 +109,6 @@ KeyframeViewItem *KeyframeViewBase::AddKeyframeInternal(NodeKeyframePtr key)
item->SetScale(GetScale()); item->SetScale(GetScale());
item_map_.insert(key.get(), item); item_map_.insert(key.get(), item);
scene()->addItem(item); scene()->addItem(item);
if (hidden_tracks_.contains(key->track())) {
item->setVisible(false);
}
} }
return item; return item;
@@ -306,27 +302,6 @@ void KeyframeViewBase::TimeTargetChangedEvent(Node *target)
} }
} }
void KeyframeViewBase::SetKeyframeTrackVisible(int track, bool visible)
{
if (!visible == hidden_tracks_.contains(track)) {
return;
}
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
for (i=item_map_.constBegin(); i!=item_map_.constEnd(); i++) {
if (i.key()->track() == track) {
i.value()->setVisible(visible);
}
}
if (visible) {
hidden_tracks_.removeOne(track);
} else {
hidden_tracks_.append(track);
}
}
void KeyframeViewBase::ContextMenuEvent(Menu& m) void KeyframeViewBase::ContextMenuEvent(Menu& m)
{ {
Q_UNUSED(m) Q_UNUSED(m)
@@ -62,8 +62,6 @@ protected:
virtual void TimeTargetChangedEvent(Node*) override; virtual void TimeTargetChangedEvent(Node*) override;
void SetKeyframeTrackVisible(int track, bool visible);
virtual void ContextMenuEvent(Menu &m); virtual void ContextMenuEvent(Menu &m);
private: private:
@@ -98,8 +96,6 @@ private:
bool currently_autoselecting_; bool currently_autoselecting_;
QList<int> hidden_tracks_;
private slots: private slots:
void ShowContextMenu(); void ShowContextMenu();
+1 -1
View File
@@ -308,7 +308,7 @@ void NodeParamView::ItemRequestedTimeChanged(const rational &time)
void NodeParamView::UpdateGlobalScrollBar() void NodeParamView::UpdateGlobalScrollBar()
{ {
int height_offscreen = param_widget_container_->height() - ruler()->height(); int height_offscreen = param_widget_container_->height() - ruler()->height() + scrollbar()->height();
keyframe_view_->SetMaxScroll(height_offscreen); keyframe_view_->SetMaxScroll(height_offscreen);
vertical_scrollbar_->setRange(0, height_offscreen - keyframe_view_->height()); vertical_scrollbar_->setRange(0, height_offscreen - keyframe_view_->height());