keyframeview: implemented transforming keyframe times to and from sequence time

Since the node graph can have transform cross nodes, input keyframes may occur
at a different times requiring transforming between sequence time and media
time. This commit implements such a mechanism in all UI classes that need it.
This commit is contained in:
itsmattkc
2020-03-26 19:17:46 +11:00
parent 592171cc31
commit 3399227b3a
27 changed files with 389 additions and 144 deletions
+4 -3
View File
@@ -540,15 +540,16 @@ QList<TimeRange> Node::TransformTimeTo(const TimeRange &time, Node *target, Node
foreach (NodeInput* input, inputs) {
if (input->IsConnected()) {
TimeRange input_adjustment = InputTimeAdjustment(input, time);
Node* connected = input->get_connected_node();
if (input->get_connected_node() == target) {
if (connected == target) {
// We found the target, no need to keep traversing
if (!paths_found.contains(input_adjustment)) {
paths_found.append(input_adjustment);
}
} else {
// We did NOT find the target, traverse this
paths_found.append(TransformTimeTo(input_adjustment, target, direction));
paths_found.append(connected->TransformTimeTo(input_adjustment, target, direction));
}
}
}
@@ -567,7 +568,7 @@ QList<TimeRange> Node::TransformTimeTo(const TimeRange &time, Node *target, Node
if (input_node == target) {
paths_found.append(output_adjustment);
} else {
paths_found.append(TransformTimeTo(output_adjustment, target, direction));
paths_found.append(input_node->TransformTimeTo(output_adjustment, target, direction));
}
}
}
+5 -5
View File
@@ -221,7 +221,7 @@ public:
/**
* @brief Find a node of a certain type that this Node outputs to
*/
const T* FindOutputNode() const;
T* FindOutputNode();
/**
* @brief Convert a pointer to a value that can be sent between NodeParams
@@ -416,7 +416,7 @@ T* Node::ValueToPtr(const QVariant &ptr)
}
template<class T>
const Node* FindOutputNodeInternal(const Node* n) {
Node* FindOutputNodeInternal(Node* n) {
foreach (NodeEdgePtr edge, n->output()->edges()) {
Node* connected = edge->input()->parentNode();
T* cast_test = dynamic_cast<T*>(connected);
@@ -424,7 +424,7 @@ const Node* FindOutputNodeInternal(const Node* n) {
if (cast_test) {
return cast_test;
} else {
const Node* drill_test = FindOutputNodeInternal<T>(connected);
Node* drill_test = FindOutputNodeInternal<T>(connected);
if (drill_test) {
return drill_test;
}
@@ -435,9 +435,9 @@ const Node* FindOutputNodeInternal(const Node* n) {
}
template<class T>
const T* Node::FindOutputNode() const
T* Node::FindOutputNode()
{
return static_cast<const T*>(FindOutputNodeInternal<T>(this));
return static_cast<T*>(FindOutputNodeInternal<T>(this));
}
#endif // NODE_H
+5
View File
@@ -18,6 +18,11 @@ void CurvePanel::SetInput(NodeInput *input)
static_cast<CurveWidget*>(GetTimeBasedWidget())->SetInput(input);
}
void CurvePanel::SetTimeTarget(Node *target)
{
static_cast<CurveWidget*>(GetTimeBasedWidget())->SetTimeTarget(target);
}
void CurvePanel::IncreaseTrackHeight()
{
CurveWidget* c = static_cast<CurveWidget*>(GetTimeBasedWidget());
+2
View File
@@ -13,6 +13,8 @@ public:
public slots:
void SetInput(NodeInput* input);
void SetTimeTarget(Node* target);
virtual void IncreaseTrackHeight() override;
virtual void DecreaseTrackHeight() override;
+23 -17
View File
@@ -26,7 +26,8 @@ PanelManager* PanelManager::instance_ = nullptr;
PanelManager::PanelManager(QObject *parent) :
QObject(parent),
locked_(false)
locked_(false),
last_focused_panel_(nullptr)
{
}
@@ -106,26 +107,31 @@ void PanelManager::FocusChanged(QWidget *old, QWidget *now)
// Use dynamic_cast to test if this object is a PanelWidget
panel_cast_test = dynamic_cast<PanelWidget*>(parent);
if (panel_cast_test != nullptr) {
// If so, bump this to the top of the focus history
if (panel_cast_test) {
int panel_index = focus_history_.indexOf(panel_cast_test);
if (last_focused_panel_ != panel_cast_test) {
// If so, bump this to the top of the focus history
int panel_index = focus_history_.indexOf(panel_cast_test);
// Force the old panel to repaint (if there is one) so it hides its border
if (!focus_history_.isEmpty()) {
focus_history_.first()->SetBorderVisible(false);
// Disable highlight border on old panel
if (!focus_history_.isEmpty()) {
focus_history_.first()->SetBorderVisible(false);
}
// Enable new border's highlight
panel_cast_test->SetBorderVisible(true);
// If it's not in the focus history, prepend it, otherwise move it
if (panel_index == -1) {
focus_history_.prepend(panel_cast_test);
} else {
focus_history_.move(panel_index, 0);
}
last_focused_panel_ = panel_cast_test;
emit FocusedPanelChanged(panel_cast_test);
}
// If it's not in the focus history, prepend it, otherwise move it
if (panel_index == -1) {
focus_history_.prepend(panel_cast_test);
} else {
focus_history_.move(panel_index, 0);
}
// Force the panel to repaint so it shows a border
panel_cast_test->SetBorderVisible(true);
break;
}
+14
View File
@@ -131,6 +131,12 @@ public slots:
*/
void SetPanelsLocked(bool locked);
signals:
/**
* @brief Signal emitted when the currently focused panel changes
*/
void FocusedPanelChanged(PanelWidget* panel);
private:
/**
* @brief History array for traversing through (see MostRecentlyFocused())
@@ -146,6 +152,14 @@ private:
* @brief PanelManager singleton instance
*/
static PanelManager* instance_;
/**
* @brief The last panel that was focused
*
* Stored to prevent emitting FocusedPanelChanged() multiple times for the same panel
*/
PanelWidget* last_focused_panel_;
};
template<class T>
+1
View File
@@ -28,6 +28,7 @@ ParamPanel::ParamPanel(QWidget* parent) :
NodeParamView* view = new NodeParamView();
connect(view, &NodeParamView::SelectedInputChanged, this, &ParamPanel::SelectedInputChanged);
connect(view, &NodeParamView::TimeTargetChanged, this, &ParamPanel::TimeTargetChanged);
SetTimeBasedWidget(view);
Retranslate();
+2
View File
@@ -36,6 +36,8 @@ public slots:
signals:
void SelectedInputChanged(NodeInput* input);
void TimeTargetChanged(Node* node);
protected:
virtual void Retranslate() override;
+13
View File
@@ -107,6 +107,8 @@ void CurveWidget::SetInput(NodeInput *input)
if (input_) {
bridge_ = new NodeParamViewWidgetBridge(input_, this);
bridge_->SetTimeTarget(GetTimeTarget());
for (int i=0;i<bridge_->widgets().size();i++) {
// Insert between two stretches to center the widget
widget_bridge_layout_->insertWidget(2 + i, bridge_->widgets().at(i));
@@ -165,6 +167,17 @@ void CurveWidget::ScaleChangedEvent(const double &scale)
view_->SetScale(scale);
}
void CurveWidget::TimeTargetChangedEvent(Node *target)
{
key_control_->SetTimeTarget(target);
view_->SetTimeTarget(target);
if (bridge_) {
bridge_->SetTimeTarget(target);
}
}
void CurveWidget::UpdateInputLabel()
{
if (input_) {
+3 -1
View File
@@ -11,7 +11,7 @@
#include "widget/nodeparamview/nodeparamviewwidgetbridge.h"
#include "widget/timebased/timebased.h"
class CurveWidget : public TimeBasedWidget
class CurveWidget : public TimeBasedWidget, public TimeTargetObject
{
Q_OBJECT
public:
@@ -31,6 +31,8 @@ protected:
virtual void TimebaseChangedEvent(const rational &) override;
virtual void ScaleChangedEvent(const double &) override;
virtual void TimeTargetChangedEvent(Node* target) override;
private:
void UpdateInputLabel();
+2
View File
@@ -24,5 +24,7 @@ set(OLIVE_SOURCES
widget/keyframeview/keyframeviewitem.cpp
widget/keyframeview/keyframeviewundo.h
widget/keyframeview/keyframeviewundo.cpp
widget/keyframeview/timetargetobject.h
widget/keyframeview/timetargetobject.cpp
PARENT_SCOPE
)
+29 -4
View File
@@ -59,6 +59,7 @@ void KeyframeViewBase::RemoveKeyframe(NodeKeyframePtr key)
KeyframeViewItem *KeyframeViewBase::AddKeyframeInternal(NodeKeyframePtr key)
{
KeyframeViewItem* item = new KeyframeViewItem(key);
item->SetTimeTarget(GetTimeTarget());
item->SetScale(GetScale());
item_map_.insert(key.get(), item);
scene()->addItem(item);
@@ -87,9 +88,12 @@ void KeyframeViewBase::mousePressEvent(QMouseEvent *event)
dragging_bezier_point_ = dynamic_cast<BezierControlPointItem*>(item_under_cursor);
if (dragging_bezier_point_) {
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()));
} else {
QList<QGraphicsItem*> selected_items = scene()->selectedItems();
selected_keys_.resize(selected_items.size());
@@ -97,8 +101,12 @@ void KeyframeViewBase::mousePressEvent(QMouseEvent *event)
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(), key->key()->time(), key->key()->value().toDouble()});
selected_keys_.replace(i, {key,
key->x(),
GetAdjustedTime(key->key()->parent()->parentNode(), GetTimeTarget(), key->key()->time(), NodeParam::kOutput),
key->key()->value().toDouble()});
}
}
}
}
@@ -128,7 +136,12 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event)
input_parent->blockSignals(true);
keypair.key->key()->set_time(CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()));
rational node_time = GetAdjustedTime(GetTimeTarget(),
keypair.key->key()->parent()->parentNode(),
CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()),
NodeParam::kInput);
keypair.key->key()->set_time(node_time);
if (y_axis_enabled_) {
keypair.key->key()->set_value(keypair.value - mouse_diff_scaled.y());
@@ -174,7 +187,10 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
keypair.key->key()->parent()->blockSignals(true);
// Calculate the new time for this keyframe
rational new_time = CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x());
rational node_time = GetAdjustedTime(GetTimeTarget(),
keypair.key->key()->parent()->parentNode(),
CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()),
NodeParam::kInput);
@@ -185,7 +201,7 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event)
// the signalling once the undo command is pushed.
item->key()->set_time(keypair.time);
new NodeParamSetKeyframeTimeCommand(item->key(),
new_time,
node_time,
keypair.time,
command);
@@ -234,6 +250,15 @@ void KeyframeViewBase::KeyframeAboutToBeRemoved(NodeKeyframe *)
{
}
void KeyframeViewBase::TimeTargetChangedEvent(Node *target)
{
QMap<NodeKeyframe*, KeyframeViewItem*>::const_iterator i;
for (i=item_map_.begin();i!=item_map_.end();i++) {
i.value()->SetTimeTarget(target);
}
}
void KeyframeViewBase::SetYAxisEnabled(bool e)
{
y_axis_enabled_ = e;
+4 -1
View File
@@ -3,10 +3,11 @@
#include "keyframeviewitem.h"
#include "node/keyframe.h"
#include "timetargetobject.h"
#include "widget/curvewidget/beziercontrolpointitem.h"
#include "widget/timelinewidget/view/timelineviewbase.h"
class KeyframeViewBase : public TimelineViewBase
class KeyframeViewBase : public TimelineViewBase, public TimeTargetObject
{
Q_OBJECT
public:
@@ -35,6 +36,8 @@ protected:
virtual void KeyframeAboutToBeRemoved(NodeKeyframe* key);
virtual void TimeTargetChangedEvent(Node*) override;
void SetYAxisEnabled(bool e);
private:
+8 -2
View File
@@ -6,6 +6,7 @@
#include <QWidget>
#include "common/qtutils.h"
#include "node/input.h"
KeyframeViewItem::KeyframeViewItem(NodeKeyframePtr key, QGraphicsItem *parent) :
QGraphicsRectItem(parent),
@@ -76,11 +77,16 @@ void KeyframeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
}
}
void KeyframeViewItem::TimeTargetChangedEvent(Node *)
{
UpdatePos();
}
void KeyframeViewItem::UpdatePos()
{
double x_center = key_->time().toDouble() * scale_;
rational adjusted = GetAdjustedTime(key_->parent()->parentNode(), GetTimeTarget(), key_->time(), NodeParam::kOutput);
setPos(x_center, vert_center_);
setPos(adjusted.toDouble() * scale_, vert_center_);
}
void KeyframeViewItem::Redraw()
+4 -1
View File
@@ -4,8 +4,9 @@
#include <QGraphicsRectItem>
#include "node/keyframe.h"
#include "timetargetobject.h"
class KeyframeViewItem : public QObject, public QGraphicsRectItem
class KeyframeViewItem : public QObject, public QGraphicsRectItem, public TimeTargetObject
{
Q_OBJECT
public:
@@ -20,6 +21,8 @@ public:
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
virtual void TimeTargetChangedEvent(Node* ) override;
private:
NodeKeyframePtr key_;
@@ -0,0 +1,59 @@
#include "timetargetobject.h"
TimeTargetObject::TimeTargetObject() :
time_target_(nullptr),
path_index_(0)
{
}
Node *TimeTargetObject::GetTimeTarget() const
{
return time_target_;
}
void TimeTargetObject::SetTimeTarget(Node *target)
{
time_target_ = target;
TimeTargetChangedEvent(time_target_);
}
void TimeTargetObject::SetPathIndex(int index)
{
path_index_ = index;
}
rational TimeTargetObject::GetAdjustedTime(Node* from, Node* to, const rational &r, NodeParam::Type direction) const
{
if (!from || !to) {
return r;
}
return GetAdjustedTime(from, to, TimeRange(r, r), direction).in();
}
TimeRange TimeTargetObject::GetAdjustedTime(Node* from, Node* to, const TimeRange &r, NodeParam::Type direction) const
{
if (!from || !to) {
return r;
}
QList<TimeRange> adjusted = from->TransformTimeTo(r, to, direction);
if (adjusted.isEmpty()) {
return r;
}
return adjusted.at(path_index_);
}
/*int TimeTargetObject::GetNumberOfPathAdjustments(Node* from, NodeParam::Type direction) const
{
if (!time_target_) {
return 0;
}
QList<TimeRange> adjusted = from->TransformTimeTo(TimeRange(), time_target_, direction);
return adjusted.size();
}*/
@@ -0,0 +1,31 @@
#ifndef TIMETARGETOBJECT_H
#define TIMETARGETOBJECT_H
#include "node/node.h"
class TimeTargetObject
{
public:
TimeTargetObject();
Node* GetTimeTarget() const;
void SetTimeTarget(Node* target);
void SetPathIndex(int index);
rational GetAdjustedTime(Node* from, Node* to, const rational& r, NodeParam::Type direction) const;
TimeRange GetAdjustedTime(Node* from, Node* to, const TimeRange& r, NodeParam::Type direction) const;
//int GetNumberOfPathAdjustments(Node* from, NodeParam::Type direction) const;
protected:
virtual void TimeTargetChangedEvent(Node* ){}
private:
Node* time_target_;
int path_index_;
};
#endif // TIMETARGETOBJECT_H
+11 -8
View File
@@ -123,6 +123,7 @@ void NodeParamView::SetNodes(QList<Node *> nodes)
delete item;
}
items_.clear();
emit TimeTargetChanged(nullptr);
// Reset keyframe view
SetTimebase(rational());
@@ -149,21 +150,23 @@ void NodeParamView::SetNodes(QList<Node *> nodes)
}
if (!nodes_.isEmpty()) {
const ViewerOutput* viewer = nodes_.first()->FindOutputNode<ViewerOutput>();
ViewerOutput* viewer = nodes_.first()->FindOutputNode<ViewerOutput>();
if (viewer) {
SetTimebase(viewer->video_params().time_base());
// Set viewer as a time target
keyframe_view_->SetTimeTarget(viewer);
foreach (NodeParamViewItem* item, items_) {
item->SetTimeTarget(viewer);
}
emit TimeTargetChanged(viewer);
}
}
SetTime(0);
// FIXME: Test code only!
if (nodes_.isEmpty()) {
emit SelectedInputChanged(nullptr);
} else {
emit SelectedInputChanged(static_cast<NodeInput*>(nodes_.first()->parameters().first()));
}
}
void NodeParamView::resizeEvent(QResizeEvent *event)
+2
View File
@@ -41,6 +41,8 @@ public:
signals:
void SelectedInputChanged(NodeInput* input);
void TimeTargetChanged(Node* target);
protected:
virtual void resizeEvent(QResizeEvent *event) override;
@@ -73,6 +73,17 @@ NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
SetupUI();
}
void NodeParamViewItem::SetTimeTarget(Node *target)
{
foreach (NodeParamViewKeyframeControl* control, key_control_list_) {
control->SetTimeTarget(target);
}
foreach (NodeParamViewWidgetBridge* bridge, bridges_) {
bridge->SetTimeTarget(target);
}
}
void NodeParamViewItem::SetTime(const rational &time)
{
time_ = time;
@@ -46,6 +46,8 @@ class NodeParamViewItem : public QWidget
public:
NodeParamViewItem(Node* node, QWidget* parent = nullptr);
void SetTimeTarget(Node* target);
void SetTime(const rational& time);
public slots:
@@ -102,6 +102,16 @@ void NodeParamViewKeyframeControl::SetButtonsEnabled(bool e)
enable_key_btn_->setEnabled(e);
}
rational NodeParamViewKeyframeControl::GetCurrentTimeAsNodeTime() const
{
return GetAdjustedTime(GetTimeTarget(), input_->parentNode(), time_, NodeParam::kInput);
}
rational NodeParamViewKeyframeControl::ConvertToViewerTime(const rational &r) const
{
return GetAdjustedTime(input_->parentNode(), GetTimeTarget(), r, NodeParam::kOutput);
}
void NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable(bool e)
{
prev_key_btn_->setVisible(e);
@@ -111,16 +121,18 @@ void NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable(bool e)
void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
{
QList<NodeKeyframePtr> keys = input_->get_keyframe_at_time(time_);
rational node_time = GetCurrentTimeAsNodeTime();
QList<NodeKeyframePtr> keys = input_->get_keyframe_at_time(node_time);
QUndoCommand* command = new QUndoCommand();
if (e && keys.isEmpty()) {
// Add a keyframe here (one for each track)
for (int i=0;i<input_->get_number_of_keyframe_tracks();i++) {
NodeKeyframePtr key = NodeKeyframe::Create(time_,
input_->get_value_at_time_for_track(time_, i),
input_->get_best_keyframe_type_for_time(time_, i),
NodeKeyframePtr key = NodeKeyframe::Create(node_time,
input_->get_value_at_time_for_track(node_time, i),
input_->get_best_keyframe_type_for_time(node_time, i),
i);
new NodeParamInsertKeyframeCommand(input_, key, command);
@@ -134,7 +146,7 @@ void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
// If this was the last keyframe on this track, set the standard value to the value at this time too
new NodeParamSetStandardValueCommand(input_,
key->track(),
input_->get_value_at_time_for_track(time_, key->track()),
input_->get_value_at_time_for_track(node_time, key->track()),
command);
}
}
@@ -152,26 +164,36 @@ void NodeParamViewKeyframeControl::UpdateState()
NodeKeyframePtr earliest_key = input_->get_earliest_keyframe();
NodeKeyframePtr latest_key = input_->get_latest_keyframe();
prev_key_btn_->setEnabled(earliest_key && time_ > earliest_key->time());
next_key_btn_->setEnabled(latest_key && time_ < latest_key->time());
toggle_key_btn_->setChecked(input_->has_keyframe_at_time(time_));
rational node_time = GetCurrentTimeAsNodeTime();
prev_key_btn_->setEnabled(earliest_key && node_time > earliest_key->time());
next_key_btn_->setEnabled(latest_key && node_time < latest_key->time());
toggle_key_btn_->setChecked(input_->has_keyframe_at_time(node_time));
}
void NodeParamViewKeyframeControl::GoToPreviousKey()
{
NodeKeyframePtr previous_key = input_->get_closest_keyframe_before_time(time_);
rational node_time = GetCurrentTimeAsNodeTime();
NodeKeyframePtr previous_key = input_->get_closest_keyframe_before_time(node_time);
if (previous_key) {
emit RequestSetTime(previous_key->time());
rational key_time = ConvertToViewerTime(previous_key->time());
emit RequestSetTime(key_time);
}
}
void NodeParamViewKeyframeControl::GoToNextKey()
{
NodeKeyframePtr next_key = input_->get_closest_keyframe_after_time(time_);
rational node_time = GetCurrentTimeAsNodeTime();
NodeKeyframePtr next_key = input_->get_closest_keyframe_after_time(node_time);
if (next_key) {
emit RequestSetTime(next_key->time());
rational key_time = ConvertToViewerTime(next_key->time());
emit RequestSetTime(key_time);
}
}
@@ -192,7 +214,7 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
QVector<QVariant> key_vals = input_->get_split_standard_value();
for (int i=0;i<key_vals.size();i++) {
NodeKeyframePtr key = NodeKeyframe::Create(time_,
NodeKeyframePtr key = NodeKeyframe::Create(GetCurrentTimeAsNodeTime(),
key_vals.at(i),
NodeKeyframe::kDefaultType,
i);
@@ -207,7 +229,7 @@ void NodeParamViewKeyframeControl::KeyframeEnableChanged(bool e)
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
// Store value at this time, we'll set this as the persistent value later
QVector<QVariant> stored_vals = input_->get_split_values_at_time(time_);
QVector<QVariant> stored_vals = input_->get_split_values_at_time(GetCurrentTimeAsNodeTime());
// Delete all keyframes
foreach (const NodeInput::KeyframeTrack& track, input_->keyframe_tracks()) {
@@ -5,8 +5,9 @@
#include <QWidget>
#include "node/input.h"
#include "widget/keyframeview/timetargetobject.h"
class NodeParamViewKeyframeControl : public QWidget
class NodeParamViewKeyframeControl : public QWidget, public TimeTargetObject
{
Q_OBJECT
public:
@@ -26,6 +27,10 @@ private:
void SetButtonsEnabled(bool e);
rational GetCurrentTimeAsNodeTime() const;
rational ConvertToViewerTime(const rational& r) const;
QPushButton* prev_key_btn_;
QPushButton* toggle_key_btn_;
QPushButton* next_key_btn_;
@@ -36,80 +36,10 @@ void NodeParamViewWidgetBridge::SetTime(const rational &time)
return;
}
// 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::kNumber:
case NodeParam::kString:
case NodeParam::kBuffer:
case NodeParam::kVector:
break;
case NodeParam::kInt:
static_cast<IntegerSlider*>(widgets_.first())->SetValue(input_->get_value_at_time(time).toLongLong());
break;
case NodeParam::kFloat:
static_cast<FloatSlider*>(widgets_.first())->SetValue(input_->get_value_at_time(time).toDouble());
break;
case NodeParam::kVec2:
{
QVector2D vec2 = input_->get_value_at_time(time).value<QVector2D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec2.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec2.y()));
break;
}
case NodeParam::kVec3:
{
QVector3D vec3 = input_->get_value_at_time(time).value<QVector3D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec3.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec3.y()));
static_cast<FloatSlider*>(widgets_.at(2))->SetValue(static_cast<double>(vec3.z()));
break;
}
case NodeParam::kVec4:
{
QVector4D vec4 = input_->get_value_at_time(time).value<QVector4D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec4.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec4.y()));
static_cast<FloatSlider*>(widgets_.at(2))->SetValue(static_cast<double>(vec4.z()));
static_cast<FloatSlider*>(widgets_.at(3))->SetValue(static_cast<double>(vec4.w()));
break;
}
case NodeParam::kFile:
// FIXME: File selector
break;
case NodeParam::kColor:
// FIXME: Color selector
break;
case NodeParam::kText:
{
static_cast<QLineEdit*>(widgets_.first())->setText(input_->get_value_at_time(time).toString());
break;
}
case NodeParam::kBoolean:
static_cast<QCheckBox*>(widgets_.first())->setChecked(input_->get_value_at_time(time).toBool());
break;
case NodeParam::kFont:
{
// FIXME: Implement this
break;
}
case NodeParam::kFootage:
static_cast<FootageComboBox*>(widgets_.first())->SetFootage(input_->get_value_at_time(time).value<StreamPtr>());
break;
}
UpdateWidgetValues();
}
const QList<QWidget *> &NodeParamViewWidgetBridge::widgets()
const QList<QWidget *> &NodeParamViewWidgetBridge::widgets() const
{
return widgets_;
}
@@ -207,18 +137,20 @@ void NodeParamViewWidgetBridge::CreateWidgets()
void NodeParamViewWidgetBridge::SetInputValue(const QVariant &value, int track)
{
rational node_time = GetCurrentTimeAsNodeTime();
QUndoCommand* command = new QUndoCommand();
if (input_->is_keyframing()) {
NodeKeyframePtr existing_key = input_->get_keyframe_at_time_on_track(time_, track);
NodeKeyframePtr existing_key = input_->get_keyframe_at_time_on_track(node_time, track);
if (existing_key) {
new NodeParamSetKeyframeValueCommand(existing_key, value, command);
} else {
// No existing key, create a new one
NodeKeyframePtr new_key = NodeKeyframe::Create(time_,
NodeKeyframePtr new_key = NodeKeyframe::Create(node_time,
value,
input_->get_best_keyframe_type_for_time(time_, track),
input_->get_best_keyframe_type_for_time(node_time, track),
track);
new NodeParamInsertKeyframeCommand(input_, new_key, command);
@@ -232,6 +164,8 @@ void NodeParamViewWidgetBridge::SetInputValue(const QVariant &value, int track)
void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant &value)
{
rational node_time = GetCurrentTimeAsNodeTime();
int slider_track = widgets_.indexOf(slider);
if (slider->IsDragging()) {
@@ -244,17 +178,17 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant
dragging_ = true;
// Cache current value
drag_old_value_ = input_->get_value_at_time_for_track(time_, slider_track);
drag_old_value_ = input_->get_value_at_time_for_track(node_time, slider_track);
// Determine whether we are creating a keyframe or not
if (input_->is_keyframing()) {
dragging_keyframe_ = input_->get_keyframe_at_time_on_track(time_, slider_track);
dragging_keyframe_ = input_->get_keyframe_at_time_on_track(node_time, slider_track);
drag_created_keyframe_ = !dragging_keyframe_;
if (drag_created_keyframe_) {
dragging_keyframe_ = NodeKeyframe::Create(time_,
dragging_keyframe_ = NodeKeyframe::Create(node_time,
value,
input_->get_best_keyframe_type_for_time(time_, slider_track),
input_->get_best_keyframe_type_for_time(node_time, slider_track),
slider_track);
input_->insert_keyframe(dragging_keyframe_);
@@ -406,11 +340,93 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
}
}
void NodeParamViewWidgetBridge::UpdateWidgetValues()
{
rational node_time = GetCurrentTimeAsNodeTime();
// 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::kNumber:
case NodeParam::kString:
case NodeParam::kBuffer:
case NodeParam::kVector:
break;
case NodeParam::kInt:
static_cast<IntegerSlider*>(widgets_.first())->SetValue(input_->get_value_at_time(node_time).toLongLong());
break;
case NodeParam::kFloat:
static_cast<FloatSlider*>(widgets_.first())->SetValue(input_->get_value_at_time(node_time).toDouble());
break;
case NodeParam::kVec2:
{
QVector2D vec2 = input_->get_value_at_time(node_time).value<QVector2D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec2.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec2.y()));
break;
}
case NodeParam::kVec3:
{
QVector3D vec3 = input_->get_value_at_time(node_time).value<QVector3D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec3.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec3.y()));
static_cast<FloatSlider*>(widgets_.at(2))->SetValue(static_cast<double>(vec3.z()));
break;
}
case NodeParam::kVec4:
{
QVector4D vec4 = input_->get_value_at_time(node_time).value<QVector4D>();
static_cast<FloatSlider*>(widgets_.at(0))->SetValue(static_cast<double>(vec4.x()));
static_cast<FloatSlider*>(widgets_.at(1))->SetValue(static_cast<double>(vec4.y()));
static_cast<FloatSlider*>(widgets_.at(2))->SetValue(static_cast<double>(vec4.z()));
static_cast<FloatSlider*>(widgets_.at(3))->SetValue(static_cast<double>(vec4.w()));
break;
}
case NodeParam::kFile:
// FIXME: File selector
break;
case NodeParam::kColor:
// FIXME: Color selector
break;
case NodeParam::kText:
{
static_cast<QLineEdit*>(widgets_.first())->setText(input_->get_value_at_time(node_time).toString());
break;
}
case NodeParam::kBoolean:
static_cast<QCheckBox*>(widgets_.first())->setChecked(input_->get_value_at_time(node_time).toBool());
break;
case NodeParam::kFont:
{
// FIXME: Implement this
break;
}
case NodeParam::kFootage:
static_cast<FootageComboBox*>(widgets_.first())->SetFootage(input_->get_value_at_time(node_time).value<StreamPtr>());
break;
}
}
rational NodeParamViewWidgetBridge::GetCurrentTimeAsNodeTime() const
{
return GetAdjustedTime(GetTimeTarget(), input_->parentNode(), time_, NodeParam::kInput);
}
void NodeParamViewWidgetBridge::InputValueChanged(const rational &start, const rational &end)
{
if (!dragging_ && start <= time_ && end >= time_) {
// We'll need to update the widgets because the values have changed on our current time
SetTime(time_);
UpdateWidgetValues();
}
}
@@ -4,9 +4,10 @@
#include <QObject>
#include "node/input.h"
#include "widget/keyframeview/timetargetobject.h"
#include "widget/slider/sliderbase.h"
class NodeParamViewWidgetBridge : public QObject
class NodeParamViewWidgetBridge : public QObject, public TimeTargetObject
{
Q_OBJECT
public:
@@ -14,7 +15,7 @@ public:
void SetTime(const rational& time);
const QList<QWidget*>& widgets();
const QList<QWidget*>& widgets() const;
private:
void CreateWidgets();
@@ -25,6 +26,10 @@ private:
void CreateSliders(int count);
void UpdateWidgetValues();
rational GetCurrentTimeAsNodeTime() const;
NodeInput* input_;
QList<QWidget*> widgets_;
+8 -4
View File
@@ -84,6 +84,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(node_panel_, &NodePanel::SelectionChanged, param_panel_, &ParamPanel::SetNodes);
connect(param_panel_, &ParamPanel::SelectedInputChanged, curve_panel_, &CurvePanel::SetInput);
connect(param_panel_, &ParamPanel::TimebaseChanged, curve_panel_, &CurvePanel::SetTimebase);
connect(param_panel_, &ParamPanel::TimeTargetChanged, curve_panel_, &CurvePanel::SetTimeTarget);
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, curve_panel_, &CurvePanel::SetTime);
connect(param_panel_, &ParamPanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
@@ -91,6 +92,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(curve_panel_, &CurvePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
connect(curve_panel_, &CurvePanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
connect(PanelManager::instance(), &PanelManager::FocusedPanelChanged, this, &MainWindow::FocusedPanelChanged);
sequence_viewer_panel_->ConnectTimeBasedPanel(param_panel_);
sequence_viewer_panel_->ConnectTimeBasedPanel(curve_panel_);
@@ -253,7 +256,6 @@ TimelinePanel* MainWindow::AppendTimelinePanel()
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
connect(panel, &TimelinePanel::TimeChanged, curve_panel_, &CurvePanel::SetTime);
connect(panel, &TimelinePanel::SelectionChanged, node_panel_, &NodePanel::SelectWithDependencies);
connect(panel, &TimelinePanel::visibilityChanged, this, &MainWindow::TimelineFocusedSlot);
connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTime);
connect(curve_panel_, &CurvePanel::TimeChanged, panel, &TimelinePanel::SetTime);
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTime);
@@ -278,10 +280,12 @@ void MainWindow::TimelineFocused(TimelinePanel* panel)
node_panel_->SetGraph(seq);
}
void MainWindow::TimelineFocusedSlot(bool visible)
void MainWindow::FocusedPanelChanged(PanelWidget *panel)
{
if (visible) {
TimelineFocused(static_cast<TimelinePanel*>(sender()));
TimelinePanel* timeline = dynamic_cast<TimelinePanel*>(panel);
if (timeline) {
TimelineFocused(timeline);
}
}
+1 -1
View File
@@ -80,7 +80,7 @@ private:
CurvePanel* curve_panel_;
private slots:
void TimelineFocusedSlot(bool visible);
void FocusedPanelChanged(PanelWidget* panel);
};