Merge branch 'master' into multicam
This commit is contained in:
@@ -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<char*>(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;
|
||||
|
||||
@@ -123,6 +123,10 @@ private:
|
||||
|
||||
std::map<rational, Sample>::const_iterator GetMipmapForScale(double scale) const;
|
||||
|
||||
void ValidateVirtualStart(const rational &new_start);
|
||||
|
||||
rational virtual_start_;
|
||||
|
||||
int channels_;
|
||||
|
||||
std::map<rational, Sample> mipmapped_data_;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -22,113 +22,94 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
#define super PlaybackCache
|
||||
|
||||
AudioWaveformCache::AudioWaveformCache(QObject *parent) :
|
||||
PlaybackCache{parent}
|
||||
super{parent}
|
||||
{
|
||||
waveforms_ = std::make_shared<AudioVisualWaveform>();
|
||||
}
|
||||
|
||||
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<rational, AudioVisualWaveform::Sample> 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<AudioWaveformCache*>(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<AudioVisualWaveform>;
|
||||
|
||||
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<TimeRangeWithWaveform> waveforms_;
|
||||
#else
|
||||
AudioVisualWaveform waveforms_;
|
||||
#endif
|
||||
WaveformPtr waveforms_;
|
||||
|
||||
AudioParams params_;
|
||||
|
||||
class WaveformPassthrough : public TimeRange
|
||||
{
|
||||
public:
|
||||
WaveformPassthrough(const TimeRange &r) :
|
||||
TimeRange(r)
|
||||
{}
|
||||
|
||||
WaveformPtr waveform;
|
||||
};
|
||||
|
||||
QVector<WaveformPassthrough> passthroughs_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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; i<waveform_threads_.size(); i++) {
|
||||
waveform_threads_[i] = CreateThread();
|
||||
}
|
||||
}
|
||||
|
||||
decoder_clear_timer_ = new QTimer(this);
|
||||
@@ -136,7 +140,10 @@ RenderTicketPtr RenderManager::RenderAudio(const RenderAudioParams ¶ms)
|
||||
ticket->setProperty("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);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,9 @@ private:
|
||||
RenderThread *video_thread_;
|
||||
RenderThread *dry_run_thread_;
|
||||
RenderThread *audio_thread_;
|
||||
RenderThread *waveform_thread_;
|
||||
|
||||
std::vector<RenderThread *> waveform_threads_;
|
||||
size_t last_waveform_thread_;
|
||||
|
||||
std::list<RenderThread *> render_threads_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; i<context_items_.size(); i++) {
|
||||
NodeParamViewContext *c = new NodeParamViewContext;
|
||||
NodeParamViewContext *c = new NodeParamViewContext(param_widget_area_);
|
||||
c->setVisible(false);
|
||||
connect(c, &NodeParamViewContext::AboutToDeleteItem, this, &NodeParamView::ItemAboutToBeRemoved, Qt::DirectConnection);
|
||||
|
||||
@@ -245,8 +245,6 @@ void NodeParamView::DeselectNodes(const QVector<Node *> &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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ private:
|
||||
|
||||
void UpdateValueTree();
|
||||
|
||||
void CreateTree();
|
||||
|
||||
ClickableLabel* connected_to_lbl_;
|
||||
|
||||
NodeInput input_;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -71,9 +71,11 @@ int GetSliderCount(NodeValue::Type type)
|
||||
|
||||
void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
{
|
||||
QWidget *parent = dynamic_cast<QWidget*>(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<IntegerSlider>(1);
|
||||
CreateSliders<IntegerSlider>(1, parent);
|
||||
break;
|
||||
}
|
||||
case NodeValue::kRational:
|
||||
{
|
||||
CreateSliders<RationalSlider>(1);
|
||||
CreateSliders<RationalSlider>(1, parent);
|
||||
break;
|
||||
}
|
||||
case NodeValue::kFloat:
|
||||
@@ -107,12 +109,12 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
case NodeValue::kVec3:
|
||||
case NodeValue::kVec4:
|
||||
{
|
||||
CreateSliders<FloatSlider>(GetSliderCount(t));
|
||||
CreateSliders<FloatSlider>(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 <typename T>
|
||||
void NodeParamViewWidgetBridge::CreateSliders(int count)
|
||||
void NodeParamViewWidgetBridge::CreateSliders(int count, QWidget *parent)
|
||||
{
|
||||
for (int i=0;i<count;i++) {
|
||||
T* fs = new T();
|
||||
T* fs = new T(parent);
|
||||
fs->SliderBase::SetDefaultValue(GetInnerInput().GetSplitDefaultValueForTrack(i));
|
||||
fs->SetLadderElementCount(2);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
void SetProperty(const QString &key, const QVariant &value);
|
||||
|
||||
template <typename T>
|
||||
void CreateSliders(int count);
|
||||
void CreateSliders(int count, QWidget *parent);
|
||||
|
||||
void UpdateWidgetValues();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user