curveview: finished rework
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
Reference in New Issue
Block a user