From 6aa493bd6798504ca4b91423d2975c5fa8d00875 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Sat, 22 Jan 2022 18:17:51 -0800 Subject: [PATCH] reworked param view passthroughs for groups --- app/node/group/group.cpp | 19 ++ app/node/group/group.h | 3 + app/widget/keyframeview/keyframeview.cpp | 6 +- app/widget/nodeparamview/nodeparamview.cpp | 2 +- .../nodeparamview/nodeparamviewitem.cpp | 70 +++---- app/widget/nodeparamview/nodeparamviewitem.h | 2 + .../nodeparamviewwidgetbridge.cpp | 198 ++++++++++-------- .../nodeparamview/nodeparamviewwidgetbridge.h | 27 ++- 8 files changed, 196 insertions(+), 131 deletions(-) diff --git a/app/node/group/group.cpp b/app/node/group/group.cpp index 3c049ddde..795c7f969 100644 --- a/app/node/group/group.cpp +++ b/app/node/group/group.cpp @@ -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(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_)) { diff --git a/app/node/group/group.h b/app/node/group/group.h index 11e69b613..05e3b851a 100644 --- a/app/node/group/group.h +++ b/app/node/group/group.h @@ -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); diff --git a/app/widget/keyframeview/keyframeview.cpp b/app/widget/keyframeview/keyframeview.cpp index ca7d37594..0d5241e3c 100644 --- a/app/widget/keyframeview/keyframeview.cpp +++ b/app/widget/keyframeview/keyframeview.cpp @@ -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); diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp index c43c6f487..24428347f 100644 --- a/app/widget/nodeparamview/nodeparamview.cpp +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -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; iinputs()) { Node *n = node; - while (NodeGroup *g = dynamic_cast(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(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(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(sender()); + NodeInputPair nip = input_group_lookup_.value({static_cast(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; } diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h index 9e45f55f7..93044ad86 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.h +++ b/app/widget/nodeparamview/nodeparamviewitem.h @@ -116,6 +116,8 @@ private: NodeParamViewCheckBoxBehavior create_checkboxes_; + QHash input_group_lookup_; + /** * @brief The column to place the keyframe controls in * diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 1a8f7aff8..658b43118 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -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; iGetSplitValueAtTimeOnTrack(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;iSliderBase::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(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).toLongLong()); + static_cast(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).toLongLong()); break; } case NodeValue::kFloat: { - static_cast(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).toDouble()); + static_cast(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).toDouble()); break; } case NodeValue::kRational: { - static_cast(widgets_.first())->SetValue(input_.GetValueAtTime(node_time).value()); + static_cast(widgets_.first())->SetValue(GetInnerInput().GetValueAtTime(node_time).value()); break; } case NodeValue::kVec2: { - QVector2D vec2 = input_.GetValueAtTime(node_time).value(); + QVector2D vec2 = GetInnerInput().GetValueAtTime(node_time).value(); static_cast(widgets_.at(0))->SetValue(static_cast(vec2.x())); static_cast(widgets_.at(1))->SetValue(static_cast(vec2.y())); @@ -443,7 +441,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues() } case NodeValue::kVec3: { - QVector3D vec3 = input_.GetValueAtTime(node_time).value(); + QVector3D vec3 = GetInnerInput().GetValueAtTime(node_time).value(); static_cast(widgets_.at(0))->SetValue(static_cast(vec3.x())); static_cast(widgets_.at(1))->SetValue(static_cast(vec3.y())); @@ -452,7 +450,7 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues() } case NodeValue::kVec4: { - QVector4D vec4 = input_.GetValueAtTime(node_time).value(); + QVector4D vec4 = GetInnerInput().GetValueAtTime(node_time).value(); static_cast(widgets_.at(0))->SetValue(static_cast(vec4.x())); static_cast(widgets_.at(1))->SetValue(static_cast(vec4.y())); @@ -463,18 +461,18 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues() case NodeValue::kFile: { FileField* ff = static_cast(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(); + ManagedColor mc = GetInnerInput().GetValueAtTime(node_time).value(); - 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(widgets_.first()); - e->setTextPreservingCursor(input_.GetValueAtTime(node_time).toString()); + e->setTextPreservingCursor(GetInnerInput().GetValueAtTime(node_time).toString()); break; } case NodeValue::kBoolean: - static_cast(widgets_.first())->setChecked(input_.GetValueAtTime(node_time).toBool()); + static_cast(widgets_.first())->setChecked(GetInnerInput().GetValueAtTime(node_time).toBool()); break; case NodeValue::kFont: { QFontComboBox* fc = static_cast(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(widgets_.first()); cb->blockSignals(true); - int index = input_.GetValueAtTime(node_time).toInt(); + int index = GetInnerInput().GetValueAtTime(node_time).toInt(); for (int i=0; icount(); 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(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(widgets_.first()); + if (key == QStringLiteral("combo_str")) { + QComboBox* cb = static_cast(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()); + } } } diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h index aff076ffa..106244d7b 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h @@ -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 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 input_hierarchy_; QVector 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); + }; }