reworked much of keyframeview for new architecture
This commit is contained in:
@@ -16,13 +16,13 @@
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/keyframeview/keyframeview.h
|
||||
widget/keyframeview/keyframeview.cpp
|
||||
widget/keyframeview/keyframeviewbase.h
|
||||
widget/keyframeview/keyframeview.h
|
||||
widget/keyframeview/keyframeviewbase.cpp
|
||||
widget/keyframeview/keyframeviewitem.h
|
||||
widget/keyframeview/keyframeviewitem.cpp
|
||||
widget/keyframeview/keyframeviewundo.h
|
||||
widget/keyframeview/keyframeviewbase.h
|
||||
widget/keyframeview/keyframeviewinputconnection.cpp
|
||||
widget/keyframeview/keyframeviewinputconnection.h
|
||||
widget/keyframeview/keyframeviewundo.cpp
|
||||
widget/keyframeview/keyframeviewundo.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
@@ -31,29 +31,10 @@ KeyframeView::KeyframeView(QWidget *parent) :
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
|
||||
void KeyframeView::SetElementY(const NodeInput &c, int y)
|
||||
{
|
||||
qreal scene_y = mapToScene(mapFromGlobal(QPoint(0, y))).y();
|
||||
|
||||
element_y_.insert(c, scene_y);
|
||||
|
||||
for (auto it=item_map().cbegin(); it!=item_map().cend(); it++) {
|
||||
if (it.key()->key_track_ref().input() == c) {
|
||||
it.value()->SetOverrideY(scene_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
void KeyframeView::SceneRectUpdateEvent(QRectF &rect)
|
||||
{
|
||||
rect.setY(0);
|
||||
rect.setHeight(max_scroll_);
|
||||
}
|
||||
|
||||
KeyframeViewItem* KeyframeView::AddKeyframe(NodeKeyframe* key)
|
||||
{
|
||||
KeyframeViewItem* item = super::AddKeyframe(key);
|
||||
item->SetOverrideY(element_y_.value(key->key_track_ref().input()));
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,19 +34,13 @@ public:
|
||||
void SetMaxScroll(int i)
|
||||
{
|
||||
max_scroll_ = i;
|
||||
UpdateSceneRect();
|
||||
}
|
||||
|
||||
void SetElementY(const NodeInput& c, int y);
|
||||
|
||||
protected:
|
||||
virtual void SceneRectUpdateEvent(QRectF& rect) override;
|
||||
|
||||
public slots:
|
||||
virtual KeyframeViewItem* AddKeyframe(NodeKeyframe* key) override;
|
||||
|
||||
private:
|
||||
QHash<NodeInput, qreal> element_y_;
|
||||
|
||||
int max_scroll_;
|
||||
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QToolTip>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
#include "dialog/keyframeproperties/keyframeproperties.h"
|
||||
#include "keyframeviewundo.h"
|
||||
#include "node/node.h"
|
||||
@@ -33,201 +34,144 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super TimeBasedView
|
||||
|
||||
KeyframeViewBase::KeyframeViewBase(QWidget *parent) :
|
||||
TimeBasedView(parent),
|
||||
super(parent),
|
||||
dragging_bezier_point_(nullptr),
|
||||
currently_autoselecting_(false),
|
||||
dragging_(false)
|
||||
dragging_(false),
|
||||
selection_manager_(this)
|
||||
{
|
||||
SetDefaultDragMode(RubberBandDrag);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(this, &KeyframeViewBase::customContextMenuRequested, this, &KeyframeViewBase::ShowContextMenu);
|
||||
connect(scene(), &QGraphicsScene::selectionChanged, this, &KeyframeViewBase::AutoSelectKeyTimeNeighbors);
|
||||
}
|
||||
|
||||
void KeyframeViewBase::Clear()
|
||||
{
|
||||
QMap<NodeKeyframe*, KeyframeViewItem*>::iterator iterator;
|
||||
|
||||
for (iterator=item_map_.begin();iterator!=item_map_.end();iterator++) {
|
||||
delete iterator.value();
|
||||
}
|
||||
|
||||
item_map_.clear();
|
||||
}
|
||||
|
||||
void KeyframeViewBase::DeleteSelected()
|
||||
{
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
|
||||
|
||||
for (i=item_map_.constBegin(); i!=item_map_.constEnd(); i++) {
|
||||
if (i.value()->isSelected()) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(i.key()));
|
||||
}
|
||||
foreach (NodeKeyframe *key, GetSelectedKeyframes()) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(key));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void KeyframeViewBase::AddKeyframesOfNode(Node *n)
|
||||
KeyframeViewBase::NodeConnections KeyframeViewBase::AddKeyframesOfNode(Node *n)
|
||||
{
|
||||
NodeConnections map;
|
||||
|
||||
foreach (const QString& i, n->inputs()) {
|
||||
AddKeyframesOfInput(n, i);
|
||||
map.insert(i, AddKeyframesOfInput(n, i));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::AddKeyframesOfInput(Node* n, const QString& input)
|
||||
KeyframeViewBase::InputConnections KeyframeViewBase::AddKeyframesOfInput(Node* n, const QString& input)
|
||||
{
|
||||
if (!n->IsInputKeyframable(input)) {
|
||||
return;
|
||||
InputConnections vec;
|
||||
|
||||
if (n->IsInputKeyframable(input)) {
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
vec.resize(arr_sz + 1);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
vec[i+1] = AddKeyframesOfElement(NodeInput(n, input, i));
|
||||
}
|
||||
}
|
||||
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
AddKeyframesOfElement(NodeInput(n, input, i));
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::AddKeyframesOfElement(const NodeInput& input)
|
||||
KeyframeViewBase::ElementConnections KeyframeViewBase::AddKeyframesOfElement(const NodeInput& input)
|
||||
{
|
||||
const QVector<NodeKeyframeTrack>& tracks = input.node()->GetKeyframeTracks(input);
|
||||
ElementConnections vec(tracks.size());
|
||||
|
||||
for (int i=0; i<tracks.size(); i++) {
|
||||
AddKeyframesOfTrack(NodeKeyframeTrackReference(input, i));
|
||||
vec[i] = AddKeyframesOfTrack(NodeKeyframeTrackReference(input, i));
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::AddKeyframesOfTrack(const NodeKeyframeTrackReference& ref)
|
||||
KeyframeViewInputConnection *KeyframeViewBase::AddKeyframesOfTrack(const NodeKeyframeTrackReference& ref)
|
||||
{
|
||||
const QVector<NodeKeyframeTrack>& tracks = ref.input().node()->GetKeyframeTracks(ref.input());
|
||||
const NodeKeyframeTrack& t = tracks.at(ref.track());
|
||||
|
||||
foreach (NodeKeyframe* key, t) {
|
||||
AddKeyframe(key);
|
||||
}
|
||||
KeyframeViewInputConnection *track = new KeyframeViewInputConnection(ref, this);
|
||||
connect(track, &KeyframeViewInputConnection::RequireUpdate, this, &KeyframeViewBase::Redraw);
|
||||
tracks_.append(track);
|
||||
Redraw();
|
||||
return track;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframesOfNode(Node *n)
|
||||
void KeyframeViewBase::RemoveKeyframesOfTrack(KeyframeViewInputConnection *connection)
|
||||
{
|
||||
foreach (const QString& i, n->inputs()) {
|
||||
RemoveKeyframesOfInput(n, i);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframesOfInput(Node* n, const QString& input)
|
||||
{
|
||||
if (!n->IsInputKeyframable(input)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
RemoveKeyframesOfElement(NodeInput(n, input, i));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframesOfElement(const NodeInput& input)
|
||||
{
|
||||
const QVector<NodeKeyframeTrack>& tracks = input.node()->GetKeyframeTracks(input);
|
||||
|
||||
for (int i=0; i<tracks.size(); i++) {
|
||||
RemoveKeyframesOfTrack(NodeKeyframeTrackReference(input, i));
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframesOfTrack(const NodeKeyframeTrackReference& ref)
|
||||
{
|
||||
const QVector<NodeKeyframeTrack>& tracks = ref.input().node()->GetKeyframeTracks(ref.input());
|
||||
const NodeKeyframeTrack& t = tracks.at(ref.track());
|
||||
|
||||
foreach (NodeKeyframe* key, t) {
|
||||
RemoveKeyframe(key);
|
||||
if (tracks_.removeOne(connection)) {
|
||||
delete connection;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::SelectAll()
|
||||
{
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
it.value()->setSelected(true);
|
||||
foreach (KeyframeViewInputConnection *track, tracks_) {
|
||||
foreach (NodeKeyframe *key, track->GetKeyframes()) {
|
||||
SelectKeyframe(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::DeselectAll()
|
||||
{
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
it.value()->setSelected(false);
|
||||
}
|
||||
selection_manager_.ClearSelection();
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframe(NodeKeyframe* key)
|
||||
void KeyframeViewBase::Clear()
|
||||
{
|
||||
KeyframeAboutToBeRemoved(key);
|
||||
|
||||
delete item_map_.take(key);
|
||||
}
|
||||
|
||||
KeyframeViewItem *KeyframeViewBase::AddKeyframe(NodeKeyframe* key)
|
||||
{
|
||||
KeyframeViewItem* item = item_map_.value(key);
|
||||
|
||||
if (!item) {
|
||||
item = new KeyframeViewItem(key);
|
||||
item->SetTimeTarget(GetTimeTarget());
|
||||
item->SetScale(GetScale());
|
||||
item_map_.insert(key, item);
|
||||
scene()->addItem(item);
|
||||
if (!tracks_.isEmpty()) {
|
||||
qDeleteAll(tracks_);
|
||||
tracks_.clear();
|
||||
Redraw();
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QGraphicsItem* item_under_cursor = itemAt(event->pos());
|
||||
NodeKeyframe *key_under_cursor = selection_manager_.MousePress(event);
|
||||
if (key_under_cursor) {
|
||||
AutoSelectKeyTimeNeighbors();
|
||||
}
|
||||
|
||||
if (HandPress(event) || (!item_under_cursor && PlayheadPress(event))) {
|
||||
BezierControlPointItem *bezier_under_cursor = dynamic_cast<BezierControlPointItem*>(itemAt(event->pos()));
|
||||
|
||||
Redraw();
|
||||
|
||||
if (HandPress(event) || (!bezier_under_cursor && !key_under_cursor && PlayheadPress(event))) {
|
||||
return;
|
||||
}
|
||||
|
||||
active_tool_ = Core::instance()->tool();
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
if (key_under_cursor || bezier_under_cursor) {
|
||||
dragging_ = true;
|
||||
drag_start_ = mapToScene(event->pos());
|
||||
|
||||
if (active_tool_ == Tool::kPointer) {
|
||||
if (item_under_cursor) {
|
||||
// Determine what type of item is under the cursor
|
||||
dragging_bezier_point_ = bezier_under_cursor;
|
||||
|
||||
dragging_ = true;
|
||||
drag_start_ = mapToScene(event->pos());
|
||||
if (dragging_bezier_point_) {
|
||||
|
||||
// Determine what type of item is under the cursor
|
||||
dragging_bezier_point_ = dynamic_cast<BezierControlPointItem*>(item_under_cursor);
|
||||
dragging_bezier_point_start_ = dragging_bezier_point_->GetCorrespondingKeyframeHandle();
|
||||
dragging_bezier_point_opposing_start_ = dragging_bezier_point_->key()->bezier_control(NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode()));
|
||||
|
||||
if (dragging_bezier_point_) {
|
||||
} else {
|
||||
|
||||
dragging_bezier_point_start_ = dragging_bezier_point_->GetCorrespondingKeyframeHandle();
|
||||
dragging_bezier_point_opposing_start_ = dragging_bezier_point_->key()->bezier_control(NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode()));
|
||||
selection_manager_.DragStart(key_under_cursor, event);
|
||||
|
||||
} else {
|
||||
|
||||
QList<QGraphicsItem*> selected_items = scene()->selectedItems();
|
||||
|
||||
selected_keys_.resize(selected_items.size());
|
||||
|
||||
initial_drag_item_ = static_cast<KeyframeViewItem*>(item_under_cursor);
|
||||
|
||||
for (int i=0;i<selected_items.size();i++) {
|
||||
KeyframeViewItem* key = static_cast<KeyframeViewItem*>(selected_items.at(i));
|
||||
|
||||
selected_keys_.replace(i, {key,
|
||||
key->x(),
|
||||
GetAdjustedTime(key->key()->parent(), GetTimeTarget(), key->key()->time(), false),
|
||||
key->key()->value().toDouble()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,11 +184,10 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
|
||||
if (dragging_) {
|
||||
// Calculate cursor difference and scale it
|
||||
QPointF mouse_diff_scaled = GetScaledCursorPos(mapToScene(event->pos()) - drag_start_);
|
||||
QPointF scene_pos = mapToScene(event->pos());
|
||||
QPointF mouse_diff_scaled = GetScaledCursorPos(scene_pos - drag_start_);
|
||||
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
// If holding shift, only move one axis
|
||||
@@ -284,15 +227,19 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event)
|
||||
QPointF bezier_pos = dragging_bezier_point_->pos() + dragging_bezier_point_->parentItem()->pos();
|
||||
emit Dragged(qRound(bezier_pos.x()), qRound(bezier_pos.y()));
|
||||
|
||||
} else if (!selected_keys_.isEmpty()) {
|
||||
} else if (selection_manager_.IsDragging()) {
|
||||
|
||||
QString tip;
|
||||
|
||||
/*
|
||||
// Validate movement - ensure no keyframe goes above its max point or below its min point
|
||||
FloatSlider::DisplayType display_type = FloatSlider::kNormal;
|
||||
|
||||
if (IsYAxisEnabled()) {
|
||||
foreach (const KeyframeItemAndTime& keypair, selected_keys_) {
|
||||
Node* node = keypair.key->key()->parent();
|
||||
const QString& input = keypair.key->key()->input();
|
||||
foreach (const KeyframeItemAndTime& keypair, dragging_keyframes_) {
|
||||
NodeKeyframe *key = keypair.key;
|
||||
Node* node = key->parent();
|
||||
const QString& input = key->input();
|
||||
double new_val = keypair.value - mouse_diff_scaled.y();
|
||||
double limited = new_val;
|
||||
|
||||
@@ -309,48 +256,37 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
Node* initial_drag_input = initial_drag_item_->key()->parent();
|
||||
const QString& initial_drag_input_id = initial_drag_item_->key()->input();
|
||||
Node* initial_drag_input = initial_drag_item_->parent();
|
||||
const QString& initial_drag_input_id = initial_drag_item_->input();
|
||||
if (initial_drag_input->HasInputProperty(initial_drag_input_id, QStringLiteral("view"))) {
|
||||
display_type = static_cast<FloatSlider::DisplayType>(initial_drag_input->GetInputProperty(initial_drag_input_id, QStringLiteral("view")).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const KeyframeItemAndTime& keypair, selected_keys_) {
|
||||
rational node_time = GetAdjustedTime(GetTimeTarget(),
|
||||
keypair.key->key()->parent(),
|
||||
CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()),
|
||||
true);
|
||||
|
||||
keypair.key->key()->set_time(node_time);
|
||||
|
||||
foreach (const KeyframeItemAndTime& keypair, dragging_keyframes_) {
|
||||
if (IsYAxisEnabled()) {
|
||||
keypair.key->key()->set_value(keypair.value - mouse_diff_scaled.y());
|
||||
key->set_value(keypair.value - mouse_diff_scaled.y());
|
||||
}
|
||||
}
|
||||
|
||||
// Show information about this keyframe
|
||||
QString tip = Timecode::time_to_timecode(initial_drag_item_->key()->time(), timebase(),
|
||||
Core::instance()->GetTimecodeDisplay(), false);
|
||||
|
||||
|
||||
if (IsYAxisEnabled()) {
|
||||
bool ok;
|
||||
double num_value = initial_drag_item_->key()->value().toDouble(&ok);
|
||||
double num_value = initial_drag_item_->value().toDouble(&ok);
|
||||
|
||||
if (ok) {
|
||||
tip.append('\n');
|
||||
tip = QStringLiteral("%1\n");
|
||||
tip.append(FloatSlider::ValueToString(num_value, display_type, 2, true));
|
||||
}
|
||||
|
||||
// Force viewport to update since Qt might try to optimize it out if the keyframe is
|
||||
// offscreen
|
||||
viewport()->update();
|
||||
}
|
||||
*/
|
||||
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(), tip);
|
||||
selection_manager_.DragMove(event, tip);
|
||||
|
||||
emit Dragged(qRound(initial_drag_item_->x()), qRound(initial_drag_item_->y()));
|
||||
Redraw();
|
||||
|
||||
emit Dragged(scene_pos.x(), scene_pos.y());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -364,8 +300,6 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
|
||||
if (dragging_) {
|
||||
if (dragging_bezier_point_) {
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
@@ -388,30 +322,19 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
|
||||
dragging_bezier_point_ = nullptr;
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
} else if (!selected_keys_.isEmpty()) {
|
||||
} else if (selection_manager_.IsDragging()) {
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
foreach (const KeyframeItemAndTime& keypair, selected_keys_) {
|
||||
NodeKeyframe* item = keypair.key->key();
|
||||
|
||||
// Commit movement
|
||||
command->add_child(new NodeParamSetKeyframeTimeCommand(item,
|
||||
item->time(),
|
||||
keypair.time));
|
||||
|
||||
// Commit value if we're setting a value
|
||||
if (IsYAxisEnabled()) {
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(item,
|
||||
item->value(),
|
||||
keypair.value));
|
||||
}
|
||||
}
|
||||
selection_manager_.DragStop(command);
|
||||
/*if (IsYAxisEnabled()) {
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(item,
|
||||
item->value(),
|
||||
keypair.value));
|
||||
}*/
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
selected_keys_.clear();
|
||||
|
||||
dragging_ = false;
|
||||
|
||||
QToolTip::hideText();
|
||||
@@ -419,31 +342,77 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
int key_sz = QtUtils::QFontMetricsWidth(fontMetrics(), "Oi");
|
||||
int key_rad = key_sz/2;
|
||||
|
||||
selection_manager_.ClearDrawnObjects();
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
painter->setPen(Qt::black);
|
||||
|
||||
foreach (KeyframeViewInputConnection *track, tracks_) {
|
||||
foreach (NodeKeyframe *key, track->GetKeyframes()) {
|
||||
QRectF key_rect(-key_rad, -key_rad, key_sz, key_sz);
|
||||
key_rect.translate(GetKeyframeSceneX(key), mapFromGlobal(QPoint(0, track->GetKeyframeY())).y());
|
||||
|
||||
if (!rect.intersects(key_rect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsKeyframeSelected(key)) {
|
||||
painter->setBrush(palette().highlight());
|
||||
} else {
|
||||
painter->setBrush(track->GetBrush());
|
||||
}
|
||||
|
||||
selection_manager_.DeclareDrawnObject(key, key_rect);
|
||||
|
||||
switch (key->type()) {
|
||||
case NodeKeyframe::kLinear:
|
||||
{
|
||||
QPointF points[] = {
|
||||
QPointF(key_rect.center().x(), key_rect.top()),
|
||||
QPointF(key_rect.right(), key_rect.center().y()),
|
||||
QPointF(key_rect.center().x(), key_rect.bottom()),
|
||||
QPointF(key_rect.left(), key_rect.center().y())
|
||||
};
|
||||
|
||||
painter->drawPolygon(points, 4);
|
||||
break;
|
||||
}
|
||||
case NodeKeyframe::kBezier:
|
||||
painter->drawEllipse(key_rect);
|
||||
break;
|
||||
case NodeKeyframe::kHold:
|
||||
painter->drawRect(key_rect);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super::drawForeground(painter, rect);
|
||||
}
|
||||
|
||||
void KeyframeViewBase::ScaleChangedEvent(const double &scale)
|
||||
{
|
||||
TimeBasedView::ScaleChangedEvent(scale);
|
||||
super::ScaleChangedEvent(scale);
|
||||
|
||||
for (auto iterator=item_map_.begin();iterator!=item_map_.end();iterator++) {
|
||||
iterator.value()->SetScale(scale);
|
||||
}
|
||||
}
|
||||
|
||||
const QMap<NodeKeyframe *, KeyframeViewItem *> &KeyframeViewBase::item_map() const
|
||||
{
|
||||
return item_map_;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::KeyframeAboutToBeRemoved(NodeKeyframe *)
|
||||
{
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void KeyframeViewBase::TimeTargetChangedEvent(Node *target)
|
||||
{
|
||||
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
for (i=item_map_.begin();i!=item_map_.end();i++) {
|
||||
i.value()->SetTimeTarget(target);
|
||||
}
|
||||
void KeyframeViewBase::TimebaseChangedEvent(const rational &timebase)
|
||||
{
|
||||
super::TimebaseChangedEvent(timebase);
|
||||
|
||||
selection_manager_.SetTimebase(timebase);
|
||||
}
|
||||
|
||||
void KeyframeViewBase::ContextMenuEvent(Menu& m)
|
||||
@@ -451,6 +420,30 @@ void KeyframeViewBase::ContextMenuEvent(Menu& m)
|
||||
Q_UNUSED(m)
|
||||
}
|
||||
|
||||
void KeyframeViewBase::SelectKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (selection_manager_.Select(key)) {
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::DeselectKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (selection_manager_.Deselect(key)) {
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
rational KeyframeViewBase::GetAdjustedKeyframeTime(NodeKeyframe *key)
|
||||
{
|
||||
return GetAdjustedTime(key->parent(), GetTimeTarget(), key->time(), false);
|
||||
}
|
||||
|
||||
double KeyframeViewBase::GetKeyframeSceneX(NodeKeyframe *key)
|
||||
{
|
||||
return TimeToScene(GetAdjustedKeyframeTime(key));
|
||||
}
|
||||
|
||||
rational KeyframeViewBase::CalculateNewTimeFromScreen(const rational &old_time, double cursor_diff)
|
||||
{
|
||||
return rational::fromDouble(old_time.toDouble() + cursor_diff);
|
||||
@@ -492,16 +485,15 @@ void KeyframeViewBase::ShowContextMenu()
|
||||
QAction* bezier_key_action = nullptr;
|
||||
QAction* hold_key_action = nullptr;
|
||||
|
||||
QList<QGraphicsItem*> items = scene()->selectedItems();
|
||||
if (!items.isEmpty()) {
|
||||
if (!GetSelectedKeyframes().isEmpty()) {
|
||||
bool all_keys_are_same_type = true;
|
||||
NodeKeyframe::Type type = static_cast<KeyframeViewItem*>(items.first())->key()->type();
|
||||
NodeKeyframe::Type type = GetSelectedKeyframes().first()->type();
|
||||
|
||||
for (int i=1;i<items.size();i++) {
|
||||
KeyframeViewItem* key_item = static_cast<KeyframeViewItem*>(items.at(i));
|
||||
KeyframeViewItem* prev_item = static_cast<KeyframeViewItem*>(items.at(i-1));
|
||||
for (int i=1;i<GetSelectedKeyframes().size();i++) {
|
||||
NodeKeyframe* key_item = GetSelectedKeyframes().at(i);
|
||||
NodeKeyframe* prev_item = GetSelectedKeyframes().at(i-1);
|
||||
|
||||
if (key_item->key()->type() != prev_item->key()->type()) {
|
||||
if (key_item->type() != prev_item->type()) {
|
||||
all_keys_are_same_type = false;
|
||||
break;
|
||||
}
|
||||
@@ -536,7 +528,7 @@ void KeyframeViewBase::ShowContextMenu()
|
||||
|
||||
ContextMenuEvent(m);
|
||||
|
||||
if (!items.isEmpty()) {
|
||||
if (!GetSelectedKeyframes().isEmpty()) {
|
||||
m.addSeparator();
|
||||
|
||||
QAction* properties_action = m.addAction(tr("P&roperties"));
|
||||
@@ -546,7 +538,7 @@ void KeyframeViewBase::ShowContextMenu()
|
||||
QAction* selected = m.exec(QCursor::pos());
|
||||
|
||||
// Process keyframe type changes
|
||||
if (!items.isEmpty()) {
|
||||
if (selected) {
|
||||
if (selected == linear_key_action
|
||||
|| selected == bezier_key_action
|
||||
|| selected == hold_key_action) {
|
||||
@@ -561,26 +553,18 @@ void KeyframeViewBase::ShowContextMenu()
|
||||
}
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
foreach (QGraphicsItem* item, items) {
|
||||
command->add_child(new KeyframeSetTypeCommand(static_cast<KeyframeViewItem*>(item)->key(),
|
||||
new_type));
|
||||
foreach (NodeKeyframe* item, GetSelectedKeyframes()) {
|
||||
command->add_child(new KeyframeSetTypeCommand(item, new_type));
|
||||
}
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::ShowKeyframePropertiesDialog()
|
||||
{
|
||||
QList<QGraphicsItem*> items = scene()->selectedItems();
|
||||
QVector<NodeKeyframe*> keys;
|
||||
|
||||
foreach (QGraphicsItem* item, items) {
|
||||
keys.append(static_cast<KeyframeViewItem*>(item)->key());
|
||||
}
|
||||
|
||||
if (!keys.isEmpty()) {
|
||||
KeyframePropertiesDialog kd(keys, timebase(), this);
|
||||
if (!GetSelectedKeyframes().isEmpty()) {
|
||||
KeyframePropertiesDialog kd(GetSelectedKeyframes(), timebase(), this);
|
||||
kd.exec();
|
||||
}
|
||||
}
|
||||
@@ -594,25 +578,15 @@ void KeyframeViewBase::AutoSelectKeyTimeNeighbors()
|
||||
// Prevents infinite loop
|
||||
currently_autoselecting_ = true;
|
||||
|
||||
QList<QGraphicsItem*> selected_items = scene()->selectedItems();
|
||||
QVector<NodeKeyframe*> copy = GetSelectedKeyframes();
|
||||
foreach (NodeKeyframe *key, copy) {
|
||||
rational key_time = key->time();
|
||||
|
||||
foreach (QGraphicsItem* g, selected_items) {
|
||||
KeyframeViewItem* key_item = static_cast<KeyframeViewItem*>(g);
|
||||
|
||||
rational key_time = key_item->key()->time();
|
||||
|
||||
QVector<NodeKeyframe*> keys = key_item->key()->parent()->GetKeyframesAtTime(key_item->key()->input(), key_time, key_item->key()->element());
|
||||
QVector<NodeKeyframe*> keys = key->parent()->GetKeyframesAtTime(key->input(), key_time, key->element());
|
||||
|
||||
foreach (NodeKeyframe* k, keys) {
|
||||
if (k == key_item->key()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure this key is not already selected
|
||||
KeyframeViewItem* item = item_map_.value(k);
|
||||
|
||||
if (item) {
|
||||
item->setSelected(true);
|
||||
if (k != key) {
|
||||
SelectKeyframe(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -620,4 +594,9 @@ void KeyframeViewBase::AutoSelectKeyTimeNeighbors()
|
||||
currently_autoselecting_ = false;
|
||||
}
|
||||
|
||||
void KeyframeViewBase::Redraw()
|
||||
{
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
#ifndef KEYFRAMEVIEWBASE_H
|
||||
#define KEYFRAMEVIEWBASE_H
|
||||
|
||||
#include "keyframeviewitem.h"
|
||||
#include "keyframeviewinputconnection.h"
|
||||
#include "node/keyframe.h"
|
||||
#include "widget/curvewidget/beziercontrolpointitem.h"
|
||||
#include "widget/menu/menu.h"
|
||||
#include "widget/timebased/timebasedview.h"
|
||||
#include "widget/timebased/timebasedviewselectionmanager.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
@@ -36,51 +37,49 @@ class KeyframeViewBase : public TimeBasedView, public TimeTargetObject
|
||||
public:
|
||||
KeyframeViewBase(QWidget* parent = nullptr);
|
||||
|
||||
virtual void Clear();
|
||||
|
||||
void DeleteSelected();
|
||||
|
||||
void AddKeyframesOfNode(Node* n);
|
||||
using ElementConnections = QVector<KeyframeViewInputConnection *>;
|
||||
using InputConnections = QVector<ElementConnections>;
|
||||
using NodeConnections = QMap<QString, InputConnections>;
|
||||
|
||||
void AddKeyframesOfInput(Node *n, const QString &input);
|
||||
NodeConnections AddKeyframesOfNode(Node* n);
|
||||
|
||||
void AddKeyframesOfElement(const NodeInput &input);
|
||||
InputConnections AddKeyframesOfInput(Node *n, const QString &input);
|
||||
|
||||
void AddKeyframesOfTrack(const NodeKeyframeTrackReference &ref);
|
||||
ElementConnections AddKeyframesOfElement(const NodeInput &input);
|
||||
|
||||
void RemoveKeyframesOfNode(Node* n);
|
||||
KeyframeViewInputConnection *AddKeyframesOfTrack(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void RemoveKeyframesOfInput(Node *n, const QString &input);
|
||||
|
||||
void RemoveKeyframesOfElement(const NodeInput &input);
|
||||
|
||||
void RemoveKeyframesOfTrack(const NodeKeyframeTrackReference &ref);
|
||||
void RemoveKeyframesOfTrack(KeyframeViewInputConnection *connection);
|
||||
|
||||
void SelectAll();
|
||||
|
||||
void DeselectAll();
|
||||
|
||||
void Clear();
|
||||
|
||||
const QVector<NodeKeyframe*> &GetSelectedKeyframes() const
|
||||
{
|
||||
return selection_manager_.GetSelectedObjects();
|
||||
}
|
||||
|
||||
signals:
|
||||
void Dragged(int current_x, int current_y);
|
||||
|
||||
public slots:
|
||||
virtual KeyframeViewItem* AddKeyframe(NodeKeyframe* key);
|
||||
|
||||
void RemoveKeyframe(NodeKeyframe* key);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void ScaleChangedEvent(const double& scale) override;
|
||||
|
||||
const QMap<NodeKeyframe*, KeyframeViewItem*>& item_map() const;
|
||||
|
||||
virtual void KeyframeAboutToBeRemoved(NodeKeyframe* key);
|
||||
|
||||
virtual void TimeTargetChangedEvent(Node*) override;
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational &timebase) override;
|
||||
|
||||
virtual void ContextMenuEvent(Menu &m);
|
||||
|
||||
bool IsDragging() const
|
||||
@@ -88,6 +87,19 @@ protected:
|
||||
return dragging_;
|
||||
}
|
||||
|
||||
void SelectKeyframe(NodeKeyframe *key);
|
||||
|
||||
void DeselectKeyframe(NodeKeyframe *key);
|
||||
|
||||
bool IsKeyframeSelected(NodeKeyframe *key) const
|
||||
{
|
||||
return selection_manager_.IsSelected(key);
|
||||
}
|
||||
|
||||
rational GetAdjustedKeyframeTime(NodeKeyframe *key);
|
||||
|
||||
double GetKeyframeSceneX(NodeKeyframe *key);
|
||||
|
||||
private:
|
||||
rational CalculateNewTimeFromScreen(const rational& old_time, double cursor_diff);
|
||||
|
||||
@@ -97,31 +109,20 @@ private:
|
||||
|
||||
QPointF GetScaledCursorPos(const QPointF &cursor_pos);
|
||||
|
||||
struct KeyframeItemAndTime {
|
||||
KeyframeViewItem* key;
|
||||
qreal item_x;
|
||||
rational time;
|
||||
double value;
|
||||
};
|
||||
|
||||
QMap<NodeKeyframe*, KeyframeViewItem*> item_map_;
|
||||
|
||||
Tool::Item active_tool_;
|
||||
|
||||
QPointF drag_start_;
|
||||
|
||||
BezierControlPointItem* dragging_bezier_point_;
|
||||
QPointF dragging_bezier_point_start_;
|
||||
QPointF dragging_bezier_point_opposing_start_;
|
||||
|
||||
KeyframeViewItem* initial_drag_item_;
|
||||
|
||||
QVector<KeyframeItemAndTime> selected_keys_;
|
||||
QVector<KeyframeViewInputConnection*> tracks_;
|
||||
|
||||
bool currently_autoselecting_;
|
||||
|
||||
bool dragging_;
|
||||
|
||||
TimeBasedViewSelectionManager<NodeKeyframe> selection_manager_;
|
||||
|
||||
private slots:
|
||||
void ShowContextMenu();
|
||||
|
||||
@@ -129,6 +130,8 @@ private slots:
|
||||
|
||||
void AutoSelectKeyTimeNeighbors();
|
||||
|
||||
void Redraw();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "keyframeviewinputconnection.h"
|
||||
|
||||
#include "keyframeview.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
KeyframeViewInputConnection::KeyframeViewInputConnection(const NodeKeyframeTrackReference &input, KeyframeViewBase *parent) :
|
||||
QObject(parent),
|
||||
keyframe_view_(parent),
|
||||
input_(input),
|
||||
y_(0),
|
||||
y_behavior_(kSingleRow),
|
||||
brush_(Qt::white)
|
||||
{
|
||||
Node *n = input.input().node();
|
||||
|
||||
connect(n, &Node::KeyframeAdded, this, &KeyframeViewInputConnection::AddKeyframe);
|
||||
connect(n, &Node::KeyframeRemoved, this, &KeyframeViewInputConnection::RemoveKeyframe);
|
||||
connect(n, &Node::KeyframeTimeChanged, this, &KeyframeViewInputConnection::RequireUpdate);
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetKeyframeY(int y)
|
||||
{
|
||||
if (y_ != y) {
|
||||
y_ = y;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetYBehavior(YBehavior e)
|
||||
{
|
||||
if (y_behavior_ != e) {
|
||||
y_behavior_ = e;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetBrush(const QBrush &brush)
|
||||
{
|
||||
if (brush_ != brush) {
|
||||
brush_ = brush;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::AddKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::RemoveKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef KEYFRAMEVIEWINPUTCONNECTION_H
|
||||
#define KEYFRAMEVIEWINPUTCONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "node/param.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class KeyframeViewBase;
|
||||
|
||||
class KeyframeViewInputConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeViewInputConnection(const NodeKeyframeTrackReference &input, KeyframeViewBase *parent);
|
||||
|
||||
const int &GetKeyframeY() const
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
|
||||
void SetKeyframeY(int y);
|
||||
|
||||
enum YBehavior {
|
||||
kSingleRow,
|
||||
kValueIsHeight
|
||||
};
|
||||
|
||||
void SetYBehavior(YBehavior e);
|
||||
|
||||
const QVector<NodeKeyframe*> GetKeyframes() const
|
||||
{
|
||||
return input_.input().node()->GetKeyframeTracks(input_.input()).at(input_.track());
|
||||
}
|
||||
|
||||
const QBrush &GetBrush() const
|
||||
{
|
||||
return brush_;
|
||||
}
|
||||
|
||||
void SetBrush(const QBrush &brush);
|
||||
|
||||
signals:
|
||||
void RequireUpdate();
|
||||
|
||||
private:
|
||||
KeyframeViewBase *keyframe_view_;
|
||||
|
||||
NodeKeyframeTrackReference input_;
|
||||
|
||||
int y_;
|
||||
|
||||
YBehavior y_behavior_;
|
||||
|
||||
QBrush brush_;
|
||||
|
||||
private slots:
|
||||
void AddKeyframe(NodeKeyframe *key);
|
||||
|
||||
void RemoveKeyframe(NodeKeyframe *key);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KEYFRAMEVIEWINPUTCONNECTION_H
|
||||
@@ -1,129 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "keyframeviewitem.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
KeyframeViewItem::KeyframeViewItem(NodeKeyframe* key, QGraphicsItem *parent) :
|
||||
QGraphicsRectItem(parent),
|
||||
key_(key),
|
||||
scale_(1.0),
|
||||
vert_center_(0),
|
||||
use_custom_brush_(false)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
|
||||
connect(key, &NodeKeyframe::TimeChanged, this, &KeyframeViewItem::UpdatePos);
|
||||
connect(key, &NodeKeyframe::TypeChanged, this, &KeyframeViewItem::Redraw);
|
||||
|
||||
int keyframe_size = QtUtils::QFontMetricsWidth(qApp->fontMetrics(), "Oi");
|
||||
int half_sz = keyframe_size/2;
|
||||
setRect(-half_sz, -half_sz, keyframe_size, keyframe_size);
|
||||
|
||||
UpdatePos();
|
||||
|
||||
// Set default brush
|
||||
}
|
||||
|
||||
void KeyframeViewItem::SetOverrideY(qreal vertical_center)
|
||||
{
|
||||
vert_center_ = vertical_center;
|
||||
UpdatePos();
|
||||
}
|
||||
|
||||
void KeyframeViewItem::SetScale(double scale)
|
||||
{
|
||||
scale_ = scale;
|
||||
UpdatePos();
|
||||
}
|
||||
|
||||
void KeyframeViewItem::SetOverrideBrush(const QBrush &b)
|
||||
{
|
||||
use_custom_brush_ = true;
|
||||
setBrush(b);
|
||||
}
|
||||
|
||||
NodeKeyframe* KeyframeViewItem::key() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
void KeyframeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
painter->setPen(Qt::black);
|
||||
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
painter->setBrush(widget->palette().highlight());
|
||||
} else if (use_custom_brush_) {
|
||||
painter->setBrush(brush());
|
||||
} else {
|
||||
painter->setBrush(widget->palette().text());
|
||||
}
|
||||
|
||||
switch (key_->type()) {
|
||||
case NodeKeyframe::kLinear:
|
||||
{
|
||||
QPointF points[] = {
|
||||
QPointF(rect().center().x(), rect().top()),
|
||||
QPointF(rect().right(), rect().center().y()),
|
||||
QPointF(rect().center().x(), rect().bottom()),
|
||||
QPointF(rect().left(), rect().center().y())
|
||||
};
|
||||
|
||||
painter->drawPolygon(points, 4);
|
||||
break;
|
||||
}
|
||||
case NodeKeyframe::kBezier:
|
||||
painter->drawEllipse(rect());
|
||||
break;
|
||||
case NodeKeyframe::kHold:
|
||||
painter->drawRect(rect());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewItem::TimeTargetChangedEvent(Node *)
|
||||
{
|
||||
UpdatePos();
|
||||
}
|
||||
|
||||
void KeyframeViewItem::UpdatePos()
|
||||
{
|
||||
rational adjusted = GetAdjustedTime(key_->parent(), GetTimeTarget(), key_->time(), false);
|
||||
|
||||
setPos(adjusted.toDouble() * scale_, vert_center_);
|
||||
}
|
||||
|
||||
void KeyframeViewItem::Redraw()
|
||||
{
|
||||
QGraphicsItem::update();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef KEYFRAMEVIEWITEM_H
|
||||
#define KEYFRAMEVIEWITEM_H
|
||||
|
||||
#include <QGraphicsRectItem>
|
||||
|
||||
#include "node/keyframe.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class KeyframeViewItem : public QObject, public QGraphicsRectItem, public TimeTargetObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeViewItem(NodeKeyframe* key, QGraphicsItem *parent = nullptr);
|
||||
|
||||
void SetOverrideY(qreal vertical_center);
|
||||
|
||||
void SetScale(double scale);
|
||||
|
||||
void SetOverrideBrush(const QBrush& b);
|
||||
|
||||
NodeKeyframe* key() const;
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
|
||||
virtual void TimeTargetChangedEvent(Node* ) override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
|
||||
double scale_;
|
||||
|
||||
qreal vert_center_;
|
||||
|
||||
bool use_custom_brush_;
|
||||
|
||||
private slots:
|
||||
void UpdatePos();
|
||||
|
||||
void Redraw();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KEYFRAMEVIEWITEM_H
|
||||
Reference in New Issue
Block a user