From c62b59965e369d0fad849cf7f2ca0c5d86e939f9 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 26 Dec 2019 16:28:38 +1100 Subject: [PATCH] updated nodes for new input structure Since all NodeInputs will generally only need their data type and default value set once, we place it all into the constructor for cleaner and easier to manage code. --- app/node/audio/pan/pan.cpp | 7 +- app/node/audio/volume/volume.cpp | 7 +- app/node/block/block.cpp | 18 +- app/node/block/clip/clip.cpp | 3 +- app/node/block/transition/transition.cpp | 6 +- app/node/distort/transform/transform.cpp | 13 +- app/node/input.cpp | 252 ++++++++++++++++++++--- app/node/input.h | 77 ++++++- app/node/input/media/media.cpp | 6 +- app/node/input/media/video/video.cpp | 3 +- app/node/inputarray.cpp | 7 +- app/node/inputarray.h | 4 +- app/node/metareader.cpp | 33 ++- app/node/output/timeline/timeline.cpp | 2 +- app/node/output/track/track.cpp | 8 +- app/node/output/viewer/viewer.cpp | 9 +- 16 files changed, 363 insertions(+), 92 deletions(-) diff --git a/app/node/audio/pan/pan.cpp b/app/node/audio/pan/pan.cpp index f09077296..44386de1a 100644 --- a/app/node/audio/pan/pan.cpp +++ b/app/node/audio/pan/pan.cpp @@ -2,15 +2,12 @@ PanNode::PanNode() { - samples_input_ = new NodeInput("samples_in"); - samples_input_->set_data_type(NodeParam::kSamples); + samples_input_ = new NodeInput("samples_in", NodeParam::kSamples); AddInput(samples_input_); - panning_input_ = new NodeInput("panning_in"); - panning_input_->set_data_type(NodeParam::kFloat); + panning_input_ = new NodeInput("panning_in", NodeParam::kFloat); panning_input_->set_minimum(-1); panning_input_->set_maximum(1); - panning_input_->set_value_at_time(0, 0); AddInput(panning_input_); } diff --git a/app/node/audio/volume/volume.cpp b/app/node/audio/volume/volume.cpp index b2d19899b..143e24dc8 100644 --- a/app/node/audio/volume/volume.cpp +++ b/app/node/audio/volume/volume.cpp @@ -2,15 +2,12 @@ VolumeNode::VolumeNode() { - samples_input_ = new NodeInput("samples_in"); - samples_input_->set_data_type(NodeParam::kSamples); + samples_input_ = new NodeInput("samples_in", NodeParam::kSamples); AddInput(samples_input_); - volume_input_ = new NodeInput("volume_in"); - volume_input_->set_data_type(NodeParam::kFloat); + volume_input_ = new NodeInput("volume_in", NodeParam::kFloat, 1); volume_input_->set_minimum(0); volume_input_->set_maximum(1); - volume_input_->set_value_at_time(0, 1); AddInput(volume_input_); } diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 2ba6046a9..efe476cc3 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -28,20 +28,20 @@ Block::Block() : previous_(nullptr), next_(nullptr) { - length_input_ = new NodeInput("length_in"); + length_input_ = new NodeInput("length_in", NodeParam::kRational); length_input_->SetConnectable(false); - length_input_->set_data_type(NodeParam::kRational); + length_input_->set_is_keyframable(false); AddInput(length_input_); connect(length_input_, SIGNAL(ValueChanged(const rational&, const rational&)), this, SLOT(LengthInputChanged())); - media_in_input_ = new NodeInput("media_in_in"); + media_in_input_ = new NodeInput("media_in_in", NodeParam::kRational); media_in_input_->SetConnectable(false); - media_in_input_->set_data_type(NodeParam::kRational); + media_in_input_->set_is_keyframable(false); AddInput(media_in_input_); - media_out_input_ = new NodeInput("media_out_in"); + media_out_input_ = new NodeInput("media_out_in", NodeParam::kRational); media_out_input_->SetConnectable(false); - media_out_input_->set_data_type(NodeParam::kRational); + media_out_input_->set_is_keyframable(false); AddInput(media_out_input_); // A block's length must be greater than 0 @@ -86,7 +86,7 @@ void Block::set_length(const rational &length) return; } - length_input_->set_value_at_time(0, QVariant::fromValue(length)); + length_input_->set_override_value(QVariant::fromValue(length)); } void Block::set_length_and_media_out(const rational &length) @@ -158,7 +158,7 @@ rational Block::media_in() const void Block::set_media_in(const rational &media_in) { - media_in_input_->set_value_at_time(0, QVariant::fromValue(media_in)); + media_in_input_->set_override_value(QVariant::fromValue(media_in)); } rational Block::media_out() const @@ -168,7 +168,7 @@ rational Block::media_out() const void Block::set_media_out(const rational &media_out) { - media_out_input_->set_value_at_time(0, QVariant::fromValue(media_out)); + media_out_input_->set_override_value(QVariant::fromValue(media_out)); } rational Block::media_length() const diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 3aad277f9..6517757c8 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -22,8 +22,7 @@ ClipBlock::ClipBlock() { - texture_input_ = new NodeInput("buffer_in"); - texture_input_->set_data_type(NodeInput::kBuffer); + texture_input_ = new NodeInput("buffer_in", NodeInput::kBuffer); AddInput(texture_input_); } diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index f6237fc45..eec961f78 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -2,12 +2,10 @@ TransitionBlock::TransitionBlock() { - out_block_input_ = new NodeInput("out_block_in"); - out_block_input_->set_data_type(NodeParam::kBuffer); + out_block_input_ = new NodeInput("out_block_in", NodeParam::kBuffer); AddInput(out_block_input_); - in_block_input_ = new NodeInput("in_block_in"); - in_block_input_->set_data_type(NodeParam::kBuffer); + in_block_input_ = new NodeInput("in_block_in", NodeParam::kBuffer); AddInput(in_block_input_); // A block's length must be greater than 0 diff --git a/app/node/distort/transform/transform.cpp b/app/node/distort/transform/transform.cpp index fba2d2a35..098918f26 100644 --- a/app/node/distort/transform/transform.cpp +++ b/app/node/distort/transform/transform.cpp @@ -25,21 +25,16 @@ TransformDistort::TransformDistort() { - position_input_ = new NodeInput("pos_in"); - position_input_->set_data_type(NodeParam::kVec2); + position_input_ = new NodeInput("pos_in", NodeParam::kVec2); AddInput(position_input_); - rotation_input_ = new NodeInput("rot_in"); - rotation_input_->set_data_type(NodeParam::kFloat); + rotation_input_ = new NodeInput("rot_in", NodeParam::kFloat); AddInput(rotation_input_); - scale_input_ = new NodeInput("scale_in"); - scale_input_->set_data_type(NodeParam::kVec2); - scale_input_->set_value_at_time(0, QVector2D(100.0f, 100.0f)); + scale_input_ = new NodeInput("scale_in", NodeParam::kVec2, QVector2D(100.0f, 100.0f)); AddInput(scale_input_); - anchor_input_ = new NodeInput("anchor_in"); - anchor_input_->set_data_type(NodeParam::kVec2); + anchor_input_ = new NodeInput("anchor_in", NodeParam::kVec2); AddInput(anchor_input_); } diff --git a/app/node/input.cpp b/app/node/input.cpp index e7bbf73fc..1160c71cc 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -25,8 +25,9 @@ #include "output.h" #include "inputarray.h" -NodeInput::NodeInput(const QString& id) : +NodeInput::NodeInput(const QString& id, const DataType &type, const QVariant &default_value) : NodeParam(id), + data_type_(type), keyframable_(true), keyframing_(false), dependent_(true), @@ -34,7 +35,7 @@ NodeInput::NodeInput(const QString& id) : has_maximum_(false) { // Have at least one keyframe/value active at any time - keyframes_.append(NodeKeyframe()); + insert_keyframe(std::make_shared(0, default_value, NodeKeyframe::kLinear)); } bool NodeInput::IsArray() @@ -61,11 +62,6 @@ const NodeParam::DataType &NodeInput::data_type() const return data_type_; } -void NodeInput::set_data_type(const NodeParam::DataType &type) -{ - data_type_ = type; -} - NodeOutput *NodeInput::get_connected_output() const { if (!edges_.isEmpty()) { @@ -89,41 +85,41 @@ Node *NodeInput::get_connected_node() const QVariant NodeInput::get_value_at_time(const rational &time) const { if (is_keyframing()) { - if (keyframes_.first().time() >= time) { + if (keyframes_.first()->time() >= time) { // This time precedes any keyframe, so we just return the first value - return keyframes_.first().value(); + return keyframes_.first()->value(); } - if (keyframes_.last().time() <= time) { + if (keyframes_.last()->time() <= time) { // This time is after any keyframes so we return the last value - return keyframes_.last().value(); + return keyframes_.last()->value(); } // If we're here, the time must be somewhere in between the keyframes for (int i=0;itime() == time || data_type() != kFloat // FIXME: Expand this to other types that can be interpolated - || (before.time() < time && before.type() == NodeKeyframe::kHold)) { + || (before->time() < time && before->type() == NodeKeyframe::kHold)) { // Time == keyframe time, so value is precise - return before.value(); + return before->value(); - } else if (before.time() < time && after.time() > time) { + } else if (before->time() < time && after->time() > time) { // We must interpolate between these keyframes - if (before.type() == NodeKeyframe::kBezier && after.type() == NodeKeyframe::kBezier) { + if (before->type() == NodeKeyframe::kBezier && after->type() == NodeKeyframe::kBezier) { // FIXME: Perform a cubic bezier interpolation - } else if (before.type() == NodeKeyframe::kLinear && after.type() == NodeKeyframe::kBezier) { + } else if (before->type() == NodeKeyframe::kLinear && after->type() == NodeKeyframe::kBezier) { // FIXME: Perform a quadratic bezier interpolation with anchors from the AFTER keyframe - } else if (before.type() == NodeKeyframe::kLinear && after.type() == NodeKeyframe::kBezier) { + } else if (before->type() == NodeKeyframe::kLinear && after->type() == NodeKeyframe::kBezier) { // FIXME: Perform a quadratic bezier interpolation with anchors from the BEFORE keyframe } else { // To have arrived here, the keyframes must both be linear - qreal period_progress = (time.toDouble() - before.time().toDouble()) / (after.time().toDouble() - before.time().toDouble()); - qreal interpolated_value = lerp(before.value().toDouble(), after.value().toDouble(), period_progress); + qreal period_progress = (time.toDouble() - before->time().toDouble()) / (after->time().toDouble() - before->time().toDouble()); + qreal interpolated_value = lerp(before->value().toDouble(), after->value().toDouble(), period_progress); return interpolated_value; } @@ -131,14 +127,167 @@ QVariant NodeInput::get_value_at_time(const rational &time) const } } - return keyframes_.first().value(); + return keyframes_.first()->value(); } -void NodeInput::set_value_at_time(const rational &time, const QVariant &value) +NodeKeyframePtr NodeInput::get_keyframe_at_time(const rational &time) const +{ + if (!is_keyframing()) { + return nullptr; + } + + foreach (NodeKeyframePtr key, keyframes_) { + if (key->time() == time) { + return key; + } + } + + return nullptr; +} + +NodeKeyframePtr NodeInput::get_closest_keyframe_to_time(const rational &time) const +{ + if (!is_keyframing()) { + return nullptr; + } + + if (time <= keyframes_.first()->time()) { + return keyframes_.first(); + } + + if (time >= keyframes_.last()->time()) { + return keyframes_.last(); + } + + for (int i=1;itime() <= time && next_key->time() >= time) { + // Return whichever is closer + rational prev_diff = time - prev_key->time(); + rational next_diff = next_key->time() - time; + + if (next_diff < prev_diff) { + return next_key; + } else { + return prev_key; + } + } + } + + return nullptr; +} + +void NodeInput::insert_keyframe(NodeKeyframePtr key) +{ + insert_keyframe_internal(key); + + connect(key.get(), &NodeKeyframe::TimeChanged, this, &NodeInput::KeyframeTimeChanged); + connect(key.get(), &NodeKeyframe::ValueChanged, this, &NodeInput::KeyframeValueChanged); + + emit KeyframeAdded(key); +} + +void NodeInput::remove_keyframe(NodeKeyframePtr key) +{ + Q_ASSERT(keyframes_.size() > 1); + + disconnect(key.get(), &NodeKeyframe::TimeChanged, this, &NodeInput::KeyframeTimeChanged); + disconnect(key.get(), &NodeKeyframe::ValueChanged, this, &NodeInput::KeyframeValueChanged); + + keyframes_.removeOne(key); + + emit KeyframeRemoved(key); +} + +void NodeInput::KeyframeTimeChanged() +{ + NodeKeyframe* key = static_cast(sender()); + int keyframe_index = FindIndexOfKeyframeFromRawPtr(key); + + Q_ASSERT(keyframe_index > -1); + + if ((keyframe_index > 0 && keyframes_.at(keyframe_index - 1)->time() > key->time()) + || (keyframe_index < keyframes_.size() - 1 && keyframes_.at(keyframe_index + 1)->time() < key->time())) { + // This keyframe needs resorting, store it and remove it from the list + NodeKeyframePtr key_shared_ptr = keyframes_.at(keyframe_index); + keyframes_.removeAt(keyframe_index); + + // Automatically insertion sort + insert_keyframe_internal(key_shared_ptr); + } +} + +void NodeInput::KeyframeValueChanged() +{ + //NodeKeyframe* key = static_cast(sender()); + //int keyframe_index = FindIndexOfKeyframeFromRawPtr(key); + + // FIXME: Finish this partial stub + emit ValueChanged(RATIONAL_MIN, RATIONAL_MAX); +} + +int NodeInput::FindIndexOfKeyframeFromRawPtr(NodeKeyframe *raw_ptr) const +{ + for (int i=0;itime() != key->time()); + + if (compare->time() > key->time()) { + keyframes_.insert(i, key); + return; + } + } + + keyframes_.append(key); +} + +bool NodeInput::has_keyframe_at_time(const rational &time) const +{ + // If we aren't keyframing, there definitely isn't a keyframe at a given time + if (!is_keyframing()) { + return false; + } + + // Loop through keyframes to see if any match + foreach (NodeKeyframePtr key, keyframes_) { + if (key->time() == time) { + return true; + } + } + + // None match + return false; +} + +/*void NodeInput::set_default_value(const QVariant &value) { if (parentNode() != nullptr) parentNode()->LockUserInput(); + set_is_keyframing(false); + keyframes_.clear(); + keyframes_.append(NodeKeyframe(0, value, NodeKeyframe::kLinear)); + + if (parentNode() != nullptr) + parentNode()->UnlockUserInput(); + + emit ValueChanged(RATIONAL_MIN, RATIONAL_MAX); + // We set up these variables in advance (see end of function) bool signal_vc = false; TimeRange signal_vc_range; @@ -230,8 +379,49 @@ void NodeInput::set_value_at_time(const rational &time, const QVariant &value) // tries to relock this node before it's unlocked here if (signal_vc) emit ValueChanged(signal_vc_range.in(), signal_vc_range.out()); + +}*/ + +/*void NodeInput::set_keyframe_data(const QList keyframes) +{ + keyframes_ = keyframes; } +void NodeInput::insert_keyframe(const NodeKeyframe &key) +{ + Q_ASSERT(is_keyframing()); + + for (int i=0;i key.time()) { + keyframes_.insert(i, key); + emit KeyframeAdded(key); + return; + } + } + + keyframes_.append(key); + emit KeyframeAdded(key); +} + +void NodeInput::remove_keyframe_at_time(const rational &time) +{ + for (int i=0;iset_value(value); +} + +const QList &NodeInput::keyframes() const +{ + return keyframes_; +} + void NodeInput::set_is_keyframable(bool k) { keyframable_ = k; diff --git a/app/node/input.h b/app/node/input.h index 35b967f5a..1b8b9fb6d 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -40,7 +40,7 @@ public: * saving/loading data from this Node so that parameter order can be changed without issues loading data saved by an * older version. This of course assumes that parameters don't change their ID. */ - NodeInput(const QString &id); + NodeInput(const QString &id, const DataType& type, const QVariant& default_value = 0); virtual bool IsArray(); @@ -58,7 +58,6 @@ public: * connected to it. */ const DataType& data_type() const; - void set_data_type(const DataType& type); /** * @brief If this input is connected to an output, retrieve the output parameter @@ -84,9 +83,37 @@ public: QVariant get_value_at_time(const rational& time) const; /** - * @brief Sets what value should be seen at a specific time + * @brief Retrieve the keyframe object at a given time + * + * @return + * + * The keyframe object at this time or nullptr if there isn't one or if is_keyframing() is false. */ - void set_value_at_time(const rational& time, const QVariant& value); + NodeKeyframePtr get_keyframe_at_time(const rational& time) const; + + /** + * @brief Gets the closest keyframe to a time + * + * If is_keyframing() is false, this will return nullptr. Otherwise, this is guaranteed to return a keyframe. + */ + NodeKeyframePtr get_closest_keyframe_to_time(const rational& time) const; + + /** + * @brief Inserts a keyframe at the given time and returns a reference to it + */ + void insert_keyframe(NodeKeyframePtr key); + + /** + * @brief Removes the keyframe + */ + void remove_keyframe(NodeKeyframePtr key); + + /** + * @brief Return whether a keyframe exists at this time + * + * If is_keyframing() is false, this will always return false. + */ + bool has_keyframe_at_time(const rational &time) const; /** * @brief Return whether keyframing is enabled on this input or not @@ -103,6 +130,18 @@ public: */ bool is_keyframable() const; + /** + * @brief Replaces all values with this value + * + * This can only be used on inputs where keyframing is disabled. + */ + void set_override_value(const QVariant& value); + + /** + * @brief Return list of keyframes in this parameter + */ + const QList& keyframes() const; + /** * @brief Set whether this input can be keyframed or not */ @@ -124,7 +163,24 @@ public: signals: void ValueChanged(const rational& start, const rational& end); + void KeyframeEnableChanged(bool); + + void KeyframeAdded(NodeKeyframePtr key); + + void KeyframeRemoved(NodeKeyframePtr key); + private: + /** + * @brief We use Qt signals/slots for keyframe communication but store them as shared ptrs. This function converts + * a raw ptr to a list index + */ + int FindIndexOfKeyframeFromRawPtr(NodeKeyframe* raw_ptr) const; + + /** + * @brief Internal insert function, automatically does an insertion sort based on the keyframe's time + */ + void insert_keyframe_internal(NodeKeyframePtr key); + /** * @brief Internal list of accepted data types * @@ -143,7 +199,7 @@ private: * All internal/user-defined data is stored in this array. Even if keyframing is not enabled, this array will contain * one entry which will be used, and its time value will be ignored. */ - QList keyframes_; + QList keyframes_; /** * @brief Internal keyframing enabled setting @@ -175,6 +231,17 @@ private: */ QVariant maximum_; +private slots: + /** + * @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time + */ + void KeyframeTimeChanged(); + + /** + * @brief Slot when a keyframe's value changes to signal that the cache needs updating + */ + void KeyframeValueChanged(); + }; #endif // NODEINPUT_H diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index eaa07d801..624068e13 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -23,9 +23,9 @@ MediaInput::MediaInput() : connected_footage_(nullptr) { - footage_input_ = new NodeInput("footage_in"); - footage_input_->set_data_type(NodeInput::kFootage); + footage_input_ = new NodeInput("footage_in", NodeInput::kFootage); footage_input_->SetConnectable(false); + footage_input_->set_is_keyframable(false); connect(footage_input_, SIGNAL(ValueChanged(const rational&, const rational&)), this, SLOT(FootageChanged())); AddInput(footage_input_); } @@ -37,7 +37,7 @@ StreamPtr MediaInput::footage() void MediaInput::SetFootage(StreamPtr f) { - footage_input_->set_value_at_time(0, QVariant::fromValue(f)); + footage_input_->set_override_value(QVariant::fromValue(f)); } void MediaInput::Retranslate() diff --git a/app/node/input/media/video/video.cpp b/app/node/input/media/video/video.cpp index 002892921..abc5bf9bd 100644 --- a/app/node/input/media/video/video.cpp +++ b/app/node/input/media/video/video.cpp @@ -11,8 +11,7 @@ VideoInput::VideoInput() { - matrix_input_ = new NodeInput("matrix_in"); - matrix_input_->set_data_type(NodeInput::kMatrix); + matrix_input_ = new NodeInput("matrix_in", NodeInput::kMatrix); AddInput(matrix_input_); } diff --git a/app/node/inputarray.cpp b/app/node/inputarray.cpp index af5680bb7..413b1d6fc 100644 --- a/app/node/inputarray.cpp +++ b/app/node/inputarray.cpp @@ -2,8 +2,9 @@ #include "node.h" -NodeInputArray::NodeInputArray(const QString &id) : - NodeInput(id) +NodeInputArray::NodeInputArray(const QString &id, const DataType &type, const QVariant &default_value) : + NodeInput(id, type, default_value), + default_value_(default_value) { } @@ -51,7 +52,7 @@ void NodeInputArray::SetSize(int size, bool lock) Q_ASSERT(!parentNode()->HasParamWithID(sub_id)); - NodeInput* new_param = new NodeInput(sub_id); + NodeInput* new_param = new NodeInput(sub_id, data_type(), default_value_); new_param->setParent(this); sub_params_.replace(i, new_param); diff --git a/app/node/inputarray.h b/app/node/inputarray.h index 51035d7df..02f0eb125 100644 --- a/app/node/inputarray.h +++ b/app/node/inputarray.h @@ -7,7 +7,7 @@ class NodeInputArray : public NodeInput { Q_OBJECT public: - NodeInputArray(const QString &id); + NodeInputArray(const QString &id, const DataType& type, const QVariant& default_value = 0); virtual bool IsArray() override; @@ -34,6 +34,8 @@ signals: private: QVector sub_params_; + QVariant default_value_; + }; #endif // INPUTARRAY_H diff --git a/app/node/metareader.cpp b/app/node/metareader.cpp index 36e50b377..aeba47dbb 100644 --- a/app/node/metareader.cpp +++ b/app/node/metareader.cpp @@ -193,12 +193,11 @@ void NodeMetaReader::XMLReadParam(QXmlStreamReader *reader) return; } - NodeInput* input = new NodeInput(param_id); - input->set_data_type(param_type); - - if (is_iterative) { - iteration_input_ = input; - } + QVariant default_val; + QVariant min_val; + bool has_min = false; + QVariant max_val; + bool has_max = false; // Traverse through param contents for more data while (!reader->atEnd() && !(reader->isEndElement() && reader->name() == "param")) { @@ -218,15 +217,31 @@ void NodeMetaReader::XMLReadParam(QXmlStreamReader *reader) XMLReadLanguageString(reader, ¶m_names_[param_id]); } else if (reader->name() == "default") { - input->set_value_at_time(0, reader->readElementText()); + default_val = reader->readElementText(); } else if (reader->name() == "min") { - input->set_minimum(reader->readElementText()); + has_min = true; + min_val = reader->readElementText(); } else if (reader->name() == "max") { - input->set_maximum(reader->readElementText()); + has_max = true; + max_val = reader->readElementText(); } } } + NodeInput* input = new NodeInput(param_id, param_type, default_val); + + if (has_min) { + input->set_minimum(min_val); + } + + if (has_max) { + input->set_maximum(max_val); + } + + if (is_iterative) { + iteration_input_ = input; + } + inputs_.append(input); } diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index 03603c403..59f79c40e 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -34,7 +34,7 @@ TimelineOutput::TimelineOutput() for (int i=0;iset_data_type(NodeParam::kBoolean); + muted_input_ = new NodeInput("muted_in", NodeParam::kBoolean); + muted_input_->set_is_keyframable(false); AddInput(muted_input_); // Set default height @@ -365,7 +365,7 @@ void TrackOutput::SetTrackName(const QString &name) void TrackOutput::SetMuted(bool e) { - muted_input_->set_value_at_time(0, e); + muted_input_->set_override_value(e); InvalidateCache(0, track_length()); } diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index f5b527182..b0a583669 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -22,16 +22,13 @@ ViewerOutput::ViewerOutput() { - texture_input_ = new NodeInput("tex_in"); - texture_input_->set_data_type(NodeInput::kTexture); + texture_input_ = new NodeInput("tex_in", NodeInput::kTexture); AddInput(texture_input_); - samples_input_ = new NodeInput("samples_in"); - samples_input_->set_data_type(NodeInput::kSamples); + samples_input_ = new NodeInput("samples_in", NodeInput::kSamples); AddInput(samples_input_); - length_input_ = new NodeInput("length_in"); - length_input_->set_data_type(NodeInput::kRational); + length_input_ = new NodeInput("length_in", NodeInput::kRational); AddInput(length_input_); // Create UUID for this node