Merge branch 'master' into rational_slider

This commit is contained in:
ThomasWilshaw
2021-04-12 10:42:26 +01:00
committed by GitHub
80 changed files with 1266 additions and 491 deletions
@@ -37,8 +37,10 @@ void HandMovableView::ApplicationToolChanged(Tool::Item tool)
{
if (tool == Tool::kHand) {
setDragMode(ScrollHandDrag);
setInteractive(false);
} else {
setDragMode(default_drag_mode_);
setInteractive(true);
}
ToolChangedEvent(tool);
@@ -51,6 +53,7 @@ bool HandMovableView::HandPress(QMouseEvent *event)
dragging_hand_ = true;
setDragMode(ScrollHandDrag);
setInteractive(false);
// Transform mouse event to act like the left button is pressed
QMouseEvent transformed(event->type(),
@@ -94,6 +97,7 @@ bool HandMovableView::HandRelease(QMouseEvent *event)
QGraphicsView::mouseReleaseEvent(&transformed);
setInteractive(true);
setDragMode(pre_hand_drag_mode_);
dragging_hand_ = false;
+4 -3
View File
@@ -262,7 +262,7 @@ void NodeParamView::UpdateItemTime(const int64_t &timestamp)
void NodeParamView::QueueKeyframePositionUpdate()
{
QMetaObject::invokeMethod(this, "UpdateElementY", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, &NodeParamView::UpdateElementY, Qt::QueuedConnection);
}
void NodeParamView::SignalNodeOrder()
@@ -310,8 +310,9 @@ void NodeParamView::AddNode(Node *n)
connect(item, &NodeParamViewItem::dockLocationChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::dockLocationChanged, this, &NodeParamView::SignalNodeOrder);
connect(item, &NodeParamViewItem::PinToggled, this, &NodeParamView::PinNode);
connect(item, &NodeParamViewItem::ExpandedChanged, this, &NodeParamView::UpdateElementY);
connect(item, &NodeParamViewItem::ArrayExpandedChanged, this, &NodeParamView::UpdateElementY);
connect(item, &NodeParamViewItem::ArrayExpandedChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::ExpandedChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::Moved, this, &NodeParamView::QueueKeyframePositionUpdate);
// Set time target
item->SetTimeTarget(GetTimeTarget());
+42 -8
View File
@@ -36,8 +36,13 @@ const int NodeParamViewItemBody::kKeyControlColumn = 10;
const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn-1;
const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn-1;
// 0 is for the array collapse button, 1 is for the main label, widgets start at 2
const int NodeParamViewItemBody::kWidgetStartColumn = 2;
#define super QDockWidget
NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
QDockWidget(parent),
super(parent),
node_(node),
highlighted_(false)
{
@@ -97,12 +102,12 @@ void NodeParamViewItem::changeEvent(QEvent *e)
Retranslate();
}
QWidget::changeEvent(e);
super::changeEvent(e);
}
void NodeParamViewItem::paintEvent(QPaintEvent *event)
{
QDockWidget::paintEvent(event);
super::paintEvent(event);
// Draw border if focused
if (highlighted_) {
@@ -113,6 +118,13 @@ void NodeParamViewItem::paintEvent(QPaintEvent *event)
}
}
void NodeParamViewItem::moveEvent(QMoveEvent *event)
{
super::moveEvent(event);
emit Moved();
}
void NodeParamViewItem::Retranslate()
{
node_->Retranslate();
@@ -257,6 +269,10 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
InputUI ui_objects;
// Store layout and row
ui_objects.layout = layout;
ui_objects.row = row;
// Add descriptor label
ui_objects.main_label = new QLabel();
@@ -299,23 +315,24 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
// Create a widget/input bridge for this input
ui_objects.widget_bridge = new NodeParamViewWidgetBridge(NodeInput(node, input, element), this);
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::WidgetsRecreated, this, &NodeParamViewItemBody::ReplaceWidgets);
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked, this, &NodeParamViewItemBody::ToggleArrayExpanded);
// 0 is for the array collapse button, 1 is for the main label, widgets start at 2
const int widget_start = 2;
// Place widgets into layout
PlaceWidgetsFromBridge(layout, ui_objects.widget_bridge, row);
// Add widgets for this parameter to the layout
for (int i=0; i<ui_objects.widget_bridge->widgets().size(); i++) {
QWidget* w = ui_objects.widget_bridge->widgets().at(i);
layout->addWidget(w, row, i+widget_start);
layout->addWidget(w, row, i+kWidgetStartColumn);
}
if (node->IsInputConnectable(input)) {
// Create clickable label used when an input is connected
ui_objects.connected_label = new NodeParamViewConnectedLabel(input_ref);
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode);
layout->addWidget(ui_objects.connected_label, row, widget_start);
layout->addWidget(ui_objects.connected_label, row, kWidgetStartColumn);
}
// Add keyframe control to this layout if parameter is keyframable
@@ -414,6 +431,16 @@ void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput& input)
}
}
void NodeParamViewItemBody::PlaceWidgetsFromBridge(QGridLayout* layout, NodeParamViewWidgetBridge *bridge, int row)
{
// Add widgets for this parameter to the layout
for (int i=0; i<bridge->widgets().size(); i++) {
QWidget* w = bridge->widgets().at(i);
layout->addWidget(w, row, i+kWidgetStartColumn);
}
}
void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
{
const NodeInputPair& input = array_collapse_buttons_.key(static_cast<CollapseButton*>(sender()));
@@ -510,12 +537,19 @@ void NodeParamViewItemBody::ToggleArrayExpanded()
}
}
void NodeParamViewItemBody::SetTimebase(const rational& timebase) {
void NodeParamViewItemBody::SetTimebase(const rational& timebase)
{
foreach (const InputUI& ui_obj, input_ui_map_) {
ui_obj.widget_bridge->SetTimebase(timebase);
}
}
void NodeParamViewItemBody::ReplaceWidgets(const NodeInput &input)
{
InputUI ui = input_ui_map_.value(input);
PlaceWidgetsFromBridge(ui.layout, ui.widget_bridge, ui.row);
}
NodeParamViewItemBody::InputUI::InputUI() :
main_label(nullptr),
widget_bridge(nullptr),
@@ -99,6 +99,8 @@ private:
void UpdateUIForEdgeConnection(const NodeInput &input);
void PlaceWidgetsFromBridge(QGridLayout *layout, NodeParamViewWidgetBridge* bridge, int row);
struct InputUI {
InputUI();
@@ -106,6 +108,8 @@ private:
NodeParamViewWidgetBridge* widget_bridge;
NodeParamViewConnectedLabel* connected_label;
NodeParamViewKeyframeControl* key_control;
QGridLayout* layout;
int row;
NodeParamViewArrayButton* array_insert_btn;
NodeParamViewArrayButton* array_remove_btn;
@@ -134,6 +138,8 @@ private:
static const int kArrayInsertColumn;
static const int kArrayRemoveColumn;
static const int kWidgetStartColumn;
private slots:
void EdgeChanged(const NodeOutput &output, const NodeInput &input);
@@ -149,6 +155,8 @@ private slots:
void ToggleArrayExpanded();
void ReplaceWidgets(const NodeInput& input);
};
class NodeParamViewItem : public QDockWidget
@@ -192,11 +200,15 @@ signals:
void ArrayExpandedChanged(bool e);
void Moved();
protected:
virtual void changeEvent(QEvent *e) override;
virtual void paintEvent(QPaintEvent *event) override;
virtual void moveEvent(QMoveEvent *event) override;
private:
NodeParamViewItemTitleBar* title_bar_;
@@ -50,6 +50,7 @@ NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(const NodeInput &input, QOb
connect(input_.node(), &Node::ValueChanged, this, &NodeParamViewWidgetBridge::InputValueChanged);
connect(input_.node(), &Node::InputPropertyChanged, this, &NodeParamViewWidgetBridge::PropertyChanged);
connect(input_.node(), &Node::InputDataTypeChanged, this, &NodeParamViewWidgetBridge::InputDataTypeChanged);
}
void NodeParamViewWidgetBridge::SetTime(const rational &time)
@@ -212,14 +213,25 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
command->add_child(new NodeParamSetKeyframeValueCommand(existing_key, value));
} else {
// No existing key, create a new one
NodeKeyframe* new_key = new NodeKeyframe(node_time,
value,
input_.node()->GetBestKeyframeTypeForTimeOnTrack(NodeKeyframeTrackReference(input_, track), node_time),
track,
input_.element(),
input_.input());
int nb_tracks = NodeValue::get_number_of_keyframe_tracks(input_.node()->GetInputDataType(input_.input()));
for (int i=0; i<nb_tracks; i++) {
QVariant track_value;
command->add_child(new NodeParamInsertKeyframeCommand(input_.node(), new_key));
if (i == track) {
track_value = value;
} else {
track_value = input_.node()->GetValueAtTime(input_.input(), node_time, input_.element());
}
NodeKeyframe* new_key = new NodeKeyframe(node_time,
track_value,
input_.node()->GetBestKeyframeTypeForTimeOnTrack(NodeKeyframeTrackReference(input_, i), node_time),
i,
input_.element(),
input_.input());
command->add_child(new NodeParamInsertKeyframeCommand(input_.node(), new_key));
}
}
} else {
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(input_, track), value));
@@ -767,6 +779,22 @@ void NodeParamViewWidgetBridge::PropertyChanged(const QString& input, const QStr
}
}
void NodeParamViewWidgetBridge::InputDataTypeChanged(const QString &input, NodeValue::Type type)
{
Q_UNUSED(type)
if (input == this->input_.input()) {
// Delete all widgets
qDeleteAll(widgets_);
widgets_.clear();
// Create new widgets
CreateWidgets();
// Signal that widgets are new
emit WidgetsRecreated(input_);
}
}
bool NodeParamViewScrollBlocker::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched)
@@ -54,6 +54,8 @@ public:
signals:
void ArrayWidgetDoubleClicked();
void WidgetsRecreated(const NodeInput& input);
private:
void CreateWidgets();
@@ -87,6 +89,8 @@ private slots:
void PropertyChanged(const QString &input, const QString& key, const QVariant& value);
void InputDataTypeChanged(const QString& input, NodeValue::Type type);
};
}
+29 -5
View File
@@ -298,11 +298,11 @@ void NodeView::Paste()
QVector<Node*> pasted_nodes = PasteNodesFromClipboard(graph_, command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
if (!pasted_nodes.isEmpty()) {
AttachNodesToCursor(pasted_nodes);
command->add_child(new NodeViewAttachNodesToCursor(this, pasted_nodes));
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
}
void NodeView::Duplicate()
@@ -321,9 +321,11 @@ void NodeView::Duplicate()
QVector<Node*> duplicated_nodes = Node::CopyDependencyGraph(selected, command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
if (!duplicated_nodes.isEmpty()) {
command->add_child(new NodeViewAttachNodesToCursor(this, duplicated_nodes));
}
AttachNodesToCursor(duplicated_nodes);
Core::instance()->undo_stack()->pushIfHasChildren(command);
}
void NodeView::SetColorLabel(int index)
@@ -839,4 +841,26 @@ void NodeView::ZoomFromKeyboard(double multiplier)
ZoomIntoCursorPosition(multiplier, cursor_pos);
}
NodeView::NodeViewAttachNodesToCursor::NodeViewAttachNodesToCursor(NodeView *view, const QVector<Node *> &nodes) :
view_(view),
nodes_(nodes)
{
}
void NodeView::NodeViewAttachNodesToCursor::redo()
{
view_->AttachNodesToCursor(nodes_);
}
void NodeView::NodeViewAttachNodesToCursor::undo()
{
view_->DetachItemsFromCursor();
}
Project *NodeView::NodeViewAttachNodesToCursor::GetRelevantProject() const
{
// Will either return a project or a nullptr which is also acceptable
return dynamic_cast<Project*>(view_->graph_);
}
}
+18
View File
@@ -110,6 +110,24 @@ private:
void ZoomFromKeyboard(double multiplier);
class NodeViewAttachNodesToCursor : public UndoCommand
{
public:
NodeViewAttachNodesToCursor(NodeView* view, const QVector<Node*>& nodes);
virtual void redo() override;
virtual void undo() override;
virtual Project * GetRelevantProject() const override;
private:
NodeView* view_;
QVector<Node*> nodes_;
};
NodeGraph* graph_;
struct AttachedItem {
+11 -7
View File
@@ -490,15 +490,19 @@ void ProjectExplorer::ContextMenuStartProxy(QAction *a)
Sequence* sequence = Node::ValueToPtr<Sequence>(a->data());
// To get here, the `context_menu_items_` must be all kFootage
foreach (Node* i, context_menu_items_) {
Footage* f = static_cast<Footage*>(i);
foreach (Node* item, context_menu_items_) {
Footage* f = static_cast<Footage*>(item);
QVector<VideoParams> enabled_streams = f->GetEnabledVideoStreams();
int sz = f->InputArraySize(Footage::kVideoParamsInput);
foreach (const VideoParams& stream, enabled_streams) {
// Start a background task for proxying
PreCacheTask* proxy_task = new PreCacheTask(f, stream.stream_index(), sequence);
TaskManager::instance()->AddTask(proxy_task);
for (int j=0; j<sz; j++) {
VideoParams vp = f->GetVideoParams(j);
if (vp.enabled()) {
// Start a background task for proxying
PreCacheTask* proxy_task = new PreCacheTask(f, j, sequence);
TaskManager::instance()->AddTask(proxy_task);
}
}
}
}
+6 -2
View File
@@ -1009,7 +1009,7 @@ void TimelineWidget::SetViewTimestamp(const int64_t &ts)
for (int i=0;i<views_.size();i++) {
TimelineAndTrackView* view = views_.at(i);
if (use_audio_time_units_ && i == Track::kAudio) {
if (GetConnectedNode() && use_audio_time_units_ && i == Track::kAudio) {
view->view()->SetTime(Timecode::rescale_timestamp(ts,
timebase(),
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base()));
@@ -1021,7 +1021,7 @@ void TimelineWidget::SetViewTimestamp(const int64_t &ts)
void TimelineWidget::ViewTimestampChanged(int64_t ts)
{
if (use_audio_time_units_ && sender() == views_.at(Track::kAudio)) {
if (GetConnectedNode() && use_audio_time_units_ && sender() == views_.at(Track::kAudio)) {
ts = Timecode::rescale_timestamp(ts,
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base(),
timebase());
@@ -1503,6 +1503,10 @@ QVector<SnapData> AttemptSnap(const QVector<double>& screen_pt,
bool TimelineWidget::SnapPoint(QVector<rational> start_times, rational* movement, int snap_points)
{
if (!GetConnectedNode()) {
return false;
}
QVector<double> screen_pt;
foreach (const rational& s, start_times) {
+4
View File
@@ -160,6 +160,10 @@ int SeekableWidget::TimeToScreen(const rational &time) const
void SeekableWidget::SeekToScreenPoint(int screen)
{
if (timebase().isNull()) {
return;
}
int64_t timestamp = qMax(static_cast<int64_t>(0), ScreenToUnitRounded(screen));
if (Core::instance()->snapping() && snap_service_) {
+14 -3
View File
@@ -129,7 +129,7 @@ ViewerWidget::~ViewerWidget()
{
instances_.removeOne(this);
QList<ViewerWindow*> windows = windows_;
auto windows = windows_;
foreach (ViewerWindow* window, windows) {
delete window;
@@ -311,6 +311,11 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
}
}
if (windows_.contains(screen)) {
delete windows_.take(screen);
return;
}
ViewerWindow* vw = new ViewerWindow(this);
vw->setGeometry(screen->geometry());
@@ -326,7 +331,7 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
vw->display_widget()->SetImage(display_widget_->last_loaded_buffer());
windows_.append(vw);
windows_.insert(screen, vw);
}
void ViewerWidget::ForceUpdate()
@@ -745,7 +750,7 @@ void ViewerWidget::ContextMenuSetCustomSafeMargins()
void ViewerWidget::WindowAboutToClose()
{
windows_.removeOne(static_cast<ViewerWindow*>(sender()));
windows_.remove(windows_.key(static_cast<ViewerWindow*>(sender())));
}
void ViewerWidget::ContextMenuScopeTriggered(QAction *action)
@@ -801,6 +806,10 @@ void ViewerWidget::RendererGeneratedFrameForQueue()
void ViewerWidget::ShowContextMenu(const QPoint &pos)
{
if (!GetConnectedNode()) {
return;
}
Menu menu(static_cast<QWidget*>(sender()));
context_menu_widget_ = dynamic_cast<ViewerDisplayWidget*>(sender());
@@ -854,6 +863,8 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
QString::number(s->size().height())));
a->setData(i);
a->setCheckable(true);
a->setChecked(windows_.contains(QGuiApplication::screens().at(i)));
}
connect(full_screen_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuSetFullScreen);
+1 -1
View File
@@ -223,7 +223,7 @@ private:
AudioWaveformView* waveform_view_;
QList<ViewerWindow*> windows_;
QHash<QScreen*, ViewerWindow*> windows_;
ViewerDisplayWidget* display_widget_;