diff --git a/app/audio/audiovisualwaveform.cpp b/app/audio/audiovisualwaveform.cpp index e13effd5c..f6f0e4db4 100644 --- a/app/audio/audiovisualwaveform.cpp +++ b/app/audio/audiovisualwaveform.cpp @@ -90,6 +90,15 @@ void AudioVisualWaveform::OverwriteSamplesFromMipmap(const AudioVisualWaveform:: input_length = samples_length; } +void AudioVisualWaveform::ValidateVirtualStart(const rational &new_start) +{ + if (length_ == 0) { + virtual_start_ = new_start; + } else if (virtual_start_ > new_start) { + TrimIn(new_start - virtual_start_); + } +} + void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int sample_rate, const rational &start) { if (!channels_) { @@ -97,18 +106,12 @@ void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int samp return; } - // Old less optimized code. Keeping this around as a reference, but the below code is at least - // 10x faster so this shouldn't be used in production. - // - // size_t input_start, input_length; - // for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { - // OverwriteSamplesFromBuffer(samples, sample_rate, start, it->first.toDouble(), it->second, input_start, input_length); - // } + ValidateVirtualStart(start); // Process the largest mipmap directly for the samples auto current_mipmap = mipmapped_data_.rbegin(); size_t input_start, input_length; - OverwriteSamplesFromBuffer(samples, sample_rate, start, current_mipmap->first.toDouble(), current_mipmap->second, input_start, input_length); + OverwriteSamplesFromBuffer(samples, sample_rate, start - virtual_start_, current_mipmap->first.toDouble(), current_mipmap->second, input_start, input_length); while (true) { // For each smaller mipmap, we just process from the mipmap before it, making each one @@ -120,7 +123,7 @@ void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int samp } OverwriteSamplesFromMipmap(previous_mipmap->second, previous_mipmap->first.toDouble(), - input_start, input_length, start, current_mipmap->first.toDouble(), + input_start, input_length, start - virtual_start_, current_mipmap->first.toDouble(), current_mipmap->second); } @@ -130,6 +133,8 @@ void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int samp void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, const rational &dest, const rational& offset, const rational& length) { + ValidateVirtualStart(dest); + for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { rational rate = it->first; @@ -139,7 +144,7 @@ void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, const r double rate_dbl = rate.toDouble(); // Get our destination sample - size_t our_start_index = time_to_samples(dest, rate_dbl); + size_t our_start_index = time_to_samples(dest - virtual_start_, rate_dbl); // Get our source sample size_t their_start_index = time_to_samples(offset, rate_dbl); @@ -172,6 +177,8 @@ void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, const r void AudioVisualWaveform::OverwriteSilence(const rational &start, const rational &length) { + ValidateVirtualStart(start); + for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { rational rate = it->first; @@ -180,7 +187,7 @@ void AudioVisualWaveform::OverwriteSilence(const rational &start, const rational double rate_dbl = rate.toDouble(); // Get our destination sample - size_t our_start_index = time_to_samples(start, rate_dbl); + size_t our_start_index = time_to_samples(start - virtual_start_, rate_dbl); size_t our_length_index = time_to_samples(length, rate_dbl); size_t our_end_index = our_start_index + our_length_index; @@ -190,6 +197,8 @@ void AudioVisualWaveform::OverwriteSilence(const rational &start, const rational memset(reinterpret_cast(our_arr.data()) + our_start_index * sizeof(SamplePerChannel), 0, our_length_index * sizeof(SamplePerChannel)); } + + length_ = qMax(length_, start + length); } void AudioVisualWaveform::TrimIn(rational length) @@ -198,6 +207,8 @@ void AudioVisualWaveform::TrimIn(rational length) return; } + virtual_start_ += length; + bool negative = (length < 0); if (negative) { length = -length; @@ -225,9 +236,9 @@ void AudioVisualWaveform::TrimIn(rational length) AudioVisualWaveform AudioVisualWaveform::Mid(const rational &offset) const { - AudioVisualWaveform mid = *this; + AudioVisualWaveform mid = *this; - mid.TrimIn(offset); + mid.TrimIn(offset - virtual_start_); return mid; } @@ -236,7 +247,7 @@ AudioVisualWaveform AudioVisualWaveform::Mid(const rational &offset, const ratio { AudioVisualWaveform mid = *this; - mid.TrimRange(offset, length); + mid.TrimRange(offset - virtual_start_, length); return mid; } @@ -273,7 +284,7 @@ AudioVisualWaveform::Sample AudioVisualWaveform::GetSummaryFromTime(const ration double rate_dbl = using_mipmap->first.toDouble(); - size_t start_sample = time_to_samples(start, rate_dbl); + size_t start_sample = time_to_samples(start - virtual_start_, rate_dbl); size_t sample_length = time_to_samples(length, rate_dbl); const Sample &mipmap_data = using_mipmap->second; @@ -421,7 +432,7 @@ void AudioVisualWaveform::DrawWaveform(QPainter *painter, const QRect& rect, con double rate_dbl = rate.toDouble(); const Sample& arr = using_mipmap->second; - size_t start_sample_index = samples.time_to_samples(start_time, rate_dbl); + size_t start_sample_index = samples.time_to_samples(start_time - samples.virtual_start_, rate_dbl); if (start_sample_index >= arr.size()) { return; diff --git a/app/audio/audiovisualwaveform.h b/app/audio/audiovisualwaveform.h index 8591ea11b..8f34961a1 100644 --- a/app/audio/audiovisualwaveform.h +++ b/app/audio/audiovisualwaveform.h @@ -123,6 +123,10 @@ private: std::map::const_iterator GetMipmapForScale(double scale) const; + void ValidateVirtualStart(const rational &new_start); + + rational virtual_start_; + int channels_; std::map mipmapped_data_; diff --git a/app/common/timerange.h b/app/common/timerange.h index b6235f9b8..8fc55872e 100644 --- a/app/common/timerange.h +++ b/app/common/timerange.h @@ -126,6 +126,17 @@ public: return false; } + bool OverlapsWith(const TimeRange& r, bool in_inclusive = true, bool out_inclusive = true) const + { + for (const TimeRange &range : array_) { + if (range.OverlapsWith(r, in_inclusive, out_inclusive)) { + return true; + } + } + + return false; + } + bool isEmpty() const { return array_.isEmpty(); diff --git a/app/node/generator/shape/generatorwithmerge.cpp b/app/node/generator/shape/generatorwithmerge.cpp index 8622c1881..93f8bcde3 100644 --- a/app/node/generator/shape/generatorwithmerge.cpp +++ b/app/node/generator/shape/generatorwithmerge.cpp @@ -59,7 +59,7 @@ void GeneratorWithMerge::PushMergableJob(const NodeValueRow &value, TexturePtr j merge.SetShaderID(QStringLiteral("mrg")); merge.Insert(MergeNode::kBaseIn, value[kBaseInput]); - merge.Insert(MergeNode::kBlendIn, NodeValue(NodeValue::kTexture, base->toJob(*job->job()), this)); + merge.Insert(MergeNode::kBlendIn, NodeValue(NodeValue::kTexture, job, this)); table->Push(NodeValue::kTexture, base->toJob(merge), this); } else { diff --git a/app/render/audiowaveformcache.cpp b/app/render/audiowaveformcache.cpp index 5ed1ee280..4f9870759 100644 --- a/app/render/audiowaveformcache.cpp +++ b/app/render/audiowaveformcache.cpp @@ -22,113 +22,94 @@ namespace olive { +#define super PlaybackCache + AudioWaveformCache::AudioWaveformCache(QObject *parent) : - PlaybackCache{parent} + super{parent} { + waveforms_ = std::make_shared(); } void AudioWaveformCache::WriteWaveform(const TimeRange &range, const TimeRangeList &valid_ranges, const AudioVisualWaveform *waveform) { // Write each valid range to the segments foreach (const TimeRange& r, valid_ranges) { -#ifdef AVW_USE_LIST - // Write visual - TimeRangeList::util_remove(&waveforms_, r); - if (waveform) { - TimeRangeWithWaveform wv = r; - rational local_start = r.in() - range.in(); - if (local_start != 0) { - wv.waveform = waveform->Mid(local_start, r.length()); - } else { - wv.waveform = *waveform; - } - waveforms_.append(wv); + waveforms_->OverwriteSums(*waveform, r.in(), r.in() - range.in(), r.length()); } -#else - if (waveform) { - waveforms_.OverwriteSums(*waveform, r.in(), r.in() - range.in(), r.length()); - } -#endif Validate(r); } } +void DrawSubRect(QPainter *painter, const QRect &rect, const double &scale, const TimeRange &wave_range, const AudioVisualWaveform &waveform, const TimeRange &subrange) +{ + // Find start time of passthrough + TimeRange intersect = wave_range.Intersected(subrange); + + // Create new rect that starts at the offset of pass_start from start_time + // Set rect width to either length of passthrough or until the end + QRect pass_rect(rect.x() + (intersect.in() - wave_range.in()).toDouble() * scale, + rect.y(), + intersect.length().toDouble() * scale, + rect.height()); + + // Draw waveform with this info + AudioVisualWaveform::DrawWaveform(painter, pass_rect, scale, waveform, intersect.in()); +} + void AudioWaveformCache::Draw(QPainter *painter, const QRect &rect, const double &scale, const rational &start_time) const { - rational end = start_time + rational::fromDouble(rect.width() / scale); - TimeRange draw_range(start_time, end); + if (!passthroughs_.empty()) { + TimeRange wave_range(start_time, start_time + rational::fromDouble(rect.width() / scale)); + TimeRangeList draw_range = {wave_range}; + for (const WaveformPassthrough &p : passthroughs_) { + if (draw_range.OverlapsWith(p, true, false)) { + DrawSubRect(painter, rect, scale, wave_range, *p.waveform, p); -#ifdef AVW_USE_LIST - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - if (wv.OverlapsWith(draw_range)) { - rational substart = std::max(wv.in(), draw_range.in()); - rational subend = std::min(wv.out(), draw_range.out()); - - QRect subrect = rect; - subrect.setLeft(subrect.left() + (substart - draw_range.in()).toDouble()*scale); - subrect.setWidth((subend - substart).toDouble()*scale); - - rational local_start = substart - wv.in(); - AudioVisualWaveform::DrawWaveform(painter, subrect, scale, wv.waveform, local_start); + // Remove this range + draw_range.remove(p); + } } + + for (const TimeRange &r : draw_range) { + DrawSubRect(painter, rect, scale, wave_range, *waveforms_, r); + } + } else { + AudioVisualWaveform::DrawWaveform(painter, rect, scale, *waveforms_, start_time); } -#else - AudioVisualWaveform::DrawWaveform(painter, rect, scale, waveforms_, start_time); -#endif } AudioVisualWaveform::Sample AudioWaveformCache::GetSummaryFromTime(const rational &start, const rational &length) const { -#ifdef AVW_USE_LIST - QMap sample; - - TimeRange acquire(start, start+length); - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - if (wv.OverlapsWith(acquire)) { - TimeRange this_range = wv.Intersected(acquire); - auto sum = wv.waveform.GetSummaryFromTime(this_range.in() - wv.in(), this_range.length()); - sample.insert(this_range.in(), sum); - } - } - - AudioVisualWaveform::Sample result; - - for (auto it=sample.cbegin(); it!=sample.cend(); it++) { - result.insert(result.end(), it.value().begin(), it.value().end()); - } - - return result; -#else - return waveforms_.GetSummaryFromTime(start, length); -#endif + return waveforms_->GetSummaryFromTime(start, length); } rational AudioWaveformCache::length() const { -#ifdef AVW_USE_LIST - rational len = 0; - - foreach (const TimeRangeWithWaveform &wv, waveforms_) { - len = std::max(len, wv.out()); - } - - return len; -#else - return waveforms_.length(); -#endif + return waveforms_->length(); } void AudioWaveformCache::SetPassthrough(PlaybackCache *cache) { AudioWaveformCache *c = static_cast(cache); - waveforms_ = c->waveforms_; + for (const TimeRange &r : c->GetValidatedRanges()) { - Validate(r); + WaveformPassthrough t = r; + t.waveform = c->waveforms_; + passthroughs_.append(t); } + passthroughs_.append(c->passthroughs_); + SetParameters(c->GetParameters()); SetSavingEnabled(c->IsSavingEnabled()); } +void AudioWaveformCache::InvalidateEvent(const TimeRange& range) +{ + TimeRangeList::util_remove(&passthroughs_, range); + + super::InvalidateEvent(range); +} + } diff --git a/app/render/audiowaveformcache.h b/app/render/audiowaveformcache.h index a1a6dcfe5..95a498d4f 100644 --- a/app/render/audiowaveformcache.h +++ b/app/render/audiowaveformcache.h @@ -24,8 +24,6 @@ #include "audio/audiovisualwaveform.h" #include "playbackcache.h" -//#define AVW_USE_LIST - namespace olive { class AudioWaveformCache : public PlaybackCache @@ -40,7 +38,7 @@ public: void SetParameters(const AudioParams &p) { params_ = p; - waveforms_.set_channel_count(p.channel_count()); + waveforms_->set_channel_count(p.channel_count()); } void Draw(QPainter* painter, const QRect &rect, const double &scale, const rational &start_time) const; @@ -51,45 +49,28 @@ public: virtual void SetPassthrough(PlaybackCache *cache) override; +protected: + virtual void InvalidateEvent(const TimeRange& range) override; + private: -#ifdef AVW_USE_LIST - class TimeRangeWithWaveform : public TimeRange - { - public: - TimeRangeWithWaveform() = default; - TimeRangeWithWaveform(const TimeRange &r) : - TimeRange(r) - { - } + using WaveformPtr = std::shared_ptr; - void set_in(const rational& in) - { - waveform.TrimIn(in - this->in()); - TimeRange::set_in(in); - } - - void set_out(const rational& out) - { - waveform.Resize(out - this->in()); - TimeRange::set_out(out); - } - - void set_range(const rational& in, const rational& out) - { - waveform.TrimRange(in, out-in); - TimeRange::set_range(in, out); - } - - AudioVisualWaveform waveform; - }; - - QVector waveforms_; -#else - AudioVisualWaveform waveforms_; -#endif + WaveformPtr waveforms_; AudioParams params_; + class WaveformPassthrough : public TimeRange + { + public: + WaveformPassthrough(const TimeRange &r) : + TimeRange(r) + {} + + WaveformPtr waveform; + }; + + QVector passthroughs_; + }; } diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index 13966a892..32b1a9574 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -55,7 +55,11 @@ RenderManager::RenderManager(QObject *parent) : video_thread_ = CreateThread(context_); dry_run_thread_ = CreateThread(); audio_thread_ = CreateThread(); - waveform_thread_ = CreateThread(); + + waveform_threads_.resize(QThread::idealThreadCount()); + for (size_t i=0; isetProperty("mode", params.mode); if (params.generate_waveforms) { - waveform_thread_->AddTicket(ticket); + size_t thread_index = last_waveform_thread_%waveform_threads_.size(); + RenderThread *thread = waveform_threads_[thread_index]; + thread->AddTicket(ticket); + last_waveform_thread_++; } else { audio_thread_->AddTicket(ticket); } diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index da52892c4..25dbae894 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -232,7 +232,9 @@ private: RenderThread *video_thread_; RenderThread *dry_run_thread_; RenderThread *audio_thread_; - RenderThread *waveform_thread_; + + std::vector waveform_threads_; + size_t last_waveform_thread_; std::list render_threads_; diff --git a/app/widget/colorwheel/colorvalueswidget.cpp b/app/widget/colorwheel/colorvalueswidget.cpp index e125decd5..4ba54df49 100644 --- a/app/widget/colorwheel/colorvalueswidget.cpp +++ b/app/widget/colorwheel/colorvalueswidget.cpp @@ -440,6 +440,10 @@ void ColorValuesTab::HexChanged(const QString &s) uint32_t hex = s.toULong(&ok, 16); if (ok) { + if (hex >= 0x1000000) { + hex >>= 8; + } + uint32_t r = (hex & 0xFF0000) >> 16; uint32_t g = (hex & 0x00FF00) >> 8; uint32_t b = (hex & 0x0000FF); diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp index 5a6254bd5..b0d6f1618 100644 --- a/app/widget/nodeparamview/nodeparamview.cpp +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -76,7 +76,7 @@ NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) : // Create contexts for three different types context_items_.resize(Track::kCount + 1); for (int i=0; isetVisible(false); connect(c, &NodeParamViewContext::AboutToDeleteItem, this, &NodeParamView::ItemAboutToBeRemoved, Qt::DirectConnection); @@ -245,8 +245,6 @@ void NodeParamView::DeselectNodes(const QVector &nodes) void NodeParamView::UpdateContexts() { - //TIME_THIS_FUNCTION; - bool changes_made = false; foreach (Node *ctx, current_contexts_) { @@ -735,7 +733,7 @@ void NodeParamView::AddNode(Node *n, Node *ctx, NodeParamViewContext *context) return; } - NodeParamViewItem* item = new NodeParamViewItem(n, IsGroupMode() ? kCheckBoxesOnNonConnected : kNoCheckBoxes, context); + NodeParamViewItem* item = new NodeParamViewItem(n, IsGroupMode() ? kCheckBoxesOnNonConnected : kNoCheckBoxes, context->GetDockArea()); connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::SetTimeAndSignal); connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::SelectNodeFromConnectedLink); diff --git a/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp b/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp index 824452f4b..937037219 100644 --- a/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp +++ b/app/widget/nodeparamview/nodeparamviewconnectedlabel.cpp @@ -50,13 +50,13 @@ NodeParamViewConnectedLabel::NodeParamViewConnectedLabel(const NodeInput &input, label_layout->setMargin(0); layout->addLayout(label_layout); - CollapseButton *collapse_btn = new CollapseButton(); + CollapseButton *collapse_btn = new CollapseButton(this); collapse_btn->setChecked(false); label_layout->addWidget(collapse_btn); - label_layout->addWidget(new QLabel(tr("Connected to"))); + label_layout->addWidget(new QLabel(tr("Connected to"), this)); - connected_to_lbl_ = new ClickableLabel(); + connected_to_lbl_ = new ClickableLabel(this); connected_to_lbl_->setCursor(Qt::PointingHandCursor); connected_to_lbl_->setContextMenuPolicy(Qt::CustomContextMenu); connect(connected_to_lbl_, &ClickableLabel::MouseClicked, this, &NodeParamViewConnectedLabel::ConnectionClicked); @@ -80,18 +80,23 @@ NodeParamViewConnectedLabel::NodeParamViewConnectedLabel(const NodeInput &input, connect(input_.node(), &Node::InputConnected, this, &NodeParamViewConnectedLabel::InputConnected); connect(input_.node(), &Node::InputDisconnected, this, &NodeParamViewConnectedLabel::InputDisconnected); - // Set up table area - value_tree_ = new NodeValueTree(); - value_tree_->setVisible(false); - layout->addWidget(value_tree_); + // Creating the tree is expensive, hold off until the user specifically requests it + value_tree_ = nullptr; connect(collapse_btn, &CollapseButton::toggled, this, &NodeParamViewConnectedLabel::SetValueTreeVisible); } +void NodeParamViewConnectedLabel::CreateTree() +{ + // Set up table area + value_tree_ = new NodeValueTree(this); + layout()->addWidget(value_tree_); +} + void NodeParamViewConnectedLabel::SetTime(const rational &time) { time_ = time; - if (value_tree_->isVisible()) { + if (value_tree_ && value_tree_->isVisible()) { UpdateValueTree(); } } @@ -154,14 +159,22 @@ void NodeParamViewConnectedLabel::UpdateLabel() void NodeParamViewConnectedLabel::UpdateValueTree() { - value_tree_->SetNode(input_, time_); + if (value_tree_) { + value_tree_->SetNode(input_, time_); + } } void NodeParamViewConnectedLabel::SetValueTreeVisible(bool e) { - value_tree_->setVisible(e); + if (value_tree_) { + value_tree_->setVisible(e); + } if (e) { + if (!value_tree_) { + CreateTree(); + } + UpdateValueTree(); } } diff --git a/app/widget/nodeparamview/nodeparamviewconnectedlabel.h b/app/widget/nodeparamview/nodeparamviewconnectedlabel.h index 183ff633b..9a7a81ee7 100644 --- a/app/widget/nodeparamview/nodeparamviewconnectedlabel.h +++ b/app/widget/nodeparamview/nodeparamviewconnectedlabel.h @@ -51,6 +51,8 @@ private: void UpdateValueTree(); + void CreateTree(); + ClickableLabel* connected_to_lbl_; NodeInput input_; diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp index 7b0e82fd3..a27cbe824 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.cpp +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -88,7 +88,7 @@ void NodeParamViewItem::RecreateBody() body_->deleteLater(); } - body_ = new NodeParamViewItemBody(node_, create_checkboxes_); + body_ = new NodeParamViewItemBody(node_, create_checkboxes_, this); connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode); connect(body_, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItem::RequestSetTime); connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this, &NodeParamViewItem::ArrayExpandedChanged); @@ -148,7 +148,7 @@ NodeParamViewItemBody::NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBe if (n->InputIsArray(input)) { // Insert here - QWidget* array_widget = new QWidget(); + QWidget* array_widget = new QWidget(this); QGridLayout* array_layout = new QGridLayout(array_widget); array_layout->setContentsMargins(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral(" ")), 0, 0, 0); @@ -160,7 +160,7 @@ NodeParamViewItemBody::NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBe int arr_sz = 0; // Add one last add button for appending to the array - NodeParamViewArrayButton* append_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd); + NodeParamViewArrayButton* append_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd, this); connect(append_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayAppendClicked); array_layout->addWidget(append_btn, arr_sz, kArrayInsertColumn); @@ -186,7 +186,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const // Create optional checkbox if requested if (create_checkboxes_) { - ui_objects.optional_checkbox = new QCheckBox(); + ui_objects.optional_checkbox = new QCheckBox(this); connect(ui_objects.optional_checkbox, &QCheckBox::clicked, this, &NodeParamViewItemBody::OptionalCheckBoxClicked); layout->addWidget(ui_objects.optional_checkbox, row, kOptionalCheckBox); @@ -196,7 +196,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const } // Add descriptor label - ui_objects.main_label = new QLabel(); + ui_objects.main_label = new QLabel(this); // Create input label layout->addWidget(ui_objects.main_label, row, kLabelColumn); @@ -205,7 +205,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const if (element == -1) { // Create a collapse toggle for expanding/collapsing the array - CollapseButton* array_collapse_btn = new CollapseButton(); + CollapseButton* array_collapse_btn = new CollapseButton(this); // Default to collapsed array_collapse_btn->setChecked(false); @@ -220,8 +220,8 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const } else { - NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd); - NodeParamViewArrayButton* remove_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kRemove); + NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd, this); + NodeParamViewArrayButton* remove_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kRemove, this); layout->addWidget(insert_element_btn, row, kArrayInsertColumn); layout->addWidget(remove_element_btn, row, kArrayRemoveColumn); @@ -249,14 +249,14 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const if (node->IsInputConnectable(input)) { // Create clickable label used when an input is connected - ui_objects.connected_label = new NodeParamViewConnectedLabel(resolved); + ui_objects.connected_label = new NodeParamViewConnectedLabel(resolved, this); connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode); layout->addWidget(ui_objects.connected_label, row, kWidgetStartColumn, 1, kKeyControlColumn - kWidgetStartColumn); } // Add keyframe control to this layout if parameter is keyframable if (node->IsInputKeyframable(input)) { - ui_objects.key_control = new NodeParamViewKeyframeControl(); + ui_objects.key_control = new NodeParamViewKeyframeControl(this); ui_objects.key_control->SetInput(resolved); layout->addWidget(ui_objects.key_control, row, kKeyControlColumn); connect(ui_objects.key_control, &NodeParamViewKeyframeControl::RequestSetTime, this, &NodeParamViewItemBody::RequestSetTime); diff --git a/app/widget/nodeparamview/nodeparamviewitemtitlebar.cpp b/app/widget/nodeparamview/nodeparamviewitemtitlebar.cpp index 0e9aa6b32..ea51f647b 100644 --- a/app/widget/nodeparamview/nodeparamviewitemtitlebar.cpp +++ b/app/widget/nodeparamview/nodeparamviewitemtitlebar.cpp @@ -33,31 +33,31 @@ NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent) : { QHBoxLayout* layout = new QHBoxLayout(this); - collapse_btn_ = new CollapseButton(); + collapse_btn_ = new CollapseButton(this); connect(collapse_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::ExpandedStateChanged); layout->addWidget(collapse_btn_); - lbl_ = new QLabel(); + lbl_ = new QLabel(this); layout->addWidget(lbl_); // Place next buttons on the far side layout->addStretch(); - add_fx_btn_ = new QPushButton(); + add_fx_btn_ = new QPushButton(this); add_fx_btn_->setIcon(icon::AddEffect); add_fx_btn_->setFixedSize(add_fx_btn_->sizeHint().height(), add_fx_btn_->sizeHint().height()); add_fx_btn_->setVisible(false); layout->addWidget(add_fx_btn_); connect(add_fx_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::AddEffectButtonClicked); - pin_btn_ = new QPushButton(QStringLiteral("P")); + pin_btn_ = new QPushButton(QStringLiteral("P"), this); pin_btn_->setCheckable(true); pin_btn_->setFixedSize(pin_btn_->sizeHint().height(), pin_btn_->sizeHint().height()); pin_btn_->setVisible(false); layout->addWidget(pin_btn_); connect(pin_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::PinToggled); - enabled_checkbox_ = new QCheckBox(); + enabled_checkbox_ = new QCheckBox(this); enabled_checkbox_->setVisible(false); layout->addWidget(enabled_checkbox_); connect(enabled_checkbox_, &QCheckBox::clicked, this, &NodeParamViewItemTitleBar::EnabledCheckBoxClicked); diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h index c11b206e0..0f8ffab7d 100644 --- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h +++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h @@ -33,7 +33,11 @@ class NodeParamViewKeyframeControl : public QWidget, public TimeTargetObject { Q_OBJECT public: - NodeParamViewKeyframeControl(bool right_align = true, QWidget* parent = nullptr); + NodeParamViewKeyframeControl(bool right_align, QWidget* parent = nullptr); + NodeParamViewKeyframeControl(QWidget* parent = nullptr) : + NodeParamViewKeyframeControl(true, parent) + { + } const NodeInput& GetConnectedInput() const { diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 9f0ae6ac8..dd33a7659 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -71,9 +71,11 @@ int GetSliderCount(NodeValue::Type type) void NodeParamViewWidgetBridge::CreateWidgets() { + QWidget *parent = dynamic_cast(this->parent()); + if (GetInnerInput().IsArray() && GetInnerInput().element() == -1) { - NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(GetInnerInput().node(), GetInnerInput().input()); + NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(GetInnerInput().node(), GetInnerInput().input(), parent); connect(w, &NodeParamViewArrayWidget::DoubleClicked, this, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked); widgets_.append(w); @@ -94,12 +96,12 @@ void NodeParamViewWidgetBridge::CreateWidgets() break; case NodeValue::kInt: { - CreateSliders(1); + CreateSliders(1, parent); break; } case NodeValue::kRational: { - CreateSliders(1); + CreateSliders(1, parent); break; } case NodeValue::kFloat: @@ -107,12 +109,12 @@ void NodeParamViewWidgetBridge::CreateWidgets() case NodeValue::kVec3: case NodeValue::kVec4: { - CreateSliders(GetSliderCount(t)); + CreateSliders(GetSliderCount(t), parent); break; } case NodeValue::kCombo: { - QComboBox* combobox = new QComboBox(); + QComboBox* combobox = new QComboBox(parent); QStringList items = GetInnerInput().GetComboBoxStrings(); foreach (const QString& s, items) { @@ -125,21 +127,21 @@ void NodeParamViewWidgetBridge::CreateWidgets() } case NodeValue::kFile: { - FileField* file_field = new FileField(); + FileField* file_field = new FileField(parent); widgets_.append(file_field); connect(file_field, &FileField::FilenameChanged, this, &NodeParamViewWidgetBridge::WidgetCallback); break; } case NodeValue::kColor: { - ColorButton* color_button = new ColorButton(GetInnerInput().node()->project()->color_manager()); + ColorButton* color_button = new ColorButton(GetInnerInput().node()->project()->color_manager(), parent); widgets_.append(color_button); connect(color_button, &ColorButton::ColorChanged, this, &NodeParamViewWidgetBridge::WidgetCallback); break; } case NodeValue::kText: { - NodeParamViewTextEdit* line_edit = new NodeParamViewTextEdit(); + NodeParamViewTextEdit* line_edit = new NodeParamViewTextEdit(parent); widgets_.append(line_edit); connect(line_edit, &NodeParamViewTextEdit::textEdited, this, &NodeParamViewWidgetBridge::WidgetCallback); connect(line_edit, &NodeParamViewTextEdit::RequestEditInViewer, this, &NodeParamViewWidgetBridge::RequestEditTextInViewer); @@ -147,21 +149,21 @@ void NodeParamViewWidgetBridge::CreateWidgets() } case NodeValue::kBoolean: { - QCheckBox* check_box = new QCheckBox(); + QCheckBox* check_box = new QCheckBox(parent); widgets_.append(check_box); connect(check_box, &QCheckBox::clicked, this, &NodeParamViewWidgetBridge::WidgetCallback); break; } case NodeValue::kFont: { - QFontComboBox* font_combobox = new QFontComboBox(); + QFontComboBox* font_combobox = new QFontComboBox(parent); widgets_.append(font_combobox); connect(font_combobox, &QFontComboBox::currentFontChanged, this, &NodeParamViewWidgetBridge::WidgetCallback); break; } case NodeValue::kBezier: { - BezierWidget *bezier = new BezierWidget(); + BezierWidget *bezier = new BezierWidget(parent); widgets_.append(bezier); connect(bezier->x_slider(), &FloatSlider::ValueChanged, this, &NodeParamViewWidgetBridge::WidgetCallback); @@ -384,10 +386,10 @@ void NodeParamViewWidgetBridge::WidgetCallback() } template -void NodeParamViewWidgetBridge::CreateSliders(int count) +void NodeParamViewWidgetBridge::CreateSliders(int count, QWidget *parent) { for (int i=0;iSliderBase::SetDefaultValue(GetInnerInput().GetSplitDefaultValueForTrack(i)); fs->SetLadderElementCount(2); diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h index 98a71d5d7..772febbde 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h @@ -75,7 +75,7 @@ private: void SetProperty(const QString &key, const QVariant &value); template - void CreateSliders(int count); + void CreateSliders(int count, QWidget *parent); void UpdateWidgetValues();