reworked param view passthroughs for groups
This commit is contained in:
@@ -139,6 +139,25 @@ QString NodeGroup::GetInputName(const QString &id) const
|
||||
return pass.node()->GetInputName(pass.input());
|
||||
}
|
||||
|
||||
NodeInput NodeGroup::ResolveInput(NodeInput input)
|
||||
{
|
||||
while (GetInner(&input)) {}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
bool NodeGroup::GetInner(NodeInput *input)
|
||||
{
|
||||
if (NodeGroup *g = dynamic_cast<NodeGroup*>(input->node())) {
|
||||
const NodeInput &passthrough = g->GetInputPassthroughs().value(input->input());
|
||||
input->set_node(passthrough.node());
|
||||
input->set_input(passthrough.input());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeGroupAddInputPassthrough::redo()
|
||||
{
|
||||
if (!group_->ContainsInputPassthrough(input_)) {
|
||||
|
||||
@@ -63,6 +63,9 @@ public:
|
||||
|
||||
virtual QString GetInputName(const QString& id) const override;
|
||||
|
||||
static NodeInput ResolveInput(NodeInput input);
|
||||
static bool GetInner(NodeInput *input);
|
||||
|
||||
signals:
|
||||
void InputPassthroughAdded(NodeGroup *group, const NodeInput &input);
|
||||
|
||||
|
||||
@@ -72,10 +72,14 @@ KeyframeView::NodeConnections KeyframeView::AddKeyframesOfNode(Node *n)
|
||||
return map;
|
||||
}
|
||||
|
||||
KeyframeView::InputConnections KeyframeView::AddKeyframesOfInput(Node* n, const QString& input)
|
||||
KeyframeView::InputConnections KeyframeView::AddKeyframesOfInput(Node* on, const QString& oinput)
|
||||
{
|
||||
InputConnections vec;
|
||||
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(on, oinput));
|
||||
Node *n = resolved.node();
|
||||
const QString &input = resolved.input();
|
||||
|
||||
if (n->IsInputKeyframable(input)) {
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
vec.resize(arr_sz + 1);
|
||||
|
||||
@@ -580,7 +580,7 @@ void NodeParamView::UpdateElementY()
|
||||
if (!connections.isEmpty()) {
|
||||
foreach (const QString& input, it.key()->inputs()) {
|
||||
if (!(it.key()->GetInputFlags(input) & kInputFlagHidden)) {
|
||||
int arr_sz = it.key()->InputArraySize(input);
|
||||
int arr_sz = NodeGroup::ResolveInput(NodeInput(it.key(), input)).GetArraySize();
|
||||
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
NodeInput ic = {it.key(), input, i};
|
||||
|
||||
@@ -102,19 +102,17 @@ NodeParamViewItemBody::NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBe
|
||||
// Create widgets all root level components
|
||||
foreach (QString input, node->inputs()) {
|
||||
Node *n = node;
|
||||
while (NodeGroup *g = dynamic_cast<NodeGroup*>(n)) {
|
||||
const NodeInput &ni = g->GetInputPassthroughs().value(input);
|
||||
n = ni.node();
|
||||
input = ni.input();
|
||||
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(n, input));
|
||||
if (!connected_signals.contains(resolved.node())) {
|
||||
connect(resolved.node(), &Node::InputArraySizeChanged, this, &NodeParamViewItemBody::InputArraySizeChanged);
|
||||
connect(resolved.node(), &Node::InputConnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
connect(resolved.node(), &Node::InputDisconnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
|
||||
connected_signals.append(resolved.node());
|
||||
}
|
||||
|
||||
if (!connected_signals.contains(n)) {
|
||||
connect(n, &Node::InputArraySizeChanged, this, &NodeParamViewItemBody::InputArraySizeChanged);
|
||||
connect(n, &Node::InputConnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
connect(n, &Node::InputDisconnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
|
||||
connected_signals.append(n);
|
||||
}
|
||||
input_group_lookup_.insert({resolved.node(), resolved.input()}, {n, input});
|
||||
|
||||
if (!(n->GetInputFlags(input) & kInputFlagHidden)) {
|
||||
CreateWidgets(root_layout, n, input, -1, insert_row);
|
||||
@@ -208,14 +206,6 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
|
||||
connect(remove_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayRemoveClicked);
|
||||
|
||||
}
|
||||
} else if (dynamic_cast<ClipBlock*>(node) && input == ClipBlock::kSpeedInput) {
|
||||
// Special behavior - this was the most preferable way to do this so we could support multiple
|
||||
// nodes per item one day
|
||||
QPushButton *btn = new QPushButton(tr("..."));
|
||||
btn->setFixedWidth(btn->sizeHint().height());
|
||||
connect(btn, &QPushButton::clicked, this, &NodeParamViewItemBody::ShowSpeedDurationDialogForNode);
|
||||
layout->addWidget(btn, row, kExtraButtonColumn);
|
||||
ui_objects.extra_btn = btn;
|
||||
}
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
@@ -233,9 +223,12 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
|
||||
layout->addWidget(w, row, i+kWidgetStartColumn);
|
||||
}
|
||||
|
||||
// In case this input is a group, resolve that actual input to use for connected labels
|
||||
NodeInput resolved = NodeGroup::ResolveInput(input_ref);
|
||||
|
||||
if (node->IsInputConnectable(input)) {
|
||||
// Create clickable label used when an input is connected
|
||||
ui_objects.connected_label = new NodeParamViewConnectedLabel(input_ref);
|
||||
ui_objects.connected_label = new NodeParamViewConnectedLabel(resolved);
|
||||
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode);
|
||||
layout->addWidget(ui_objects.connected_label, row, kWidgetStartColumn, 1, kKeyControlColumn - kWidgetStartColumn);
|
||||
}
|
||||
@@ -243,7 +236,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (node->IsInputKeyframable(input)) {
|
||||
ui_objects.key_control = new NodeParamViewKeyframeControl();
|
||||
ui_objects.key_control->SetInput(input_ref);
|
||||
ui_objects.key_control->SetInput(resolved);
|
||||
layout->addWidget(ui_objects.key_control, row, kKeyControlColumn);
|
||||
connect(ui_objects.key_control, &NodeParamViewKeyframeControl::RequestSetTime, this, &NodeParamViewItemBody::RequestSetTime);
|
||||
}
|
||||
@@ -305,11 +298,7 @@ int NodeParamViewItemBody::GetElementY(NodeInput c) const
|
||||
c.set_element(-1);
|
||||
}
|
||||
|
||||
while (NodeGroup *g = dynamic_cast<NodeGroup*>(c.node())) {
|
||||
const NodeInput &passthrough = g->GetInputPassthroughs().value(c.input());
|
||||
c.set_node(passthrough.node());
|
||||
c.set_input(passthrough.input());
|
||||
}
|
||||
//c = NodeGroup::ResolveInput(c);
|
||||
|
||||
// Find its row in the parameters
|
||||
QLabel* lbl = input_ui_map_.value(c).main_label;
|
||||
@@ -328,7 +317,10 @@ void NodeParamViewItemBody::EdgeChanged(Node *output, const NodeInput& input)
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
UpdateUIForEdgeConnection(input);
|
||||
const NodeInputPair &pair = input_group_lookup_.value({input.node(), input.input()});
|
||||
NodeInput resolved(pair.node, pair.input, input.element());
|
||||
|
||||
UpdateUIForEdgeConnection(resolved);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput& input)
|
||||
@@ -337,20 +329,22 @@ void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput& input)
|
||||
if (input_ui_map_.contains(input)) {
|
||||
const InputUI& ui_objects = input_ui_map_[input];
|
||||
|
||||
bool is_connected = NodeGroup::ResolveInput(input).IsConnected();
|
||||
|
||||
foreach (QWidget* w, ui_objects.widget_bridge->widgets()) {
|
||||
w->setVisible(!input.IsConnected());
|
||||
w->setVisible(!is_connected);
|
||||
}
|
||||
|
||||
// Show/hide connection label
|
||||
ui_objects.connected_label->setVisible(input.IsConnected());
|
||||
ui_objects.connected_label->setVisible(is_connected);
|
||||
|
||||
if (ui_objects.key_control) {
|
||||
ui_objects.key_control->setVisible(!input.IsConnected());
|
||||
ui_objects.key_control->setVisible(!is_connected);
|
||||
}
|
||||
|
||||
// Show/hide optional checkbox if requested
|
||||
if (create_checkboxes_ == kCheckBoxesOnNonConnected) {
|
||||
ui_objects.optional_checkbox->setVisible(!input.IsConnected());
|
||||
ui_objects.optional_checkbox->setVisible(!is_connected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,7 +408,8 @@ void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
|
||||
array_ui_.value(input).widget->setVisible(checked);
|
||||
if (checked) {
|
||||
// Ensure widgets are created (the signal will be ignored if they are)
|
||||
InputArraySizeChangedInternal(input.node, input.input, input.node->InputArraySize(input.input));
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(input.node, input.input));
|
||||
InputArraySizeChangedInternal(input.node, input.input, resolved.GetArraySize());
|
||||
}
|
||||
|
||||
emit ArrayExpandedChanged(checked);
|
||||
@@ -424,16 +419,17 @@ void NodeParamViewItemBody::InputArraySizeChanged(const QString& input, int old_
|
||||
{
|
||||
Q_UNUSED(old_sz)
|
||||
|
||||
Node* node = static_cast<Node*>(sender());
|
||||
NodeInputPair nip = input_group_lookup_.value({static_cast<Node*>(sender()), input});
|
||||
|
||||
InputArraySizeChangedInternal(node, input, size);
|
||||
InputArraySizeChangedInternal(nip.node, nip.input, size);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayAppendClicked()
|
||||
{
|
||||
for (auto it=array_ui_.cbegin(); it!=array_ui_.cend(); it++) {
|
||||
if (it.value().append_btn == sender()) {
|
||||
it.key().node->InputArrayAppend(it.key().input, true);
|
||||
NodeInput real_input = NodeGroup::ResolveInput(NodeInput(it.key().node, it.key().input));
|
||||
real_input.node()->InputArrayAppend(real_input.input(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -444,7 +440,7 @@ void NodeParamViewItemBody::ArrayInsertClicked()
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_insert_btn == sender()) {
|
||||
// Found our input and element
|
||||
const NodeInput& ic = it.key();
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
ic.node()->InputArrayInsert(ic.input(), ic.element(), true);
|
||||
break;
|
||||
}
|
||||
@@ -456,7 +452,7 @@ void NodeParamViewItemBody::ArrayRemoveClicked()
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_remove_btn == sender()) {
|
||||
// Found our input and element
|
||||
const NodeInput& ic = it.key();
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
ic.node()->InputArrayRemove(ic.input(), ic.element(), true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,8 @@ private:
|
||||
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
|
||||
QHash<NodeInputPair, NodeInputPair> input_group_lookup_;
|
||||
|
||||
/**
|
||||
* @brief The column to place the keyframe controls in
|
||||
*
|
||||
|
||||
@@ -41,24 +41,25 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(const NodeInput &input, QObject *parent) :
|
||||
QObject(parent),
|
||||
input_(input)
|
||||
NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(NodeInput input, QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
CreateWidgets();
|
||||
do {
|
||||
input_hierarchy_.append(input);
|
||||
|
||||
connect(input_.node(), &Node::ValueChanged, this, &NodeParamViewWidgetBridge::InputValueChanged);
|
||||
connect(input_.node(), &Node::InputPropertyChanged, this, &NodeParamViewWidgetBridge::PropertyChanged);
|
||||
connect(input_.node(), &Node::InputDataTypeChanged, this, &NodeParamViewWidgetBridge::InputDataTypeChanged);
|
||||
connect(input.node(), &Node::ValueChanged, this, &NodeParamViewWidgetBridge::InputValueChanged);
|
||||
connect(input.node(), &Node::InputPropertyChanged, this, &NodeParamViewWidgetBridge::PropertyChanged);
|
||||
connect(input.node(), &Node::InputDataTypeChanged, this, &NodeParamViewWidgetBridge::InputDataTypeChanged);
|
||||
} while (NodeGroup::GetInner(&input));
|
||||
|
||||
CreateWidgets();
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::SetTime(const rational &time)
|
||||
{
|
||||
time_ = time;
|
||||
|
||||
if (input_.IsValid()) {
|
||||
UpdateWidgetValues();
|
||||
}
|
||||
UpdateWidgetValues();
|
||||
}
|
||||
|
||||
int GetSliderCount(NodeValue::Type type)
|
||||
@@ -68,16 +69,16 @@ int GetSliderCount(NodeValue::Type type)
|
||||
|
||||
void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
{
|
||||
if (input_.IsArray() && input_.element() == -1) {
|
||||
if (GetInnerInput().IsArray() && GetInnerInput().element() == -1) {
|
||||
|
||||
NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(input_.node(), input_.input());
|
||||
NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(GetInnerInput().node(), GetInnerInput().input());
|
||||
connect(w, &NodeParamViewArrayWidget::DoubleClicked, this, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked);
|
||||
widgets_.append(w);
|
||||
|
||||
} else {
|
||||
|
||||
// We assume the first data type is the "primary" type
|
||||
NodeValue::Type t = input_.GetDataType();
|
||||
NodeValue::Type t = GetDataType();
|
||||
switch (t) {
|
||||
// None of these inputs have applicable UI widgets
|
||||
case NodeValue::kNone:
|
||||
@@ -113,7 +114,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
{
|
||||
QComboBox* combobox = new QComboBox();
|
||||
|
||||
QStringList items = input_.GetComboBoxStrings();
|
||||
QStringList items = GetInnerInput().GetComboBoxStrings();
|
||||
foreach (const QString& s, items) {
|
||||
combobox->addItem(s);
|
||||
}
|
||||
@@ -131,7 +132,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
}
|
||||
case NodeValue::kColor:
|
||||
{
|
||||
ColorButton* color_button = new ColorButton(input_.node()->project()->color_manager());
|
||||
ColorButton* color_button = new ColorButton(GetInnerInput().node()->project()->color_manager());
|
||||
widgets_.append(color_button);
|
||||
connect(color_button, &ColorButton::ColorChanged, this, &NodeParamViewWidgetBridge::WidgetCallback);
|
||||
break;
|
||||
@@ -160,10 +161,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
}
|
||||
|
||||
// Check all properties
|
||||
auto input_properties = input_.node()->GetInputProperties(input_.input());
|
||||
for (auto it=input_properties.cbegin(); it!=input_properties.cend(); it++) {
|
||||
PropertyChanged(input_.input(), it.key(), it.value());
|
||||
}
|
||||
UpdateProperties();
|
||||
|
||||
UpdateWidgetValues();
|
||||
|
||||
@@ -186,16 +184,16 @@ void NodeParamViewWidgetBridge::SetInputValue(const QVariant &value, int track)
|
||||
|
||||
void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int track, MultiUndoCommand *command, bool insert_on_all_tracks_if_no_key)
|
||||
{
|
||||
if (input_.IsKeyframing()) {
|
||||
if (GetInnerInput().IsKeyframing()) {
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
NodeKeyframe* existing_key = input_.GetKeyframeAtTimeOnTrack(node_time, track);
|
||||
NodeKeyframe* existing_key = GetInnerInput().GetKeyframeAtTimeOnTrack(node_time, track);
|
||||
|
||||
if (existing_key) {
|
||||
command->add_child(new NodeParamSetKeyframeValueCommand(existing_key, value));
|
||||
} else {
|
||||
// No existing key, create a new one
|
||||
int nb_tracks = NodeValue::get_number_of_keyframe_tracks(input_.node()->GetInputDataType(input_.input()));
|
||||
int nb_tracks = NodeValue::get_number_of_keyframe_tracks(GetInnerInput().node()->GetInputDataType(GetInnerInput().input()));
|
||||
for (int i=0; i<nb_tracks; i++) {
|
||||
QVariant track_value;
|
||||
|
||||
@@ -204,21 +202,21 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
|
||||
} else if (!insert_on_all_tracks_if_no_key) {
|
||||
continue;
|
||||
} else {
|
||||
track_value = input_.node()->GetSplitValueAtTimeOnTrack(input_.input(), node_time, i, input_.element());
|
||||
track_value = GetInnerInput().node()->GetSplitValueAtTimeOnTrack(GetInnerInput().input(), node_time, i, GetInnerInput().element());
|
||||
}
|
||||
|
||||
NodeKeyframe* new_key = new NodeKeyframe(node_time,
|
||||
track_value,
|
||||
input_.node()->GetBestKeyframeTypeForTimeOnTrack(NodeKeyframeTrackReference(input_, i), node_time),
|
||||
GetInnerInput().node()->GetBestKeyframeTypeForTimeOnTrack(NodeKeyframeTrackReference(GetInnerInput(), i), node_time),
|
||||
i,
|
||||
input_.element(),
|
||||
input_.input());
|
||||
GetInnerInput().element(),
|
||||
GetInnerInput().input());
|
||||
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_.node(), new_key));
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(GetInnerInput().node(), new_key));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(input_, track), value));
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(GetInnerInput(), track), value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +230,7 @@ void NodeParamViewWidgetBridge::ProcessSlider(NumericSliderBase *slider, const Q
|
||||
if (!dragger_.IsStarted()) {
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
dragger_.Start(NodeKeyframeTrackReference(input_, slider_track), node_time);
|
||||
dragger_.Start(NodeKeyframeTrackReference(GetInnerInput(), slider_track), node_time);
|
||||
}
|
||||
|
||||
dragger_.Drag(value);
|
||||
@@ -256,7 +254,7 @@ void NodeParamViewWidgetBridge::ProcessSlider(NumericSliderBase *slider, const Q
|
||||
|
||||
void NodeParamViewWidgetBridge::WidgetCallback()
|
||||
{
|
||||
switch (input_.GetDataType()) {
|
||||
switch (GetDataType()) {
|
||||
// None of these inputs have applicable UI widgets
|
||||
case NodeValue::kNone:
|
||||
case NodeValue::kTexture:
|
||||
@@ -333,12 +331,12 @@ void NodeParamViewWidgetBridge::WidgetCallback()
|
||||
SetInputValueInternal(c.blue(), 2, command, false);
|
||||
SetInputValueInternal(c.alpha(), 3, command, false);
|
||||
|
||||
Node* n = input_.node();
|
||||
Node* n = GetInnerInput().node();
|
||||
n->blockSignals(true);
|
||||
n->SetInputProperty(input_.input(), QStringLiteral("col_input"), c.color_input());
|
||||
n->SetInputProperty(input_.input(), QStringLiteral("col_display"), c.color_output().display());
|
||||
n->SetInputProperty(input_.input(), QStringLiteral("col_view"), c.color_output().view());
|
||||
n->SetInputProperty(input_.input(), QStringLiteral("col_look"), c.color_output().look());
|
||||
n->SetInputProperty(GetInnerInput().input(), QStringLiteral("col_input"), c.color_input());
|
||||
n->SetInputProperty(GetInnerInput().input(), QStringLiteral("col_display"), c.color_output().display());
|
||||
n->SetInputProperty(GetInnerInput().input(), QStringLiteral("col_view"), c.color_output().view());
|
||||
n->SetInputProperty(GetInnerInput().input(), QStringLiteral("col_look"), c.color_output().look());
|
||||
n->blockSignals(false);
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
@@ -386,7 +384,7 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
|
||||
{
|
||||
for (int i=0;i<count;i++) {
|
||||
T* fs = new T();
|
||||
fs->SliderBase::SetDefaultValue(input_.GetSplitDefaultValueForTrack(i));
|
||||
fs->SliderBase::SetDefaultValue(GetInnerInput().GetSplitDefaultValueForTrack(i));
|
||||
fs->SetLadderElementCount(2);
|
||||
widgets_.append(fs);
|
||||
connect(fs, &T::ValueChanged, this, &NodeParamViewWidgetBridge::WidgetCallback);
|
||||
@@ -395,17 +393,17 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
|
||||
|
||||
void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
{
|
||||
if (input_.IsArray() && input_.element() == -1) {
|
||||
if (GetInnerInput().IsArray() && GetInnerInput().element() == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
rational node_time;
|
||||
if (input_.IsKeyframing()) {
|
||||
if (GetInnerInput().IsKeyframing()) {
|
||||
node_time = GetCurrentTimeAsNodeTime();
|
||||
}
|
||||
|
||||
// We assume the first data type is the "primary" type
|
||||
switch (input_.GetDataType()) {
|
||||
switch (GetDataType()) {
|
||||
// None of these inputs have applicable UI widgets
|
||||
case NodeValue::kNone:
|
||||
case NodeValue::kTexture:
|
||||
@@ -420,22 +418,22 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
break;
|
||||
case NodeValue::kInt:
|
||||
{
|
||||
static_cast<IntegerSlider*>(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).toLongLong());
|
||||
static_cast<IntegerSlider*>(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).toLongLong());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kFloat:
|
||||
{
|
||||
static_cast<FloatSlider*>(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).toDouble());
|
||||
static_cast<FloatSlider*>(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).toDouble());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kRational:
|
||||
{
|
||||
static_cast<RationalSlider*>(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).value<rational>());
|
||||
static_cast<RationalSlider*>(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).value<rational>());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kVec2:
|
||||
{
|
||||
QVector2D vec2 = input_.GetValueAtTime(node_time).value<QVector2D>();
|
||||
QVector2D vec2 = GetInnerInput().GetValueAtTime(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()));
|
||||
@@ -443,7 +441,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
}
|
||||
case NodeValue::kVec3:
|
||||
{
|
||||
QVector3D vec3 = input_.GetValueAtTime(node_time).value<QVector3D>();
|
||||
QVector3D vec3 = GetInnerInput().GetValueAtTime(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()));
|
||||
@@ -452,7 +450,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
}
|
||||
case NodeValue::kVec4:
|
||||
{
|
||||
QVector4D vec4 = input_.GetValueAtTime(node_time).value<QVector4D>();
|
||||
QVector4D vec4 = GetInnerInput().GetValueAtTime(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()));
|
||||
@@ -463,18 +461,18 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
case NodeValue::kFile:
|
||||
{
|
||||
FileField* ff = static_cast<FileField*>(widgets_.first());
|
||||
ff->SetFilename(input_.GetValueAtTime(node_time).toString());
|
||||
ff->SetFilename(GetInnerInput().GetValueAtTime(node_time).toString());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kColor:
|
||||
{
|
||||
ManagedColor mc = input_.GetValueAtTime(node_time).value<Color>();
|
||||
ManagedColor mc = GetInnerInput().GetValueAtTime(node_time).value<Color>();
|
||||
|
||||
mc.set_color_input(input_.GetProperty("col_input").toString());
|
||||
mc.set_color_input(GetInnerInput().GetProperty("col_input").toString());
|
||||
|
||||
QString d = input_.GetProperty("col_display").toString();
|
||||
QString v = input_.GetProperty("col_view").toString();
|
||||
QString l = input_.GetProperty("col_look").toString();
|
||||
QString d = GetInnerInput().GetProperty("col_display").toString();
|
||||
QString v = GetInnerInput().GetProperty("col_view").toString();
|
||||
QString l = GetInnerInput().GetProperty("col_look").toString();
|
||||
|
||||
mc.set_color_output(ColorTransform(d, v, l));
|
||||
|
||||
@@ -484,17 +482,17 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
case NodeValue::kText:
|
||||
{
|
||||
NodeParamViewTextEdit* e = static_cast<NodeParamViewTextEdit*>(widgets_.first());
|
||||
e->setTextPreservingCursor(input_.GetValueAtTime(node_time).toString());
|
||||
e->setTextPreservingCursor(GetInnerInput().GetValueAtTime(node_time).toString());
|
||||
break;
|
||||
}
|
||||
case NodeValue::kBoolean:
|
||||
static_cast<QCheckBox*>(widgets_.first())->setChecked(input_.GetValueAtTime(node_time).toBool());
|
||||
static_cast<QCheckBox*>(widgets_.first())->setChecked(GetInnerInput().GetValueAtTime(node_time).toBool());
|
||||
break;
|
||||
case NodeValue::kFont:
|
||||
{
|
||||
QFontComboBox* fc = static_cast<QFontComboBox*>(widgets_.first());
|
||||
fc->blockSignals(true);
|
||||
fc->setCurrentFont(input_.GetValueAtTime(node_time).toString());
|
||||
fc->setCurrentFont(GetInnerInput().GetValueAtTime(node_time).toString());
|
||||
fc->blockSignals(false);
|
||||
break;
|
||||
}
|
||||
@@ -502,7 +500,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
{
|
||||
QComboBox* cb = static_cast<QComboBox*>(widgets_.first());
|
||||
cb->blockSignals(true);
|
||||
int index = input_.GetValueAtTime(node_time).toInt();
|
||||
int index = GetInnerInput().GetValueAtTime(node_time).toInt();
|
||||
for (int i=0; i<cb->count(); i++) {
|
||||
if (cb->itemData(i).toInt() == index) {
|
||||
cb->setCurrentIndex(i);
|
||||
@@ -516,19 +514,19 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
|
||||
|
||||
rational NodeParamViewWidgetBridge::GetCurrentTimeAsNodeTime() const
|
||||
{
|
||||
return GetAdjustedTime(GetTimeTarget(), input_.node(), time_, true);
|
||||
return GetAdjustedTime(GetTimeTarget(), GetInnerInput().node(), time_, true);
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::SetTimebase(const rational& timebase)
|
||||
{
|
||||
if (input_.GetDataType() == NodeValue::kRational) {
|
||||
if (GetDataType() == NodeValue::kRational) {
|
||||
static_cast<RationalSlider*>(widgets_.first())->SetTimebase(timebase);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::InputValueChanged(const NodeInput &input, const TimeRange &range)
|
||||
{
|
||||
if (input_ == input
|
||||
if (GetInnerInput() == input
|
||||
&& !dragger_.IsStarted()
|
||||
&& range.in() <= time_ && range.out() >= time_) {
|
||||
// We'll need to update the widgets because the values have changed on our current time
|
||||
@@ -536,13 +534,9 @@ void NodeParamViewWidgetBridge::InputValueChanged(const NodeInput &input, const
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::PropertyChanged(const QString& input, const QString &key, const QVariant &value)
|
||||
void NodeParamViewWidgetBridge::SetProperty(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (input != input_.input() || (input_.IsArray() && input_.element() == -1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeValue::Type data_type = input_.GetDataType();
|
||||
NodeValue::Type data_type = GetDataType();
|
||||
|
||||
// Parameters for all types
|
||||
if (key == QStringLiteral("enabled")) {
|
||||
@@ -657,35 +651,37 @@ void NodeParamViewWidgetBridge::PropertyChanged(const QString& input, const QStr
|
||||
|
||||
// ComboBox strings changing
|
||||
if (data_type == NodeValue::kCombo) {
|
||||
QComboBox* cb = static_cast<QComboBox*>(widgets_.first());
|
||||
if (key == QStringLiteral("combo_str")) {
|
||||
QComboBox* cb = static_cast<QComboBox*>(widgets_.first());
|
||||
|
||||
int old_index = cb->currentIndex();
|
||||
int old_index = cb->currentIndex();
|
||||
|
||||
// Block the combobox changed signals since we anticipate the index will be the same and not require a re-render
|
||||
cb->blockSignals(true);
|
||||
// Block the combobox changed signals since we anticipate the index will be the same and not require a re-render
|
||||
cb->blockSignals(true);
|
||||
|
||||
cb->clear();
|
||||
cb->clear();
|
||||
|
||||
QStringList items = input_.GetComboBoxStrings();
|
||||
int index = 0;
|
||||
foreach (const QString& s, items) {
|
||||
if (s.isEmpty()) {
|
||||
cb->insertSeparator(cb->count());
|
||||
cb->setItemData(cb->count()-1, -1);
|
||||
} else {
|
||||
cb->addItem(s, index);
|
||||
index++;
|
||||
QStringList items = value.toStringList();
|
||||
int index = 0;
|
||||
foreach (const QString& s, items) {
|
||||
if (s.isEmpty()) {
|
||||
cb->insertSeparator(cb->count());
|
||||
cb->setItemData(cb->count()-1, -1);
|
||||
} else {
|
||||
cb->addItem(s, index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb->setCurrentIndex(old_index);
|
||||
cb->setCurrentIndex(old_index);
|
||||
|
||||
cb->blockSignals(false);
|
||||
cb->blockSignals(false);
|
||||
|
||||
// In case the amount of items is LESS and the previous index cannot be set, NOW we trigger a re-cache since the
|
||||
// value has changed
|
||||
if (cb->currentIndex() != old_index) {
|
||||
WidgetCallback();
|
||||
// In case the amount of items is LESS and the previous index cannot be set, NOW we trigger a re-cache since the
|
||||
// value has changed
|
||||
if (cb->currentIndex() != old_index) {
|
||||
WidgetCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -742,8 +738,7 @@ 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()) {
|
||||
if (sender() == GetOuterInput().node() && input == GetOuterInput().input()) {
|
||||
// Delete all widgets
|
||||
qDeleteAll(widgets_);
|
||||
widgets_.clear();
|
||||
@@ -752,7 +747,34 @@ void NodeParamViewWidgetBridge::InputDataTypeChanged(const QString &input, NodeV
|
||||
CreateWidgets();
|
||||
|
||||
// Signal that widgets are new
|
||||
emit WidgetsRecreated(input_);
|
||||
emit WidgetsRecreated(GetOuterInput());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::PropertyChanged(const QString &input, const QString &key, const QVariant &value)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (auto it=input_hierarchy_.cbegin(); it!=input_hierarchy_.cend(); it++) {
|
||||
if (it->input() == input) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
UpdateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewWidgetBridge::UpdateProperties()
|
||||
{
|
||||
// Set properties from the last entry (the innermost input) to the first (the outermost)
|
||||
for (auto it=input_hierarchy_.crbegin(); it!=input_hierarchy_.crend(); it++) {
|
||||
auto input_properties = it->node()->GetInputProperties(it->input());
|
||||
for (auto jt=input_properties.cbegin(); jt!=input_properties.cend(); jt++) {
|
||||
SetProperty(jt.key(), jt.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class NodeParamViewWidgetBridge : public QObject, public TimeTargetObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewWidgetBridge(const NodeInput& input, QObject* parent);
|
||||
NodeParamViewWidgetBridge(NodeInput input, QObject* parent);
|
||||
|
||||
void SetTime(const rational& time);
|
||||
|
||||
@@ -66,6 +66,8 @@ private:
|
||||
|
||||
void ProcessSlider(NumericSliderBase* slider, const QVariant& value);
|
||||
|
||||
void SetProperty(const QString &key, const QVariant &value);
|
||||
|
||||
template <typename T>
|
||||
void CreateSliders(int count);
|
||||
|
||||
@@ -73,7 +75,24 @@ private:
|
||||
|
||||
rational GetCurrentTimeAsNodeTime() const;
|
||||
|
||||
NodeInput input_;
|
||||
const NodeInput &GetOuterInput() const
|
||||
{
|
||||
return input_hierarchy_.first();
|
||||
}
|
||||
|
||||
const NodeInput &GetInnerInput() const
|
||||
{
|
||||
return input_hierarchy_.last();
|
||||
}
|
||||
|
||||
NodeValue::Type GetDataType() const
|
||||
{
|
||||
return GetOuterInput().GetDataType();
|
||||
}
|
||||
|
||||
void UpdateProperties();
|
||||
|
||||
QVector<NodeInput> input_hierarchy_;
|
||||
|
||||
QVector<QWidget*> widgets_;
|
||||
|
||||
@@ -88,10 +107,10 @@ private slots:
|
||||
|
||||
void InputValueChanged(const NodeInput& input, const TimeRange& range);
|
||||
|
||||
void PropertyChanged(const QString &input, const QString& key, const QVariant& value);
|
||||
|
||||
void InputDataTypeChanged(const QString& input, NodeValue::Type type);
|
||||
|
||||
void PropertyChanged(const QString &input, const QString &key, const QVariant &value);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user