nodeparamview: separated the NodeParamView body into a separate widget for nesting
Will allow display of NodeInputArrays.
This commit is contained in:
@@ -321,8 +321,11 @@ void Block::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
|
||||
name_input_->set_name(tr("Name"));
|
||||
length_input_->set_name(tr("Length"));
|
||||
media_in_input_->set_name(tr("Media In"));
|
||||
enabled_input_->set_name(tr("Enabled"));
|
||||
speed_input_->set_name(tr("Speed"));
|
||||
}
|
||||
|
||||
NodeInput *Block::length_input() const
|
||||
|
||||
@@ -58,6 +58,8 @@ NodeInput *TransitionBlock::in_block_input() const
|
||||
|
||||
void TransitionBlock::Retranslate()
|
||||
{
|
||||
Block::Retranslate();
|
||||
|
||||
out_block_input_->set_name(tr("From"));
|
||||
in_block_input_->set_name(tr("To"));
|
||||
}
|
||||
|
||||
@@ -113,6 +113,8 @@ void TrackOutput::SetTrackHeight(const int &height)
|
||||
|
||||
void TrackOutput::Retranslate()
|
||||
{
|
||||
Block::Retranslate();
|
||||
|
||||
block_input_->set_name(tr("Blocks"));
|
||||
muted_input_->set_name(tr("Muted"));
|
||||
}
|
||||
|
||||
@@ -217,6 +217,12 @@ void ViewerOutput::UpdateLength(const rational &length)
|
||||
|
||||
void ViewerOutput::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
|
||||
texture_input_->set_name(tr("Texture"));
|
||||
|
||||
samples_input_->set_name(tr("Samples"));
|
||||
|
||||
for (int i=0;i<track_inputs_.size();i++) {
|
||||
QString input_name;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
add_subdirectory(audiomonitor)
|
||||
add_subdirectory(clickablelabel)
|
||||
add_subdirectory(collapsebutton)
|
||||
add_subdirectory(colorbutton)
|
||||
add_subdirectory(colorwheel)
|
||||
add_subdirectory(columnedgridlayout)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 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/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/collapsebutton/collapsebutton.h
|
||||
widget/collapsebutton/collapsebutton.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,50 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 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 "collapsebutton.h"
|
||||
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
CollapseButton::CollapseButton(QWidget *parent) :
|
||||
QPushButton(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
setStyleSheet("border: none; background: none;");
|
||||
setCheckable(true);
|
||||
setChecked(true);
|
||||
setIconSize(QSize(fontMetrics().height()/2, fontMetrics().height()/2));
|
||||
|
||||
connect(this, &CollapseButton::toggled, this, &CollapseButton::UpdateIcon);
|
||||
|
||||
UpdateIcon(isChecked());
|
||||
}
|
||||
|
||||
void CollapseButton::UpdateIcon(bool e)
|
||||
{
|
||||
if (e) {
|
||||
setIcon(icon::TriDown);
|
||||
} else {
|
||||
setIcon(icon::TriRight);
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -0,0 +1,43 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 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 COLLAPSEBUTTON_H
|
||||
#define COLLAPSEBUTTON_H
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class CollapseButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollapseButton(QWidget* parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void UpdateIcon(bool e);
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // COLLAPSEBUTTON_H
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "core.h"
|
||||
#include "nodeparamviewundo.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -46,16 +45,8 @@ NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
|
||||
|
||||
QHBoxLayout* title_bar_layout = new QHBoxLayout(title_bar_);
|
||||
|
||||
title_bar_collapse_btn_ = new QPushButton();
|
||||
title_bar_collapse_btn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
title_bar_collapse_btn_->setStyleSheet("border: none; background: none;");
|
||||
title_bar_collapse_btn_->setCheckable(true);
|
||||
title_bar_collapse_btn_->setChecked(true);
|
||||
|
||||
// FIXME: Revise icon sizing algorithm (share with NodeViewItem)
|
||||
title_bar_collapse_btn_->setIconSize(QSize(fontMetrics().height()/2, fontMetrics().height()/2));
|
||||
|
||||
connect(title_bar_collapse_btn_, &QPushButton::clicked, this, &NodeParamViewItem::SetExpanded);
|
||||
title_bar_collapse_btn_ = new CollapseButton();
|
||||
connect(title_bar_collapse_btn_, &QPushButton::toggled, this, &NodeParamViewItem::SetExpanded);
|
||||
title_bar_layout->addWidget(title_bar_collapse_btn_);
|
||||
|
||||
title_bar_lbl_ = new QLabel(title_bar_);
|
||||
@@ -65,50 +56,44 @@ NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
|
||||
main_layout->addWidget(title_bar_);
|
||||
|
||||
// Create and add contents widget
|
||||
contents_ = new QWidget(this);
|
||||
content_layout_ = new QGridLayout(contents_);
|
||||
main_layout->addWidget(contents_);
|
||||
QList<NodeInput*> inputs;
|
||||
|
||||
// Filter out inputs
|
||||
foreach (NodeParam* p, node->parameters()) {
|
||||
if (p->type() == NodeParam::kInput) {
|
||||
inputs.append(static_cast<NodeInput*>(p));
|
||||
}
|
||||
}
|
||||
|
||||
body_ = new NodeParamViewItemBody(inputs);
|
||||
connect(body_, &NodeParamViewItemBody::InputClicked, this, &NodeParamViewItem::InputClicked);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItem::RequestSetTime);
|
||||
connect(body_, &NodeParamViewItemBody::KeyframeAdded, this, &NodeParamViewItem::KeyframeAdded);
|
||||
connect(body_, &NodeParamViewItemBody::KeyframeRemoved, this, &NodeParamViewItem::KeyframeRemoved);
|
||||
main_layout->addWidget(body_);
|
||||
|
||||
// Set correct widget state
|
||||
SetExpanded(title_bar_collapse_btn_->isChecked());
|
||||
|
||||
SetupUI();
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SetTimeTarget(Node *target)
|
||||
{
|
||||
foreach (NodeParamViewKeyframeControl* control, key_control_list_) {
|
||||
control->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewWidgetBridge* bridge, bridges_) {
|
||||
bridge->SetTimeTarget(target);
|
||||
}
|
||||
body_->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SetTime(const rational &time)
|
||||
{
|
||||
time_ = time;
|
||||
|
||||
foreach (NodeParamViewWidgetBridge* bridge, bridges_) {
|
||||
// Updates the UI widgets from the time
|
||||
bridge->SetTime(time_);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewKeyframeControl* key_control, key_control_list_) {
|
||||
key_control->SetTime(time_);
|
||||
}
|
||||
body_->SetTime(time_);
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SignalAllKeyframes()
|
||||
{
|
||||
foreach (NodeInput* input, node_->GetInputsIncludingArrays()) {
|
||||
foreach (const NodeInput::KeyframeTrack& track, input->keyframe_tracks()) {
|
||||
foreach (NodeKeyframePtr key, track) {
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
body_->SignalAllKeyframes();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::changeEvent(QEvent *e)
|
||||
@@ -120,187 +105,20 @@ void NodeParamViewItem::changeEvent(QEvent *e)
|
||||
QWidget::changeEvent(e);
|
||||
}
|
||||
|
||||
void NodeParamViewItem::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframePtr keyframe)
|
||||
{
|
||||
// Find its row in the parameters
|
||||
QLabel* lbl = label_map_.value(input);
|
||||
|
||||
// Find label's Y position
|
||||
QPoint lbl_center = lbl->rect().center();
|
||||
|
||||
// Find global position
|
||||
lbl_center = lbl->mapToGlobal(lbl_center);
|
||||
|
||||
emit KeyframeAdded(keyframe, lbl_center.y());
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SetupUI()
|
||||
{
|
||||
int row_count = 0;
|
||||
|
||||
foreach (NodeParam* param, node_->parameters()) {
|
||||
// This widget only needs to show input parameters
|
||||
if (param->type() == NodeParam::kInput) {
|
||||
NodeInput* input = static_cast<NodeInput*>(param);
|
||||
|
||||
// Add descriptor label
|
||||
ClickableLabel* param_label = new ClickableLabel();
|
||||
connect(param_label, &ClickableLabel::MouseClicked, this, &NodeParamViewItem::LabelClicked);
|
||||
param_lbls_.insert(input, param_label);
|
||||
|
||||
label_map_.insert(input, param_label);
|
||||
|
||||
content_layout_->addWidget(param_label, row_count, 0);
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
NodeParamViewWidgetBridge* bridge = new NodeParamViewWidgetBridge(input, this);
|
||||
bridges_.insert(input, bridge);
|
||||
|
||||
// Add widgets for this parameter to the layout
|
||||
const QList<QWidget*>& widgets_for_param = bridge->widgets();
|
||||
for (int i=0;i<widgets_for_param.size();i++) {
|
||||
content_layout_->addWidget(widgets_for_param.at(i), row_count, i + 1);
|
||||
}
|
||||
|
||||
if (input->IsConnectable()) {
|
||||
// Create clickable label used when an input is connected
|
||||
NodeParamViewConnectedLabel* connected_lbl = new NodeParamViewConnectedLabel(input);
|
||||
connected_.insert(input, connected_lbl);
|
||||
connect(connected_lbl, &NodeParamViewConnectedLabel::ConnectionClicked, this, &NodeParamViewItem::ConnectionClicked);
|
||||
content_layout_->addWidget(connected_lbl, row_count, 1);
|
||||
|
||||
UpdateUIForEdgeConnection(input);
|
||||
|
||||
connect(input, &NodeInput::EdgeAdded, this, &NodeParamViewItem::EdgeChanged);
|
||||
connect(input, &NodeInput::EdgeRemoved, this, &NodeParamViewItem::EdgeChanged);
|
||||
}
|
||||
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (input->is_keyframable()) {
|
||||
// Hacky but effective way to make sure this widget is always as far right as possible
|
||||
int control_column = 10;
|
||||
|
||||
NodeParamViewKeyframeControl* key_control = new NodeParamViewKeyframeControl();
|
||||
key_control->SetInput(input);
|
||||
content_layout_->addWidget(key_control, row_count, control_column);
|
||||
connect(key_control, &NodeParamViewKeyframeControl::RequestSetTime, this, &NodeParamViewItem::RequestSetTime);
|
||||
key_control_list_.append(key_control);
|
||||
|
||||
connect(input, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewItem::InputKeyframeEnableChanged);
|
||||
connect(input, &NodeInput::KeyframeAdded, this, &NodeParamViewItem::InputAddedKeyframe);
|
||||
connect(input, &NodeInput::KeyframeRemoved, this, &NodeParamViewItem::KeyframeRemoved);
|
||||
}
|
||||
|
||||
|
||||
|
||||
row_count++;
|
||||
}
|
||||
}
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::Retranslate()
|
||||
{
|
||||
node_->Retranslate();
|
||||
|
||||
title_bar_lbl_->setText(node_->Name());
|
||||
|
||||
|
||||
QMap<NodeInput*, ClickableLabel*>::const_iterator i;
|
||||
|
||||
for (i=param_lbls_.begin(); i!=param_lbls_.end(); i++) {
|
||||
i.value()->setText(tr("%1:").arg(i.key()->name()));
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItem::UpdateUIForEdgeConnection(NodeInput *input)
|
||||
{
|
||||
// Show/hide bridge widgets
|
||||
foreach (QWidget* w, bridges_.value(input)->widgets()) {
|
||||
w->setVisible(!input->IsConnected());
|
||||
}
|
||||
|
||||
// Show/hide connection label
|
||||
connected_.value(input)->setVisible(input->IsConnected());
|
||||
}
|
||||
|
||||
NodeParamViewKeyframeControl *NodeParamViewItem::KeyframeControlFromInput(NodeInput *input) const
|
||||
{
|
||||
foreach (NodeParamViewKeyframeControl* key_control, key_control_list_) {
|
||||
if (key_control->GetConnectedInput() == input) {
|
||||
return key_control;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
body_->Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SetExpanded(bool e)
|
||||
{
|
||||
expanded_ = e;
|
||||
|
||||
contents_->setVisible(e);
|
||||
|
||||
if (expanded_) {
|
||||
title_bar_collapse_btn_->setIcon(icon::TriDown);
|
||||
} else {
|
||||
title_bar_collapse_btn_->setIcon(icon::TriRight);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItem::InputKeyframeEnableChanged(bool e)
|
||||
{
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
foreach (const NodeInput::KeyframeTrack& track, input->keyframe_tracks()) {
|
||||
foreach (NodeKeyframePtr key, track) {
|
||||
if (e) {
|
||||
// Add a keyframe item for each keyframe
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
} else {
|
||||
// Remove each keyframe item
|
||||
emit KeyframeRemoved(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItem::InputAddedKeyframe(NodeKeyframePtr key)
|
||||
{
|
||||
// Get NodeInput that emitted this signal
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
}
|
||||
|
||||
void NodeParamViewItem::LabelClicked()
|
||||
{
|
||||
ClickableLabel* lbl = static_cast<ClickableLabel*>(sender());
|
||||
|
||||
NodeInput* input = label_map_.key(lbl, nullptr);
|
||||
|
||||
if (input) {
|
||||
emit InputClicked(input);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItem::EdgeChanged()
|
||||
{
|
||||
UpdateUIForEdgeConnection(static_cast<NodeInput*>(sender()));
|
||||
}
|
||||
|
||||
void NodeParamViewItem::ConnectionClicked()
|
||||
{
|
||||
NodeParamViewConnectedLabel* src = static_cast<NodeParamViewConnectedLabel*>(sender());
|
||||
|
||||
NodeInput* input = connected_.key(src);
|
||||
|
||||
Node* connected = input->get_connected_node();
|
||||
|
||||
if (connected) {
|
||||
emit RequestSelectNode({connected});
|
||||
}
|
||||
body_->setVisible(e);
|
||||
}
|
||||
|
||||
NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent) :
|
||||
@@ -320,4 +138,232 @@ void NodeParamViewItemTitleBar::paintEvent(QPaintEvent *event)
|
||||
p.drawLine(0, bottom, width(), bottom);
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::NodeParamViewItemBody(const QList<NodeInput *> &inputs, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
int row_count = 0;
|
||||
|
||||
QGridLayout* content_layout = new QGridLayout(this);
|
||||
|
||||
foreach (NodeInput* input, inputs) {
|
||||
InputUI ui_objects;
|
||||
|
||||
// Add descriptor label
|
||||
ui_objects.main_label = new ClickableLabel();
|
||||
connect(ui_objects.main_label, &ClickableLabel::MouseClicked, this, &NodeParamViewItemBody::LabelClicked);
|
||||
|
||||
if (input->IsArray()) {
|
||||
QHBoxLayout* array_label_layout = new QHBoxLayout();
|
||||
array_label_layout->setMargin(0);
|
||||
|
||||
CollapseButton* array_collapse_btn = new CollapseButton();
|
||||
|
||||
array_label_layout->addWidget(array_collapse_btn);
|
||||
array_label_layout->addWidget(ui_objects.main_label);
|
||||
|
||||
content_layout->addLayout(array_label_layout, row_count, 0);
|
||||
} else {
|
||||
content_layout->addWidget(ui_objects.main_label, row_count, 0);
|
||||
}
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
ui_objects.widget_bridge = new NodeParamViewWidgetBridge(input, this);
|
||||
|
||||
// Add widgets for this parameter to the layout
|
||||
{
|
||||
int column = 1;
|
||||
foreach (QWidget* w, ui_objects.widget_bridge->widgets()) {
|
||||
content_layout->addWidget(w, row_count, column);
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
if (input->IsConnectable()) {
|
||||
// Create clickable label used when an input is connected
|
||||
ui_objects.connected_label = new NodeParamViewConnectedLabel(input);
|
||||
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::ConnectionClicked, this, &NodeParamViewItemBody::ConnectionClicked);
|
||||
content_layout->addWidget(ui_objects.connected_label, row_count, 1);
|
||||
|
||||
connect(input, &NodeInput::EdgeAdded, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
connect(input, &NodeInput::EdgeRemoved, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
}
|
||||
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (input->is_keyframable()) {
|
||||
// Hacky but effective way to make sure this widget is always as far right as possible
|
||||
int control_column = 10;
|
||||
|
||||
ui_objects.key_control = new NodeParamViewKeyframeControl();
|
||||
ui_objects.key_control->SetInput(input);
|
||||
content_layout->addWidget(ui_objects.key_control, row_count, control_column);
|
||||
connect(ui_objects.key_control, &NodeParamViewKeyframeControl::RequestSetTime, this, &NodeParamViewItemBody::RequestSetTime);
|
||||
|
||||
connect(input, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewItemBody::InputKeyframeEnableChanged);
|
||||
connect(input, &NodeInput::KeyframeAdded, this, &NodeParamViewItemBody::InputAddedKeyframe);
|
||||
connect(input, &NodeInput::KeyframeRemoved, this, &NodeParamViewItemBody::KeyframeRemoved);
|
||||
}
|
||||
|
||||
input_ui_map_.insert(input, ui_objects);
|
||||
|
||||
// Update "connected" label
|
||||
if (input->IsConnectable()) {
|
||||
UpdateUIForEdgeConnection(input);
|
||||
}
|
||||
|
||||
row_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTimeTarget(Node *target)
|
||||
{
|
||||
foreach (const InputUI& ui_obj, input_ui_map_) {
|
||||
// Only keyframable inputs have a key control widget
|
||||
if (ui_obj.key_control) {
|
||||
ui_obj.key_control->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
ui_obj.widget_bridge->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SetTimeTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTime(const rational &time)
|
||||
{
|
||||
foreach (const InputUI& ui_obj, input_ui_map_) {
|
||||
ui_obj.key_control->SetTime(time);
|
||||
ui_obj.widget_bridge->SetTime(time);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SetTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::Retranslate()
|
||||
{
|
||||
QMap<NodeInput*, InputUI>::const_iterator i;
|
||||
|
||||
for (i=input_ui_map_.begin(); i!=input_ui_map_.end(); i++) {
|
||||
i.value().main_label->setText(tr("%1:").arg(i.key()->name()));
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->Retranslate();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SignalAllKeyframes()
|
||||
{
|
||||
QMap<NodeInput*, InputUI>::const_iterator i;
|
||||
|
||||
for (i=input_ui_map_.begin(); i!=input_ui_map_.end(); i++) {
|
||||
NodeInput* input = i.key();
|
||||
|
||||
foreach (const NodeInput::KeyframeTrack& track, input->keyframe_tracks()) {
|
||||
foreach (NodeKeyframePtr key, track) {
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SignalAllKeyframes();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::EdgeChanged()
|
||||
{
|
||||
UpdateUIForEdgeConnection(static_cast<NodeInput*>(sender()));
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::UpdateUIForEdgeConnection(NodeInput *input)
|
||||
{
|
||||
// Show/hide bridge widgets
|
||||
const InputUI& ui_objects = input_ui_map_[input];
|
||||
|
||||
foreach (QWidget* w, ui_objects.widget_bridge->widgets()) {
|
||||
w->setVisible(!input->IsConnected());
|
||||
}
|
||||
|
||||
// Show/hide connection label
|
||||
ui_objects.connected_label->setVisible(input->IsConnected());
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputKeyframeEnableChanged(bool e)
|
||||
{
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
foreach (const NodeInput::KeyframeTrack& track, input->keyframe_tracks()) {
|
||||
foreach (NodeKeyframePtr key, track) {
|
||||
if (e) {
|
||||
// Add a keyframe item for each keyframe
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
} else {
|
||||
// Remove each keyframe item
|
||||
emit KeyframeRemoved(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputAddedKeyframe(NodeKeyframePtr key)
|
||||
{
|
||||
// Get NodeInput that emitted this signal
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::LabelClicked()
|
||||
{
|
||||
QMap<NodeInput*, InputUI>::const_iterator iterator;
|
||||
for (iterator=input_ui_map_.begin(); iterator!=input_ui_map_.end(); iterator++) {
|
||||
if (iterator.value().connected_label == sender()) {
|
||||
emit InputClicked(iterator.key());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ConnectionClicked()
|
||||
{
|
||||
QMap<NodeInput*, InputUI>::const_iterator iterator;
|
||||
for (iterator=input_ui_map_.begin(); iterator!=input_ui_map_.end(); iterator++) {
|
||||
if (iterator.value().connected_label == sender()) {
|
||||
Node* connected = iterator.key()->get_connected_node();
|
||||
|
||||
if (connected) {
|
||||
emit RequestSelectNode({connected});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframePtr keyframe)
|
||||
{
|
||||
// Find its row in the parameters
|
||||
QLabel* lbl = input_ui_map_.value(input).main_label;
|
||||
|
||||
// Find label's Y position
|
||||
QPoint lbl_center = lbl->rect().center();
|
||||
|
||||
// Find global position
|
||||
lbl_center = lbl->mapToGlobal(lbl_center);
|
||||
|
||||
emit KeyframeAdded(keyframe, lbl_center.y());
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::InputUI::InputUI() :
|
||||
main_label(nullptr),
|
||||
widget_bridge(nullptr),
|
||||
connected_label(nullptr),
|
||||
key_control(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "nodeparamviewkeyframecontrol.h"
|
||||
#include "nodeparamviewwidgetbridge.h"
|
||||
#include "widget/clickablelabel/clickablelabel.h"
|
||||
#include "widget/collapsebutton/collapsebutton.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -43,6 +44,61 @@ protected:
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
|
||||
class NodeParamViewItemBody : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItemBody(const QList<NodeInput*>& inputs, QWidget* parent = nullptr);
|
||||
|
||||
void SetTimeTarget(Node* target);
|
||||
|
||||
void SetTime(const rational& time);
|
||||
|
||||
void Retranslate();
|
||||
|
||||
void SignalAllKeyframes();
|
||||
|
||||
signals:
|
||||
void KeyframeAdded(NodeKeyframePtr key, int y);
|
||||
|
||||
void KeyframeRemoved(NodeKeyframePtr key);
|
||||
|
||||
void RequestSetTime(const rational& time);
|
||||
|
||||
void InputClicked(NodeInput* input);
|
||||
|
||||
void RequestSelectNode(const QList<Node*>& node);
|
||||
|
||||
private:
|
||||
void UpdateUIForEdgeConnection(NodeInput* input);
|
||||
|
||||
void InputAddedKeyframeInternal(NodeInput* input, NodeKeyframePtr keyframe);
|
||||
|
||||
struct InputUI {
|
||||
InputUI();
|
||||
|
||||
ClickableLabel* main_label;
|
||||
NodeParamViewWidgetBridge* widget_bridge;
|
||||
NodeParamViewConnectedLabel* connected_label;
|
||||
NodeParamViewKeyframeControl* key_control;
|
||||
};
|
||||
|
||||
QMap<NodeInput*, InputUI> input_ui_map_;
|
||||
|
||||
QList<NodeParamViewItemBody*> sub_bodies_;
|
||||
|
||||
private slots:
|
||||
void EdgeChanged();
|
||||
|
||||
void InputKeyframeEnableChanged(bool e);
|
||||
|
||||
void InputAddedKeyframe(NodeKeyframePtr key);
|
||||
|
||||
void LabelClicked();
|
||||
|
||||
void ConnectionClicked();
|
||||
|
||||
};
|
||||
|
||||
class NodeParamViewItem : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -71,55 +127,25 @@ protected:
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void InputAddedKeyframeInternal(NodeInput* input, NodeKeyframePtr keyframe);
|
||||
|
||||
void SetupUI();
|
||||
|
||||
void Retranslate();
|
||||
|
||||
void UpdateUIForEdgeConnection(NodeInput* input);
|
||||
|
||||
NodeParamViewKeyframeControl* KeyframeControlFromInput(NodeInput* input) const;
|
||||
|
||||
bool expanded_;
|
||||
|
||||
NodeParamViewItemTitleBar* title_bar_;
|
||||
|
||||
QLabel* title_bar_lbl_;
|
||||
|
||||
QPushButton* title_bar_collapse_btn_;
|
||||
CollapseButton* title_bar_collapse_btn_;
|
||||
|
||||
QWidget* contents_;
|
||||
|
||||
QGridLayout* content_layout_;
|
||||
NodeParamViewItemBody* body_;
|
||||
|
||||
Node* node_;
|
||||
|
||||
rational time_;
|
||||
|
||||
QMap<NodeInput*, ClickableLabel*> param_lbls_;
|
||||
|
||||
QMap<NodeInput*, NodeParamViewWidgetBridge*> bridges_;
|
||||
|
||||
QMap<NodeInput*, NodeParamViewConnectedLabel*> connected_;
|
||||
|
||||
QMap<NodeInput*, QLabel*> label_map_;
|
||||
|
||||
QList<NodeParamViewKeyframeControl*> key_control_list_;
|
||||
|
||||
private slots:
|
||||
void SetExpanded(bool e);
|
||||
|
||||
void InputKeyframeEnableChanged(bool e);
|
||||
|
||||
void InputAddedKeyframe(NodeKeyframePtr key);
|
||||
|
||||
void LabelClicked();
|
||||
|
||||
void EdgeChanged();
|
||||
|
||||
void ConnectionClicked();
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user