change: change code style to Linux style except indent.
This commit is contained in:
+61
-55
@@ -27,121 +27,127 @@
|
||||
#include "transition/transition.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super Node
|
||||
|
||||
const QString Block::kLengthInput = QStringLiteral("length_in");
|
||||
|
||||
Block::Block() :
|
||||
previous_(nullptr),
|
||||
next_(nullptr),
|
||||
track_(nullptr)
|
||||
Block::Block()
|
||||
: previous_(nullptr)
|
||||
, next_(nullptr)
|
||||
, track_(nullptr)
|
||||
{
|
||||
AddInput(kLengthInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable | kInputFlagHidden));
|
||||
SetInputProperty(kLengthInput, QStringLiteral("min"), QVariant::fromValue(rational(0, 1)));
|
||||
SetInputProperty(kLengthInput, QStringLiteral("view"), RationalSlider::kTime);
|
||||
SetInputProperty(kLengthInput, QStringLiteral("viewlock"), true);
|
||||
AddInput(kLengthInput, NodeValue::kRational,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable |
|
||||
kInputFlagHidden));
|
||||
SetInputProperty(kLengthInput, QStringLiteral("min"),
|
||||
QVariant::fromValue(rational(0, 1)));
|
||||
SetInputProperty(kLengthInput, QStringLiteral("view"),
|
||||
RationalSlider::kTime);
|
||||
SetInputProperty(kLengthInput, QStringLiteral("viewlock"), true);
|
||||
|
||||
SetInputFlag(kEnabledInput, kInputFlagNotConnectable);
|
||||
SetInputFlag(kEnabledInput, kInputFlagNotKeyframable);
|
||||
SetInputFlag(kEnabledInput, kInputFlagNotConnectable);
|
||||
SetInputFlag(kEnabledInput, kInputFlagNotKeyframable);
|
||||
|
||||
SetFlag(kDontShowInParamView);
|
||||
SetFlag(kDontShowInParamView);
|
||||
}
|
||||
|
||||
QVector<Node::CategoryID> Block::Category() const
|
||||
{
|
||||
return {kCategoryTimeline};
|
||||
return { kCategoryTimeline };
|
||||
}
|
||||
|
||||
rational Block::length() const
|
||||
{
|
||||
return GetStandardValue(kLengthInput).value<rational>();
|
||||
return GetStandardValue(kLengthInput).value<rational>();
|
||||
}
|
||||
|
||||
void Block::set_length_and_media_out(const rational &length)
|
||||
{
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_length_internal(length);
|
||||
set_length_internal(length);
|
||||
}
|
||||
|
||||
void Block::set_length_and_media_in(const rational &length)
|
||||
{
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the length without setting media out
|
||||
set_length_internal(length);
|
||||
// Set the length without setting media out
|
||||
set_length_internal(length);
|
||||
}
|
||||
|
||||
bool Block::is_enabled() const
|
||||
{
|
||||
return GetStandardValue(kEnabledInput).toBool();
|
||||
return GetStandardValue(kEnabledInput).toBool();
|
||||
}
|
||||
|
||||
void Block::set_enabled(bool e)
|
||||
{
|
||||
SetStandardValue(kEnabledInput, e);
|
||||
SetStandardValue(kEnabledInput, e);
|
||||
|
||||
emit EnabledChanged();
|
||||
emit EnabledChanged();
|
||||
}
|
||||
|
||||
void Block::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
super::InputValueChangedEvent(input, element);
|
||||
super::InputValueChangedEvent(input, element);
|
||||
|
||||
if (input == kLengthInput) {
|
||||
emit LengthChanged();
|
||||
} else if (input == kEnabledInput) {
|
||||
emit EnabledChanged();
|
||||
}
|
||||
if (input == kLengthInput) {
|
||||
emit LengthChanged();
|
||||
} else if (input == kEnabledInput) {
|
||||
emit EnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Block::set_length_internal(const rational &length)
|
||||
{
|
||||
SetStandardValue(kLengthInput, QVariant::fromValue(length));
|
||||
SetStandardValue(kLengthInput, QVariant::fromValue(length));
|
||||
}
|
||||
|
||||
void Block::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kLengthInput, tr("Length"));
|
||||
SetInputName(kEnabledInput, tr("Enabled"));
|
||||
SetInputName(kLengthInput, tr("Length"));
|
||||
SetInputName(kEnabledInput, tr("Enabled"));
|
||||
}
|
||||
|
||||
void Block::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
||||
void Block::InvalidateCache(const TimeRange &range, const QString &from,
|
||||
int element, InvalidateCacheOptions options)
|
||||
{
|
||||
TimeRange r;
|
||||
TimeRange r;
|
||||
|
||||
if (from == kLengthInput) {
|
||||
// We must intercept the signal here
|
||||
r = TimeRange(qMin(length(), last_length_), RATIONAL_MAX);
|
||||
if (from == kLengthInput) {
|
||||
// We must intercept the signal here
|
||||
r = TimeRange(qMin(length(), last_length_), RATIONAL_MAX);
|
||||
|
||||
if (!NodeInputDragger::IsInputBeingDragged()) {
|
||||
last_length_ = length();
|
||||
}
|
||||
if (!NodeInputDragger::IsInputBeingDragged()) {
|
||||
last_length_ = length();
|
||||
}
|
||||
|
||||
options.insert(QStringLiteral("lengthevent"), true);
|
||||
} else {
|
||||
r = range;
|
||||
}
|
||||
options.insert(QStringLiteral("lengthevent"), true);
|
||||
} else {
|
||||
r = range;
|
||||
}
|
||||
|
||||
super::InvalidateCache(r, from, element, options);
|
||||
super::InvalidateCache(r, from, element, options);
|
||||
}
|
||||
|
||||
void Block::set_previous_next(Block *previous, Block *next)
|
||||
{
|
||||
if (previous) {
|
||||
previous->set_next(next);
|
||||
}
|
||||
if (next) {
|
||||
next->set_previous(previous);
|
||||
}
|
||||
if (previous) {
|
||||
previous->set_next(next);
|
||||
}
|
||||
if (next) {
|
||||
next->set_previous(previous);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+75
-73
@@ -24,118 +24,120 @@
|
||||
#include "node/node.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TransitionBlock;
|
||||
|
||||
/**
|
||||
* @brief A Node that represents a block of time, also displayable on a Timeline
|
||||
*/
|
||||
class Block : public Node
|
||||
{
|
||||
Q_OBJECT
|
||||
class Block : public Node {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Block();
|
||||
Block();
|
||||
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
|
||||
const rational& in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
const rational &in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
|
||||
const rational& out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
const rational &out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
|
||||
void set_in(const rational& in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
void set_in(const rational &in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
|
||||
void set_out(const rational& out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
void set_out(const rational &out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
|
||||
rational length() const;
|
||||
virtual void set_length_and_media_out(const rational &length);
|
||||
virtual void set_length_and_media_in(const rational &length);
|
||||
rational length() const;
|
||||
virtual void set_length_and_media_out(const rational &length);
|
||||
virtual void set_length_and_media_in(const rational &length);
|
||||
|
||||
TimeRange range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
TimeRange range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
|
||||
Block* previous() const
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
Block *previous() const
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
|
||||
Block* next() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
Block *next() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
void set_previous(Block* previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
void set_previous(Block *previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
|
||||
void set_next(Block* next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
void set_next(Block *next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
Track* track() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
Track *track() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void set_track(Track* track)
|
||||
{
|
||||
track_ = track;
|
||||
emit TrackChanged(track_);
|
||||
}
|
||||
void set_track(Track *track)
|
||||
{
|
||||
track_ = track;
|
||||
emit TrackChanged(track_);
|
||||
}
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
virtual void InvalidateCache(
|
||||
const TimeRange &range, const QString &from, int element = -1,
|
||||
InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
|
||||
static const QString kLengthInput;
|
||||
static const QString kLengthInput;
|
||||
|
||||
static void set_previous_next(Block *previous, Block *next);
|
||||
static void set_previous_next(Block *previous, Block *next);
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void EnabledChanged();
|
||||
void EnabledChanged();
|
||||
|
||||
void LengthChanged();
|
||||
void LengthChanged();
|
||||
|
||||
void PreviewChanged();
|
||||
void PreviewChanged();
|
||||
|
||||
void TrackChanged(Track *track);
|
||||
void TrackChanged(Track *track);
|
||||
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
virtual void InputValueChangedEvent(const QString &input,
|
||||
int element) override;
|
||||
|
||||
Block* previous_;
|
||||
Block* next_;
|
||||
Block *previous_;
|
||||
Block *next_;
|
||||
|
||||
private:
|
||||
void set_length_internal(const rational &length);
|
||||
void set_length_internal(const rational &length);
|
||||
|
||||
rational in_point_;
|
||||
rational out_point_;
|
||||
Track* track_;
|
||||
|
||||
rational last_length_;
|
||||
rational in_point_;
|
||||
rational out_point_;
|
||||
Track *track_;
|
||||
|
||||
rational last_length_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+411
-334
@@ -28,7 +28,8 @@
|
||||
#include "widget/slider/floatslider.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super Block
|
||||
|
||||
@@ -36,149 +37,164 @@ const QString ClipBlock::kBufferIn = QStringLiteral("buffer_in");
|
||||
const QString ClipBlock::kMediaInInput = QStringLiteral("media_in_in");
|
||||
const QString ClipBlock::kSpeedInput = QStringLiteral("speed_in");
|
||||
const QString ClipBlock::kReverseInput = QStringLiteral("reverse_in");
|
||||
const QString ClipBlock::kMaintainAudioPitchInput = QStringLiteral("maintain_audio_pitch_in");
|
||||
const QString ClipBlock::kMaintainAudioPitchInput =
|
||||
QStringLiteral("maintain_audio_pitch_in");
|
||||
const QString ClipBlock::kAutoCacheInput = QStringLiteral("autocache_in");
|
||||
const QString ClipBlock::kLoopModeInput = QStringLiteral("loop_in");
|
||||
|
||||
ClipBlock::ClipBlock() :
|
||||
in_transition_(nullptr),
|
||||
out_transition_(nullptr),
|
||||
connected_viewer_(nullptr)
|
||||
ClipBlock::ClipBlock()
|
||||
: in_transition_(nullptr)
|
||||
, out_transition_(nullptr)
|
||||
, connected_viewer_(nullptr)
|
||||
{
|
||||
AddInput(kMediaInInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kMediaInInput, QStringLiteral("view"), RationalSlider::kTime);
|
||||
SetInputProperty(kMediaInInput, QStringLiteral("viewlock"), true);
|
||||
AddInput(kMediaInInput, NodeValue::kRational,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kMediaInInput, QStringLiteral("view"),
|
||||
RationalSlider::kTime);
|
||||
SetInputProperty(kMediaInInput, QStringLiteral("viewlock"), true);
|
||||
|
||||
AddInput(kSpeedInput, NodeValue::kFloat, 1.0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kSpeedInput, QStringLiteral("view"), FloatSlider::kPercentage);
|
||||
SetInputProperty(kSpeedInput, QStringLiteral("min"), 0.0);
|
||||
AddInput(kSpeedInput, NodeValue::kFloat, 1.0,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
SetInputProperty(kSpeedInput, QStringLiteral("view"),
|
||||
FloatSlider::kPercentage);
|
||||
SetInputProperty(kSpeedInput, QStringLiteral("min"), 0.0);
|
||||
|
||||
AddInput(kReverseInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kReverseInput, NodeValue::kBoolean, false,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kMaintainAudioPitchInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kMaintainAudioPitchInput, NodeValue::kBoolean, false,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kAutoCacheInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kAutoCacheInput, NodeValue::kBoolean, false,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
PrependInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
|
||||
//SetValueHintForInput(kBufferIn, ValueHint(NodeValue::kBuffer));
|
||||
PrependInput(kBufferIn, NodeValue::kNone,
|
||||
InputFlags(kInputFlagNotKeyframable));
|
||||
//SetValueHintForInput(kBufferIn, ValueHint(NodeValue::kBuffer));
|
||||
|
||||
SetEffectInput(kBufferIn);
|
||||
SetEffectInput(kBufferIn);
|
||||
|
||||
AddInput(kLoopModeInput, NodeValue::kCombo, 0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kLoopModeInput, NodeValue::kCombo, 0,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
}
|
||||
|
||||
QString ClipBlock::Name() const
|
||||
{
|
||||
if (connected_viewer_ && !connected_viewer_->GetLabel().isEmpty()) {
|
||||
return connected_viewer_->GetLabel();
|
||||
} else if (track()) {
|
||||
if (track()->type() == Track::kVideo) {
|
||||
return tr("Video Clip");
|
||||
} else if (track()->type() == Track::kAudio) {
|
||||
return tr("Audio Clip");
|
||||
}
|
||||
}
|
||||
if (connected_viewer_ && !connected_viewer_->GetLabel().isEmpty()) {
|
||||
return connected_viewer_->GetLabel();
|
||||
} else if (track()) {
|
||||
if (track()->type() == Track::kVideo) {
|
||||
return tr("Video Clip");
|
||||
} else if (track()->type() == Track::kAudio) {
|
||||
return tr("Audio Clip");
|
||||
}
|
||||
}
|
||||
|
||||
return tr("Clip");
|
||||
return tr("Clip");
|
||||
}
|
||||
|
||||
QString ClipBlock::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.clip");
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.clip");
|
||||
}
|
||||
|
||||
QString ClipBlock::Description() const
|
||||
{
|
||||
return tr("A time-based node that represents a media source.");
|
||||
return tr("A time-based node that represents a media source.");
|
||||
}
|
||||
|
||||
void ClipBlock::set_length_and_media_out(const rational &length)
|
||||
{
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
rational proposed_media_in = SequenceToMediaTime(this->length() - length, kSTMIgnoreReverse | kSTMIgnoreLoop);
|
||||
set_media_in(proposed_media_in);
|
||||
}
|
||||
if (reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
rational proposed_media_in = SequenceToMediaTime(
|
||||
this->length() - length, kSTMIgnoreReverse | kSTMIgnoreLoop);
|
||||
set_media_in(proposed_media_in);
|
||||
}
|
||||
|
||||
super::set_length_and_media_out(length);
|
||||
super::set_length_and_media_out(length);
|
||||
}
|
||||
|
||||
void ClipBlock::set_length_and_media_in(const rational &length)
|
||||
{
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
if (length == this->length()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rational old_length = this->length();
|
||||
rational old_length = this->length();
|
||||
|
||||
super::set_length_and_media_in(length);
|
||||
super::set_length_and_media_in(length);
|
||||
|
||||
if (!reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
set_media_in(SequenceToMediaTime(old_length - length, kSTMIgnoreLoop));
|
||||
}
|
||||
if (!reverse()) {
|
||||
// Calculate media_in adjustment
|
||||
set_media_in(SequenceToMediaTime(old_length - length, kSTMIgnoreLoop));
|
||||
}
|
||||
}
|
||||
|
||||
rational ClipBlock::media_in() const
|
||||
{
|
||||
return GetStandardValue(kMediaInInput).value<rational>();
|
||||
return GetStandardValue(kMediaInInput).value<rational>();
|
||||
}
|
||||
|
||||
void ClipBlock::set_media_in(const rational &media_in)
|
||||
{
|
||||
SetStandardValue(kMediaInInput, QVariant::fromValue(media_in));
|
||||
SetStandardValue(kMediaInInput, QVariant::fromValue(media_in));
|
||||
|
||||
RequestInvalidatedFromConnected();
|
||||
RequestInvalidatedFromConnected();
|
||||
}
|
||||
|
||||
void ClipBlock::SetAutocache(bool e)
|
||||
{
|
||||
SetStandardValue(kAutoCacheInput, e);
|
||||
SetStandardValue(kAutoCacheInput, e);
|
||||
}
|
||||
|
||||
void ClipBlock::DiscardCache()
|
||||
{
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
Track::Type type = GetTrackType();
|
||||
if (type == Track::kVideo) {
|
||||
connected->video_frame_cache()->Invalidate(TimeRange(RATIONAL_MIN, RATIONAL_MAX));
|
||||
} else if (type == Track::kAudio) {
|
||||
connected->audio_playback_cache()->Invalidate(TimeRange(RATIONAL_MIN, RATIONAL_MAX));
|
||||
}
|
||||
}
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
Track::Type type = GetTrackType();
|
||||
if (type == Track::kVideo) {
|
||||
connected->video_frame_cache()->Invalidate(
|
||||
TimeRange(RATIONAL_MIN, RATIONAL_MAX));
|
||||
} else if (type == Track::kAudio) {
|
||||
connected->audio_playback_cache()->Invalidate(
|
||||
TimeRange(RATIONAL_MIN, RATIONAL_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, uint64_t flags) const
|
||||
rational ClipBlock::SequenceToMediaTime(const rational &sequence_time,
|
||||
uint64_t flags) const
|
||||
{
|
||||
// These constants are not considered "values" per se, so we don't modify them
|
||||
if (sequence_time == RATIONAL_MIN || sequence_time == RATIONAL_MAX) {
|
||||
return sequence_time;
|
||||
}
|
||||
// These constants are not considered "values" per se, so we don't modify them
|
||||
if (sequence_time == RATIONAL_MIN || sequence_time == RATIONAL_MAX) {
|
||||
return sequence_time;
|
||||
}
|
||||
|
||||
rational media_time = sequence_time;
|
||||
rational media_time = sequence_time;
|
||||
|
||||
if (reverse() && !(flags & kSTMIgnoreReverse)) {
|
||||
media_time = length() - media_time;
|
||||
}
|
||||
if (reverse() && !(flags & kSTMIgnoreReverse)) {
|
||||
media_time = length() - media_time;
|
||||
}
|
||||
|
||||
if (!(flags & kSTMIgnoreSpeed)) {
|
||||
double speed_value = speed();
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point
|
||||
media_time = 0;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Multiply time
|
||||
media_time = rational::fromDouble(media_time.toDouble() * speed_value);
|
||||
}
|
||||
}
|
||||
if (!(flags & kSTMIgnoreSpeed)) {
|
||||
double speed_value = speed();
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point
|
||||
media_time = 0;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Multiply time
|
||||
media_time =
|
||||
rational::fromDouble(media_time.toDouble() * speed_value);
|
||||
}
|
||||
}
|
||||
|
||||
media_time += media_in();
|
||||
media_time += media_in();
|
||||
|
||||
/*if (!(flags & kSTMIgnoreLoop)
|
||||
/*if (!(flags & kSTMIgnoreLoop)
|
||||
&& this->loop_mode() != kLoopModeOff
|
||||
&& connected_viewer_
|
||||
&& !connected_viewer_->GetLength().isNull()
|
||||
@@ -195,366 +211,427 @@ rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, uint64_t
|
||||
}
|
||||
}*/
|
||||
|
||||
return media_time;
|
||||
return media_time;
|
||||
}
|
||||
|
||||
rational ClipBlock::MediaToSequenceTime(const rational &media_time) const
|
||||
{
|
||||
// These constants are not considered "values" per se, so we don't modify them
|
||||
if (media_time == RATIONAL_MIN || media_time == RATIONAL_MAX) {
|
||||
return media_time;
|
||||
}
|
||||
// These constants are not considered "values" per se, so we don't modify them
|
||||
if (media_time == RATIONAL_MIN || media_time == RATIONAL_MAX) {
|
||||
return media_time;
|
||||
}
|
||||
|
||||
rational sequence_time = media_time - media_in();
|
||||
rational sequence_time = media_time - media_in();
|
||||
|
||||
double speed_value = speed();
|
||||
if (qIsNull(speed_value)) {
|
||||
// I don't know what to return here yet...
|
||||
sequence_time = rational::NaN;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Divide time
|
||||
sequence_time = rational::fromDouble(sequence_time.toDouble() / speed_value);
|
||||
}
|
||||
double speed_value = speed();
|
||||
if (qIsNull(speed_value)) {
|
||||
// I don't know what to return here yet...
|
||||
sequence_time = rational::NaN;
|
||||
} else if (!qFuzzyCompare(speed_value, 1.0)) {
|
||||
// Divide time
|
||||
sequence_time =
|
||||
rational::fromDouble(sequence_time.toDouble() / speed_value);
|
||||
}
|
||||
|
||||
if (reverse()) {
|
||||
sequence_time = length() - sequence_time;
|
||||
}
|
||||
if (reverse()) {
|
||||
sequence_time = length() - sequence_time;
|
||||
}
|
||||
|
||||
return sequence_time;
|
||||
return sequence_time;
|
||||
}
|
||||
|
||||
void ClipBlock::RequestRangeFromConnected(const TimeRange &range)
|
||||
{
|
||||
Track::Type type = GetTrackType();
|
||||
Track::Type type = GetTrackType();
|
||||
|
||||
if (type == Track::kVideo || type == Track::kAudio) {
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
TimeRange max_range = media_range();
|
||||
if (type == Track::kVideo) {
|
||||
// Handle thumbnails
|
||||
RequestRangeForCache(connected->thumbnail_cache(), max_range, range, true, false);
|
||||
{
|
||||
TimeRange thumb_range = range.Intersected(max_range);
|
||||
if (GetAdjustedThumbnailRange(&thumb_range)) {
|
||||
connected->thumbnail_cache()->Request(this->track()->sequence(), thumb_range);
|
||||
}
|
||||
}
|
||||
if (type == Track::kVideo || type == Track::kAudio) {
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
TimeRange max_range = media_range();
|
||||
if (type == Track::kVideo) {
|
||||
// Handle thumbnails
|
||||
RequestRangeForCache(connected->thumbnail_cache(), max_range,
|
||||
range, true, false);
|
||||
{
|
||||
TimeRange thumb_range = range.Intersected(max_range);
|
||||
if (GetAdjustedThumbnailRange(&thumb_range)) {
|
||||
connected->thumbnail_cache()->Request(
|
||||
this->track()->sequence(), thumb_range);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle video cache
|
||||
RequestRangeForCache(connected->video_frame_cache(), max_range, range, true, IsAutocaching());
|
||||
} else if (type == Track::kAudio) {
|
||||
// Handle waveforms
|
||||
RequestRangeForCache(connected->waveform_cache(), max_range, range, true, (OLIVE_CONFIG("TimelineWaveformMode").toInt() == Timeline::kWaveformsEnabled));
|
||||
// Handle video cache
|
||||
RequestRangeForCache(connected->video_frame_cache(), max_range,
|
||||
range, true, IsAutocaching());
|
||||
} else if (type == Track::kAudio) {
|
||||
// Handle waveforms
|
||||
RequestRangeForCache(
|
||||
connected->waveform_cache(), max_range, range, true,
|
||||
(OLIVE_CONFIG("TimelineWaveformMode").toInt() ==
|
||||
Timeline::kWaveformsEnabled));
|
||||
|
||||
// Handle audio cache
|
||||
RequestRangeForCache(connected->audio_playback_cache(), max_range, range, true, IsAutocaching());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle audio cache
|
||||
RequestRangeForCache(connected->audio_playback_cache(),
|
||||
max_range, range, true, IsAutocaching());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::RequestInvalidatedFromConnected(bool force_all, const TimeRange &intersect)
|
||||
void ClipBlock::RequestInvalidatedFromConnected(bool force_all,
|
||||
const TimeRange &intersect)
|
||||
{
|
||||
Track::Type type = GetTrackType();
|
||||
Track::Type type = GetTrackType();
|
||||
|
||||
if (type == Track::kVideo || type == Track::kAudio) {
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
TimeRange max_range = media_range();
|
||||
if (type == Track::kVideo || type == Track::kAudio) {
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
TimeRange max_range = media_range();
|
||||
|
||||
if (!intersect.length().isNull()) {
|
||||
max_range = max_range.Intersected(intersect);
|
||||
}
|
||||
if (!intersect.length().isNull()) {
|
||||
max_range = max_range.Intersected(intersect);
|
||||
}
|
||||
|
||||
if (type == Track::kVideo) {
|
||||
// Handle thumbnails
|
||||
TimeRange thumb_range = max_range;
|
||||
if (GetAdjustedThumbnailRange(&thumb_range)) {
|
||||
RequestInvalidatedForCache(connected->thumbnail_cache(), thumb_range);
|
||||
}
|
||||
if (type == Track::kVideo) {
|
||||
// Handle thumbnails
|
||||
TimeRange thumb_range = max_range;
|
||||
if (GetAdjustedThumbnailRange(&thumb_range)) {
|
||||
RequestInvalidatedForCache(connected->thumbnail_cache(),
|
||||
thumb_range);
|
||||
}
|
||||
|
||||
// Handle video cache
|
||||
if (IsAutocaching() || force_all) {
|
||||
RequestInvalidatedForCache(connected->video_frame_cache(), max_range);
|
||||
}
|
||||
} else if (type == Track::kAudio) {
|
||||
// Handle waveforms
|
||||
if (OLIVE_CONFIG("TimelineWaveformMode").toInt() == Timeline::kWaveformsEnabled) {
|
||||
RequestInvalidatedForCache(connected->waveform_cache(), max_range);
|
||||
}
|
||||
// Handle video cache
|
||||
if (IsAutocaching() || force_all) {
|
||||
RequestInvalidatedForCache(connected->video_frame_cache(),
|
||||
max_range);
|
||||
}
|
||||
} else if (type == Track::kAudio) {
|
||||
// Handle waveforms
|
||||
if (OLIVE_CONFIG("TimelineWaveformMode").toInt() ==
|
||||
Timeline::kWaveformsEnabled) {
|
||||
RequestInvalidatedForCache(connected->waveform_cache(),
|
||||
max_range);
|
||||
}
|
||||
|
||||
// Handle audio cache
|
||||
if (IsAutocaching() || force_all) {
|
||||
RequestInvalidatedForCache(connected->audio_playback_cache(), max_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle audio cache
|
||||
if (IsAutocaching() || force_all) {
|
||||
RequestInvalidatedForCache(
|
||||
connected->audio_playback_cache(), max_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::RequestRangeForCache(PlaybackCache *cache, const TimeRange &max_range, const TimeRange &range, bool invalidate, bool request)
|
||||
void ClipBlock::RequestRangeForCache(PlaybackCache *cache,
|
||||
const TimeRange &max_range,
|
||||
const TimeRange &range, bool invalidate,
|
||||
bool request)
|
||||
{
|
||||
TimeRange r = range.Intersected(max_range);
|
||||
TimeRange r = range.Intersected(max_range);
|
||||
|
||||
if (invalidate) {
|
||||
cache->Invalidate(r);
|
||||
}
|
||||
if (invalidate) {
|
||||
cache->Invalidate(r);
|
||||
}
|
||||
|
||||
if (request) {
|
||||
cache->Request(this->track()->sequence(), r);
|
||||
}
|
||||
if (request) {
|
||||
cache->Request(this->track()->sequence(), r);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::RequestInvalidatedForCache(PlaybackCache *cache, const TimeRange &max_range)
|
||||
void ClipBlock::RequestInvalidatedForCache(PlaybackCache *cache,
|
||||
const TimeRange &max_range)
|
||||
{
|
||||
TimeRangeList invalid = cache->GetInvalidatedRanges(max_range);
|
||||
TimeRangeList invalid = cache->GetInvalidatedRanges(max_range);
|
||||
|
||||
for (const PlaybackCache::Passthrough &p : cache->GetPassthroughs()) {
|
||||
invalid.remove(p);
|
||||
}
|
||||
for (const PlaybackCache::Passthrough &p : cache->GetPassthroughs()) {
|
||||
invalid.remove(p);
|
||||
}
|
||||
|
||||
for (const TimeRange &r : invalid) {
|
||||
RequestRangeForCache(cache, max_range, r, false, true);
|
||||
}
|
||||
for (const TimeRange &r : invalid) {
|
||||
RequestRangeForCache(cache, max_range, r, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClipBlock::GetAdjustedThumbnailRange(TimeRange *r) const
|
||||
{
|
||||
switch (static_cast<Timeline::ThumbnailMode>(OLIVE_CONFIG("TimelineThumbnailMode").toInt())) {
|
||||
case Timeline::kThumbnailOff:
|
||||
// Don't cache any range
|
||||
return false;
|
||||
case Timeline::kThumbnailInOut:
|
||||
{
|
||||
// Only cache in point
|
||||
rational in = this->media_range().in();
|
||||
if (r->Contains(in)) {
|
||||
// Cache only the in point
|
||||
*r = TimeRange(in, in + thumbnail_cache()->GetTimebase());
|
||||
return true;
|
||||
} else {
|
||||
// Cache nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case Timeline::kThumbnailOn:
|
||||
// Cache entire range
|
||||
return true;
|
||||
}
|
||||
switch (static_cast<Timeline::ThumbnailMode>(
|
||||
OLIVE_CONFIG("TimelineThumbnailMode").toInt())) {
|
||||
case Timeline::kThumbnailOff:
|
||||
// Don't cache any range
|
||||
return false;
|
||||
case Timeline::kThumbnailInOut: {
|
||||
// Only cache in point
|
||||
rational in = this->media_range().in();
|
||||
if (r->Contains(in)) {
|
||||
// Cache only the in point
|
||||
*r = TimeRange(in, in + thumbnail_cache()->GetTimebase());
|
||||
return true;
|
||||
} else {
|
||||
// Cache nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case Timeline::kThumbnailOn:
|
||||
// Cache entire range
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return true;
|
||||
// Fallback
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClipBlock::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
|
||||
void ClipBlock::InvalidateCache(const TimeRange &range, const QString &from,
|
||||
int element, InvalidateCacheOptions options)
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(element)
|
||||
|
||||
// If signal is from texture input, transform all times from media time to sequence time
|
||||
if (from == kBufferIn) {
|
||||
// Render caches where necessary
|
||||
if (AreCachesEnabled()) {
|
||||
RequestRangeFromConnected(range);
|
||||
}
|
||||
// If signal is from texture input, transform all times from media time to sequence time
|
||||
if (from == kBufferIn) {
|
||||
// Render caches where necessary
|
||||
if (AreCachesEnabled()) {
|
||||
RequestRangeFromConnected(range);
|
||||
}
|
||||
|
||||
// Adjust range from media time to sequence time
|
||||
TimeRange adj;
|
||||
double speed_value = speed();
|
||||
// Adjust range from media time to sequence time
|
||||
TimeRange adj;
|
||||
double speed_value = speed();
|
||||
|
||||
if (qIsNull(speed_value)) {
|
||||
// Handle 0 speed by invalidating the whole clip
|
||||
adj = TimeRange(RATIONAL_MIN, RATIONAL_MAX);
|
||||
} else {
|
||||
adj = TimeRange(MediaToSequenceTime(range.in()), MediaToSequenceTime(range.out()));
|
||||
}
|
||||
if (qIsNull(speed_value)) {
|
||||
// Handle 0 speed by invalidating the whole clip
|
||||
adj = TimeRange(RATIONAL_MIN, RATIONAL_MAX);
|
||||
} else {
|
||||
adj = TimeRange(MediaToSequenceTime(range.in()),
|
||||
MediaToSequenceTime(range.out()));
|
||||
}
|
||||
|
||||
// Find connected viewer node
|
||||
auto viewers = FindInputNodesConnectedToInput<ViewerOutput>(NodeInput(this, kBufferIn), 1);
|
||||
ViewerOutput *new_connected_viewer = viewers.isEmpty() ? nullptr : viewers.first();
|
||||
// Find connected viewer node
|
||||
auto viewers = FindInputNodesConnectedToInput<ViewerOutput>(
|
||||
NodeInput(this, kBufferIn), 1);
|
||||
ViewerOutput *new_connected_viewer =
|
||||
viewers.isEmpty() ? nullptr : viewers.first();
|
||||
|
||||
if (new_connected_viewer != connected_viewer_) {
|
||||
if (connected_viewer_) {
|
||||
disconnect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerAdded, this, &ClipBlock::PreviewChanged);
|
||||
disconnect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerRemoved, this, &ClipBlock::PreviewChanged);
|
||||
disconnect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerModified, this, &ClipBlock::PreviewChanged);
|
||||
}
|
||||
if (new_connected_viewer != connected_viewer_) {
|
||||
if (connected_viewer_) {
|
||||
disconnect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerAdded, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
disconnect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerRemoved, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
disconnect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerModified, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
}
|
||||
|
||||
connected_viewer_ = new_connected_viewer;
|
||||
connected_viewer_ = new_connected_viewer;
|
||||
|
||||
if (connected_viewer_) {
|
||||
connect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerAdded, this, &ClipBlock::PreviewChanged);
|
||||
connect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerRemoved, this, &ClipBlock::PreviewChanged);
|
||||
connect(connected_viewer_->GetMarkers(), &TimelineMarkerList::MarkerModified, this, &ClipBlock::PreviewChanged);
|
||||
}
|
||||
}
|
||||
if (connected_viewer_) {
|
||||
connect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerAdded, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
connect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerRemoved, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
connect(connected_viewer_->GetMarkers(),
|
||||
&TimelineMarkerList::MarkerModified, this,
|
||||
&ClipBlock::PreviewChanged);
|
||||
}
|
||||
}
|
||||
|
||||
super::InvalidateCache(adj, from, element, options);
|
||||
} else {
|
||||
// Otherwise, pass signal along normally
|
||||
super::InvalidateCache(range, from, element, options);
|
||||
}
|
||||
super::InvalidateCache(adj, from, element, options);
|
||||
} else {
|
||||
// Otherwise, pass signal along normally
|
||||
super::InvalidateCache(range, from, element, options);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::LinkChangeEvent()
|
||||
{
|
||||
block_links_.clear();
|
||||
block_links_.clear();
|
||||
|
||||
foreach (Node* n, links()) {
|
||||
ClipBlock* b = dynamic_cast<ClipBlock*>(n);
|
||||
foreach (Node *n, links()) {
|
||||
ClipBlock *b = dynamic_cast<ClipBlock *>(n);
|
||||
|
||||
if (b) {
|
||||
block_links_.append(b);
|
||||
}
|
||||
}
|
||||
if (b) {
|
||||
block_links_.append(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::InputConnectedEvent(const QString &input, int element, Node *output)
|
||||
void ClipBlock::InputConnectedEvent(const QString &input, int element,
|
||||
Node *output)
|
||||
{
|
||||
super::InputConnectedEvent(input, element, output);
|
||||
super::InputConnectedEvent(input, element, output);
|
||||
|
||||
if (input == kBufferIn) {
|
||||
connect(output->thumbnail_cache(), &FrameHashCache::Invalidated, this, &Block::PreviewChanged);
|
||||
connect(output->waveform_cache(), &AudioPlaybackCache::Invalidated, this, &Block::PreviewChanged);
|
||||
connect(output->video_frame_cache(), &FrameHashCache::Invalidated, this, &Block::PreviewChanged);
|
||||
connect(output->audio_playback_cache(), &AudioPlaybackCache::Invalidated, this, &Block::PreviewChanged);
|
||||
connect(output->thumbnail_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
|
||||
connect(output->waveform_cache(), &AudioPlaybackCache::Validated, this, &Block::PreviewChanged);
|
||||
connect(output->video_frame_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
|
||||
connect(output->audio_playback_cache(), &AudioPlaybackCache::Validated, this, &Block::PreviewChanged);
|
||||
}
|
||||
if (input == kBufferIn) {
|
||||
connect(output->thumbnail_cache(), &FrameHashCache::Invalidated, this,
|
||||
&Block::PreviewChanged);
|
||||
connect(output->waveform_cache(), &AudioPlaybackCache::Invalidated,
|
||||
this, &Block::PreviewChanged);
|
||||
connect(output->video_frame_cache(), &FrameHashCache::Invalidated, this,
|
||||
&Block::PreviewChanged);
|
||||
connect(output->audio_playback_cache(),
|
||||
&AudioPlaybackCache::Invalidated, this, &Block::PreviewChanged);
|
||||
connect(output->thumbnail_cache(), &FrameHashCache::Validated, this,
|
||||
&Block::PreviewChanged);
|
||||
connect(output->waveform_cache(), &AudioPlaybackCache::Validated, this,
|
||||
&Block::PreviewChanged);
|
||||
connect(output->video_frame_cache(), &FrameHashCache::Validated, this,
|
||||
&Block::PreviewChanged);
|
||||
connect(output->audio_playback_cache(), &AudioPlaybackCache::Validated,
|
||||
this, &Block::PreviewChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::InputDisconnectedEvent(const QString &input, int element, Node *output)
|
||||
void ClipBlock::InputDisconnectedEvent(const QString &input, int element,
|
||||
Node *output)
|
||||
{
|
||||
super::InputDisconnectedEvent(input, element, output);
|
||||
super::InputDisconnectedEvent(input, element, output);
|
||||
|
||||
if (input == kBufferIn) {
|
||||
disconnect(output->thumbnail_cache(), &FrameHashCache::Invalidated, this, &Block::PreviewChanged);
|
||||
disconnect(output->waveform_cache(), &AudioPlaybackCache::Invalidated, this, &Block::PreviewChanged);
|
||||
disconnect(output->video_frame_cache(), &FrameHashCache::Invalidated, this, &Block::PreviewChanged);
|
||||
disconnect(output->audio_playback_cache(), &AudioPlaybackCache::Invalidated, this, &Block::PreviewChanged);
|
||||
disconnect(output->thumbnail_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
|
||||
disconnect(output->waveform_cache(), &AudioPlaybackCache::Validated, this, &Block::PreviewChanged);
|
||||
disconnect(output->video_frame_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
|
||||
disconnect(output->audio_playback_cache(), &AudioPlaybackCache::Validated, this, &Block::PreviewChanged);
|
||||
}
|
||||
if (input == kBufferIn) {
|
||||
disconnect(output->thumbnail_cache(), &FrameHashCache::Invalidated,
|
||||
this, &Block::PreviewChanged);
|
||||
disconnect(output->waveform_cache(), &AudioPlaybackCache::Invalidated,
|
||||
this, &Block::PreviewChanged);
|
||||
disconnect(output->video_frame_cache(), &FrameHashCache::Invalidated,
|
||||
this, &Block::PreviewChanged);
|
||||
disconnect(output->audio_playback_cache(),
|
||||
&AudioPlaybackCache::Invalidated, this,
|
||||
&Block::PreviewChanged);
|
||||
disconnect(output->thumbnail_cache(), &FrameHashCache::Validated, this,
|
||||
&Block::PreviewChanged);
|
||||
disconnect(output->waveform_cache(), &AudioPlaybackCache::Validated,
|
||||
this, &Block::PreviewChanged);
|
||||
disconnect(output->video_frame_cache(), &FrameHashCache::Validated,
|
||||
this, &Block::PreviewChanged);
|
||||
disconnect(output->audio_playback_cache(),
|
||||
&AudioPlaybackCache::Validated, this,
|
||||
&Block::PreviewChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
super::InputValueChangedEvent(input, element);
|
||||
super::InputValueChangedEvent(input, element);
|
||||
|
||||
if (input == kAutoCacheInput) {
|
||||
if (IsAutocaching()) {
|
||||
RequestInvalidatedFromConnected();
|
||||
} else {
|
||||
Track::Type type = GetTrackType();
|
||||
if (input == kAutoCacheInput) {
|
||||
if (IsAutocaching()) {
|
||||
RequestInvalidatedFromConnected();
|
||||
} else {
|
||||
Track::Type type = GetTrackType();
|
||||
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
if (type == Track::kVideo) {
|
||||
emit connected->video_frame_cache()->CancelAll();
|
||||
} else if (type == Track::kAudio) {
|
||||
emit connected->audio_playback_cache()->CancelAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (input == kLoopModeInput) {
|
||||
emit PreviewChanged();
|
||||
}
|
||||
if (Node *connected = GetConnectedOutput(kBufferIn)) {
|
||||
if (type == Track::kVideo) {
|
||||
emit connected->video_frame_cache()->CancelAll();
|
||||
} else if (type == Track::kAudio) {
|
||||
emit connected->audio_playback_cache()->CancelAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (input == kLoopModeInput) {
|
||||
emit PreviewChanged();
|
||||
}
|
||||
}
|
||||
|
||||
TimeRange ClipBlock::InputTimeAdjustment(const QString& input, int element, const TimeRange& input_time, bool clamp) const
|
||||
TimeRange ClipBlock::InputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time,
|
||||
bool clamp) const
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(element)
|
||||
|
||||
if (input == kBufferIn) {
|
||||
return TimeRange(SequenceToMediaTime(input_time.in()), SequenceToMediaTime(input_time.out()));
|
||||
}
|
||||
if (input == kBufferIn) {
|
||||
return TimeRange(SequenceToMediaTime(input_time.in()),
|
||||
SequenceToMediaTime(input_time.out()));
|
||||
}
|
||||
|
||||
return super::InputTimeAdjustment(input, element, input_time, clamp);
|
||||
return super::InputTimeAdjustment(input, element, input_time, clamp);
|
||||
}
|
||||
|
||||
TimeRange ClipBlock::OutputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const
|
||||
TimeRange ClipBlock::OutputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time) const
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(element)
|
||||
|
||||
if (input == kBufferIn) {
|
||||
return TimeRange(MediaToSequenceTime(input_time.in()), MediaToSequenceTime(input_time.out()));
|
||||
}
|
||||
if (input == kBufferIn) {
|
||||
return TimeRange(MediaToSequenceTime(input_time.in()),
|
||||
MediaToSequenceTime(input_time.out()));
|
||||
}
|
||||
|
||||
return super::OutputTimeAdjustment(input, element, input_time);
|
||||
return super::OutputTimeAdjustment(input, element, input_time);
|
||||
}
|
||||
|
||||
void ClipBlock::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
void ClipBlock::Value(const NodeValueRow &value, const NodeGlobals &globals,
|
||||
NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(globals)
|
||||
Q_UNUSED(globals)
|
||||
|
||||
// We discard most values here except for the buffer we received
|
||||
NodeValue data = value[kBufferIn];
|
||||
// We discard most values here except for the buffer we received
|
||||
NodeValue data = value[kBufferIn];
|
||||
|
||||
table->Clear();
|
||||
if (data.type() != NodeValue::kNone) {
|
||||
table->Push(data);
|
||||
}
|
||||
table->Clear();
|
||||
if (data.type() != NodeValue::kNone) {
|
||||
table->Push(data);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kBufferIn, tr("Buffer"));
|
||||
SetInputName(kMediaInInput, tr("Media In"));
|
||||
SetInputName(kSpeedInput, tr("Speed"));
|
||||
SetInputName(kReverseInput, tr("Reverse"));
|
||||
SetInputName(kMaintainAudioPitchInput, tr("Maintain Audio Pitch"));
|
||||
SetInputName(kLoopModeInput, tr("Loop"));
|
||||
SetComboBoxStrings(kLoopModeInput, {tr("None"), tr("Loop"), tr("Clamp")});
|
||||
SetInputName(kBufferIn, tr("Buffer"));
|
||||
SetInputName(kMediaInInput, tr("Media In"));
|
||||
SetInputName(kSpeedInput, tr("Speed"));
|
||||
SetInputName(kReverseInput, tr("Reverse"));
|
||||
SetInputName(kMaintainAudioPitchInput, tr("Maintain Audio Pitch"));
|
||||
SetInputName(kLoopModeInput, tr("Loop"));
|
||||
SetComboBoxStrings(kLoopModeInput, { tr("None"), tr("Loop"), tr("Clamp") });
|
||||
}
|
||||
|
||||
void ClipBlock::AddCachePassthroughFrom(ClipBlock *other)
|
||||
{
|
||||
if (auto tc = this->video_frame_cache()) {
|
||||
if (auto oc = other->video_frame_cache()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
if (auto tc = this->video_frame_cache()) {
|
||||
if (auto oc = other->video_frame_cache()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto tc = this->audio_playback_cache()) {
|
||||
if (auto oc = other->audio_playback_cache()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
if (auto tc = this->audio_playback_cache()) {
|
||||
if (auto oc = other->audio_playback_cache()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto tc = this->thumbnails()) {
|
||||
if (auto oc = other->thumbnails()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
if (auto tc = this->thumbnails()) {
|
||||
if (auto oc = other->thumbnails()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto tc = this->waveform()) {
|
||||
if (auto oc = other->waveform()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
if (auto tc = this->waveform()) {
|
||||
if (auto oc = other->waveform()) {
|
||||
tc->SetPassthrough(oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipBlock::ConnectedToPreviewEvent()
|
||||
{
|
||||
RequestInvalidatedFromConnected();
|
||||
RequestInvalidatedFromConnected();
|
||||
}
|
||||
|
||||
TimeRange ClipBlock::media_range() const
|
||||
{
|
||||
return InputTimeAdjustment(kBufferIn, -1, TimeRange(0, length()), false);
|
||||
return InputTimeAdjustment(kBufferIn, -1, TimeRange(0, length()), false);
|
||||
}
|
||||
|
||||
MultiCamNode *ClipBlock::FindMulticam()
|
||||
{
|
||||
auto v = FindInputNodesConnectedToInput<MultiCamNode>(NodeInput(this, kBufferIn), 1);
|
||||
if (v.empty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return v.first();
|
||||
}
|
||||
auto v = FindInputNodesConnectedToInput<MultiCamNode>(
|
||||
NodeInput(this, kBufferIn), 1);
|
||||
if (v.empty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return v.first();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+174
-157
@@ -27,227 +27,244 @@
|
||||
#include "node/input/multicam/multicamnode.h"
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ViewerOutput;
|
||||
|
||||
/**
|
||||
* @brief Node that represents a block of Media
|
||||
*/
|
||||
class ClipBlock : public Block
|
||||
{
|
||||
Q_OBJECT
|
||||
class ClipBlock : public Block {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClipBlock();
|
||||
ClipBlock();
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(ClipBlock)
|
||||
NODE_DEFAULT_FUNCTIONS(ClipBlock)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual void set_length_and_media_out(const rational &length) override;
|
||||
virtual void set_length_and_media_in(const rational &length) override;
|
||||
virtual void set_length_and_media_out(const rational &length) override;
|
||||
virtual void set_length_and_media_in(const rational &length) override;
|
||||
|
||||
Track::Type GetTrackType() const
|
||||
{
|
||||
if (track()) {
|
||||
return track()->type();
|
||||
} else {
|
||||
return Track::kNone;
|
||||
}
|
||||
}
|
||||
Track::Type GetTrackType() const
|
||||
{
|
||||
if (track()) {
|
||||
return track()->type();
|
||||
} else {
|
||||
return Track::kNone;
|
||||
}
|
||||
}
|
||||
|
||||
rational media_in() const;
|
||||
void set_media_in(const rational& media_in);
|
||||
rational media_in() const;
|
||||
void set_media_in(const rational &media_in);
|
||||
|
||||
bool IsAutocaching() const { return GetStandardValue(kAutoCacheInput).toBool(); }
|
||||
void SetAutocache(bool e);
|
||||
bool IsAutocaching() const
|
||||
{
|
||||
return GetStandardValue(kAutoCacheInput).toBool();
|
||||
}
|
||||
void SetAutocache(bool e);
|
||||
|
||||
void DiscardCache();
|
||||
void DiscardCache();
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options) override;
|
||||
virtual void InvalidateCache(const TimeRange &range, const QString &from,
|
||||
int element,
|
||||
InvalidateCacheOptions options) override;
|
||||
|
||||
virtual TimeRange InputTimeAdjustment(const QString& input, int element, const TimeRange& input_time, bool clamp) const override;
|
||||
virtual TimeRange InputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time,
|
||||
bool clamp) const override;
|
||||
|
||||
virtual TimeRange OutputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const override;
|
||||
virtual TimeRange
|
||||
OutputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time) const override;
|
||||
|
||||
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
virtual void Value(const NodeValueRow &value, const NodeGlobals &globals,
|
||||
NodeValueTable *table) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
void RequestInvalidatedFromConnected(bool force_all = false, const TimeRange &intersect = TimeRange());
|
||||
void
|
||||
RequestInvalidatedFromConnected(bool force_all = false,
|
||||
const TimeRange &intersect = TimeRange());
|
||||
|
||||
double speed() const
|
||||
{
|
||||
return GetStandardValue(kSpeedInput).toDouble();
|
||||
}
|
||||
double speed() const
|
||||
{
|
||||
return GetStandardValue(kSpeedInput).toDouble();
|
||||
}
|
||||
|
||||
bool reverse() const
|
||||
{
|
||||
return GetStandardValue(kReverseInput).toBool();
|
||||
}
|
||||
bool reverse() const
|
||||
{
|
||||
return GetStandardValue(kReverseInput).toBool();
|
||||
}
|
||||
|
||||
void set_reverse(bool e)
|
||||
{
|
||||
SetStandardValue(kReverseInput, e);
|
||||
}
|
||||
void set_reverse(bool e)
|
||||
{
|
||||
SetStandardValue(kReverseInput, e);
|
||||
}
|
||||
|
||||
bool maintain_audio_pitch() const
|
||||
{
|
||||
return GetStandardValue(kMaintainAudioPitchInput).toBool();
|
||||
}
|
||||
bool maintain_audio_pitch() const
|
||||
{
|
||||
return GetStandardValue(kMaintainAudioPitchInput).toBool();
|
||||
}
|
||||
|
||||
void set_maintain_audio_pitch(bool e)
|
||||
{
|
||||
SetStandardValue(kMaintainAudioPitchInput, e);
|
||||
}
|
||||
void set_maintain_audio_pitch(bool e)
|
||||
{
|
||||
SetStandardValue(kMaintainAudioPitchInput, e);
|
||||
}
|
||||
|
||||
TransitionBlock* in_transition()
|
||||
{
|
||||
return in_transition_;
|
||||
}
|
||||
TransitionBlock *in_transition()
|
||||
{
|
||||
return in_transition_;
|
||||
}
|
||||
|
||||
void set_in_transition(TransitionBlock* t)
|
||||
{
|
||||
in_transition_ = t;
|
||||
}
|
||||
void set_in_transition(TransitionBlock *t)
|
||||
{
|
||||
in_transition_ = t;
|
||||
}
|
||||
|
||||
TransitionBlock* out_transition()
|
||||
{
|
||||
return out_transition_;
|
||||
}
|
||||
TransitionBlock *out_transition()
|
||||
{
|
||||
return out_transition_;
|
||||
}
|
||||
|
||||
void set_out_transition(TransitionBlock* t)
|
||||
{
|
||||
out_transition_ = t;
|
||||
}
|
||||
void set_out_transition(TransitionBlock *t)
|
||||
{
|
||||
out_transition_ = t;
|
||||
}
|
||||
|
||||
const QVector<Block*>& block_links() const
|
||||
{
|
||||
return block_links_;
|
||||
}
|
||||
const QVector<Block *> &block_links() const
|
||||
{
|
||||
return block_links_;
|
||||
}
|
||||
|
||||
FrameHashCache *connected_video_cache() const
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->video_frame_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
FrameHashCache *connected_video_cache() const
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->video_frame_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AudioPlaybackCache *connected_audio_cache() const
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->audio_playback_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
AudioPlaybackCache *connected_audio_cache() const
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->audio_playback_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FrameHashCache *thumbnails()
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->thumbnail_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
FrameHashCache *thumbnails()
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->thumbnail_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AudioWaveformCache *waveform()
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->waveform_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
AudioWaveformCache *waveform()
|
||||
{
|
||||
if (Node *n = GetConnectedOutput(kBufferIn)) {
|
||||
return n->waveform_cache();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AddCachePassthroughFrom(ClipBlock *other);
|
||||
void AddCachePassthroughFrom(ClipBlock *other);
|
||||
|
||||
ViewerOutput *connected_viewer() const
|
||||
{
|
||||
return connected_viewer_;
|
||||
}
|
||||
ViewerOutput *connected_viewer() const
|
||||
{
|
||||
return connected_viewer_;
|
||||
}
|
||||
|
||||
virtual TimeRange GetVideoCacheRange() const override
|
||||
{
|
||||
return TimeRange(0, length());
|
||||
}
|
||||
virtual TimeRange GetVideoCacheRange() const override
|
||||
{
|
||||
return TimeRange(0, length());
|
||||
}
|
||||
|
||||
virtual TimeRange GetAudioCacheRange() const override
|
||||
{
|
||||
return TimeRange(0, length());
|
||||
}
|
||||
virtual TimeRange GetAudioCacheRange() const override
|
||||
{
|
||||
return TimeRange(0, length());
|
||||
}
|
||||
|
||||
virtual void ConnectedToPreviewEvent() override;
|
||||
virtual void ConnectedToPreviewEvent() override;
|
||||
|
||||
TimeRange media_range() const;
|
||||
TimeRange media_range() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get currently set loop mode
|
||||
*/
|
||||
LoopMode loop_mode() const
|
||||
{
|
||||
return static_cast<LoopMode>(GetStandardValue(kLoopModeInput).toInt());
|
||||
}
|
||||
LoopMode loop_mode() const
|
||||
{
|
||||
return static_cast<LoopMode>(GetStandardValue(kLoopModeInput).toInt());
|
||||
}
|
||||
|
||||
void set_loop_mode(LoopMode l)
|
||||
{
|
||||
SetStandardValue(kLoopModeInput, int(l));
|
||||
}
|
||||
void set_loop_mode(LoopMode l)
|
||||
{
|
||||
SetStandardValue(kLoopModeInput, int(l));
|
||||
}
|
||||
|
||||
MultiCamNode *FindMulticam();
|
||||
MultiCamNode *FindMulticam();
|
||||
|
||||
static const QString kBufferIn;
|
||||
static const QString kMediaInInput;
|
||||
static const QString kSpeedInput;
|
||||
static const QString kReverseInput;
|
||||
static const QString kMaintainAudioPitchInput;
|
||||
static const QString kLoopModeInput;
|
||||
static const QString kBufferIn;
|
||||
static const QString kMediaInInput;
|
||||
static const QString kSpeedInput;
|
||||
static const QString kReverseInput;
|
||||
static const QString kMaintainAudioPitchInput;
|
||||
static const QString kLoopModeInput;
|
||||
|
||||
static const QString kAutoCacheInput;
|
||||
static const QString kAutoCacheInput;
|
||||
|
||||
protected:
|
||||
virtual void LinkChangeEvent() override;
|
||||
virtual void LinkChangeEvent() override;
|
||||
|
||||
virtual void InputConnectedEvent(const QString& input, int element, Node *output) override;
|
||||
virtual void InputConnectedEvent(const QString &input, int element,
|
||||
Node *output) override;
|
||||
|
||||
virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override;
|
||||
virtual void InputDisconnectedEvent(const QString &input, int element,
|
||||
Node *output) override;
|
||||
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
virtual void InputValueChangedEvent(const QString &input,
|
||||
int element) override;
|
||||
|
||||
private:
|
||||
enum SequenceToMediaTimeFlag
|
||||
{
|
||||
kSTMNone = 0x0,
|
||||
kSTMIgnoreReverse = 0x1,
|
||||
kSTMIgnoreSpeed = 0x2,
|
||||
kSTMIgnoreLoop = 0x4
|
||||
};
|
||||
enum SequenceToMediaTimeFlag {
|
||||
kSTMNone = 0x0,
|
||||
kSTMIgnoreReverse = 0x1,
|
||||
kSTMIgnoreSpeed = 0x2,
|
||||
kSTMIgnoreLoop = 0x4
|
||||
};
|
||||
|
||||
rational SequenceToMediaTime(const rational& sequence_time, uint64_t flags = kSTMNone) const;
|
||||
rational SequenceToMediaTime(const rational &sequence_time,
|
||||
uint64_t flags = kSTMNone) const;
|
||||
|
||||
rational MediaToSequenceTime(const rational& media_time) const;
|
||||
rational MediaToSequenceTime(const rational &media_time) const;
|
||||
|
||||
void RequestRangeFromConnected(const TimeRange &range);
|
||||
void RequestRangeFromConnected(const TimeRange &range);
|
||||
|
||||
void RequestRangeForCache(PlaybackCache *cache, const TimeRange &max_range, const TimeRange &range, bool invalidate, bool request);
|
||||
void RequestInvalidatedForCache(PlaybackCache *cache, const TimeRange &max_range);
|
||||
void RequestRangeForCache(PlaybackCache *cache, const TimeRange &max_range,
|
||||
const TimeRange &range, bool invalidate,
|
||||
bool request);
|
||||
void RequestInvalidatedForCache(PlaybackCache *cache,
|
||||
const TimeRange &max_range);
|
||||
|
||||
bool GetAdjustedThumbnailRange(TimeRange *r) const;
|
||||
bool GetAdjustedThumbnailRange(TimeRange *r) const;
|
||||
|
||||
QVector<Block*> block_links_;
|
||||
QVector<Block *> block_links_;
|
||||
|
||||
TransitionBlock* in_transition_;
|
||||
TransitionBlock* out_transition_;
|
||||
TransitionBlock *in_transition_;
|
||||
TransitionBlock *out_transition_;
|
||||
|
||||
ViewerOutput *connected_viewer_;
|
||||
ViewerOutput *connected_viewer_;
|
||||
|
||||
private:
|
||||
rational last_media_in_;
|
||||
|
||||
rational last_media_in_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "gap.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
GapBlock::GapBlock()
|
||||
{
|
||||
@@ -28,17 +29,17 @@ GapBlock::GapBlock()
|
||||
|
||||
QString GapBlock::Name() const
|
||||
{
|
||||
return tr("Gap");
|
||||
return tr("Gap");
|
||||
}
|
||||
|
||||
QString GapBlock::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.gap");
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.gap");
|
||||
}
|
||||
|
||||
QString GapBlock::Description() const
|
||||
{
|
||||
return tr("A time-based node that represents an empty space.");
|
||||
return tr("A time-based node that represents an empty space.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,23 +23,22 @@
|
||||
|
||||
#include "node/block/block.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Node that represents nothing in its respective track for a certain period of time
|
||||
*/
|
||||
class GapBlock : public Block
|
||||
{
|
||||
Q_OBJECT
|
||||
class GapBlock : public Block {
|
||||
Q_OBJECT
|
||||
public:
|
||||
GapBlock();
|
||||
GapBlock();
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(GapBlock)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
NODE_DEFAULT_FUNCTIONS(GapBlock)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "subtitle.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super ClipBlock
|
||||
|
||||
@@ -28,43 +29,45 @@ const QString SubtitleBlock::kTextIn = QStringLiteral("text_in");
|
||||
|
||||
SubtitleBlock::SubtitleBlock()
|
||||
{
|
||||
AddInput(kTextIn, NodeValue::kText, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kTextIn, NodeValue::kText,
|
||||
InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
|
||||
SetInputFlag(kBufferIn, kInputFlagHidden);
|
||||
SetInputFlag(kLengthInput, kInputFlagHidden);
|
||||
SetInputFlag(kMediaInInput, kInputFlagHidden);
|
||||
SetInputFlag(kSpeedInput, kInputFlagHidden);
|
||||
SetInputFlag(kReverseInput, kInputFlagHidden);
|
||||
SetInputFlag(kMaintainAudioPitchInput, kInputFlagHidden);
|
||||
SetInputFlag(kBufferIn, kInputFlagHidden);
|
||||
SetInputFlag(kLengthInput, kInputFlagHidden);
|
||||
SetInputFlag(kMediaInInput, kInputFlagHidden);
|
||||
SetInputFlag(kSpeedInput, kInputFlagHidden);
|
||||
SetInputFlag(kReverseInput, kInputFlagHidden);
|
||||
SetInputFlag(kMaintainAudioPitchInput, kInputFlagHidden);
|
||||
|
||||
// Undo block flag that hides in param view
|
||||
SetFlag(kDontShowInParamView, false);
|
||||
// Undo block flag that hides in param view
|
||||
SetFlag(kDontShowInParamView, false);
|
||||
}
|
||||
|
||||
QString SubtitleBlock::Name() const
|
||||
{
|
||||
if (GetText().isEmpty()) {
|
||||
return tr("Subtitle");
|
||||
} else {
|
||||
return GetText();
|
||||
}
|
||||
if (GetText().isEmpty()) {
|
||||
return tr("Subtitle");
|
||||
} else {
|
||||
return GetText();
|
||||
}
|
||||
}
|
||||
|
||||
QString SubtitleBlock::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.subtitle");
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.subtitle");
|
||||
}
|
||||
|
||||
QString SubtitleBlock::Description() const
|
||||
{
|
||||
return tr("A time-based node representing a single subtitle element for a certain period of time.");
|
||||
return tr(
|
||||
"A time-based node representing a single subtitle element for a certain period of time.");
|
||||
}
|
||||
|
||||
void SubtitleBlock::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kTextIn, tr("Text"));
|
||||
SetInputName(kTextIn, tr("Text"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,34 +23,33 @@
|
||||
|
||||
#include "node/block/clip/clip.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SubtitleBlock : public ClipBlock
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class SubtitleBlock : public ClipBlock {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SubtitleBlock();
|
||||
SubtitleBlock();
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(SubtitleBlock)
|
||||
NODE_DEFAULT_FUNCTIONS(SubtitleBlock)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
static const QString kTextIn;
|
||||
static const QString kTextIn;
|
||||
|
||||
QString GetText() const
|
||||
{
|
||||
return GetStandardValue(kTextIn).toString();
|
||||
}
|
||||
|
||||
void SetText(const QString &text)
|
||||
{
|
||||
SetStandardValue(kTextIn, text);
|
||||
}
|
||||
QString GetText() const
|
||||
{
|
||||
return GetStandardValue(kTextIn).toString();
|
||||
}
|
||||
|
||||
void SetText(const QString &text)
|
||||
{
|
||||
SetStandardValue(kTextIn, text);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "crossdissolvetransition.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
CrossDissolveTransition::CrossDissolveTransition()
|
||||
{
|
||||
@@ -28,56 +29,66 @@ CrossDissolveTransition::CrossDissolveTransition()
|
||||
|
||||
QString CrossDissolveTransition::Name() const
|
||||
{
|
||||
return tr("Cross Dissolve");
|
||||
return tr("Cross Dissolve");
|
||||
}
|
||||
|
||||
QString CrossDissolveTransition::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.crossdissolve");
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.crossdissolve");
|
||||
}
|
||||
|
||||
QVector<Node::CategoryID> CrossDissolveTransition::Category() const
|
||||
{
|
||||
return {kCategoryTransition};
|
||||
return { kCategoryTransition };
|
||||
}
|
||||
|
||||
QString CrossDissolveTransition::Description() const
|
||||
{
|
||||
return tr("Smoothly transition between two clips.");
|
||||
return tr("Smoothly transition between two clips.");
|
||||
}
|
||||
|
||||
ShaderCode CrossDissolveTransition::GetShaderCode(const ShaderRequest &request) const
|
||||
ShaderCode
|
||||
CrossDissolveTransition::GetShaderCode(const ShaderRequest &request) const
|
||||
{
|
||||
Q_UNUSED(request)
|
||||
Q_UNUSED(request)
|
||||
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/crossdissolve.frag"), QString());
|
||||
return ShaderCode(
|
||||
FileFunctions::ReadFileAsString(":/shaders/crossdissolve.frag"),
|
||||
QString());
|
||||
}
|
||||
|
||||
void CrossDissolveTransition::SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const
|
||||
void CrossDissolveTransition::SampleJobEvent(const SampleBuffer &from_samples,
|
||||
const SampleBuffer &to_samples,
|
||||
SampleBuffer &out_samples,
|
||||
double time_in) const
|
||||
{
|
||||
for (size_t i=0; i<out_samples.sample_count(); i++) {
|
||||
double this_sample_time = out_samples.audio_params().samples_to_time(i).toDouble() + time_in;
|
||||
double progress = GetTotalProgress(this_sample_time);
|
||||
for (size_t i = 0; i < out_samples.sample_count(); i++) {
|
||||
double this_sample_time =
|
||||
out_samples.audio_params().samples_to_time(i).toDouble() + time_in;
|
||||
double progress = GetTotalProgress(this_sample_time);
|
||||
|
||||
for (int j=0; j<out_samples.audio_params().channel_count(); j++) {
|
||||
out_samples.data(j)[i] = 0;
|
||||
for (int j = 0; j < out_samples.audio_params().channel_count(); j++) {
|
||||
out_samples.data(j)[i] = 0;
|
||||
|
||||
if (from_samples.is_allocated()) {
|
||||
if (i < from_samples.sample_count()) {
|
||||
out_samples.data(j)[i] += from_samples.data(j)[i] * TransformCurve(1.0 - progress);
|
||||
}
|
||||
}
|
||||
if (from_samples.is_allocated()) {
|
||||
if (i < from_samples.sample_count()) {
|
||||
out_samples.data(j)[i] += from_samples.data(j)[i] *
|
||||
TransformCurve(1.0 - progress);
|
||||
}
|
||||
}
|
||||
|
||||
if (to_samples.is_allocated()) {
|
||||
// Offset input samples from the end
|
||||
size_t remain = (out_samples.sample_count() - to_samples.sample_count());
|
||||
if (i >= remain) {
|
||||
qint64 in_index = i - remain;
|
||||
out_samples.data(j)[i] += to_samples.data(j)[in_index] * TransformCurve(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (to_samples.is_allocated()) {
|
||||
// Offset input samples from the end
|
||||
size_t remain =
|
||||
(out_samples.sample_count() - to_samples.sample_count());
|
||||
if (i >= remain) {
|
||||
qint64 in_index = i - remain;
|
||||
out_samples.data(j)[i] +=
|
||||
to_samples.data(j)[in_index] * TransformCurve(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,28 +23,31 @@
|
||||
|
||||
#include "node/block/transition/transition.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CrossDissolveTransition : public TransitionBlock
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class CrossDissolveTransition : public TransitionBlock {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CrossDissolveTransition();
|
||||
CrossDissolveTransition();
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(CrossDissolveTransition)
|
||||
NODE_DEFAULT_FUNCTIONS(CrossDissolveTransition)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
//virtual void Retranslate() override;
|
||||
//virtual void Retranslate() override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override;
|
||||
virtual ShaderCode
|
||||
GetShaderCode(const ShaderRequest &request) const override;
|
||||
|
||||
protected:
|
||||
virtual void SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const override;
|
||||
|
||||
virtual void SampleJobEvent(const SampleBuffer &from_samples,
|
||||
const SampleBuffer &to_samples,
|
||||
SampleBuffer &out_samples,
|
||||
double time_in) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "diptocolortransition.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const QString DipToColorTransition::kColorInput = QStringLiteral("color_in");
|
||||
|
||||
@@ -28,46 +29,51 @@ const QString DipToColorTransition::kColorInput = QStringLiteral("color_in");
|
||||
|
||||
DipToColorTransition::DipToColorTransition()
|
||||
{
|
||||
AddInput(kColorInput, NodeValue::kColor, QVariant::fromValue(Color(0, 0, 0)));
|
||||
AddInput(kColorInput, NodeValue::kColor,
|
||||
QVariant::fromValue(Color(0, 0, 0)));
|
||||
}
|
||||
|
||||
QString DipToColorTransition::Name() const
|
||||
{
|
||||
return tr("Dip To Color");
|
||||
return tr("Dip To Color");
|
||||
}
|
||||
|
||||
QString DipToColorTransition::id() const
|
||||
{
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.diptocolor");
|
||||
return QStringLiteral("org.olivevideoeditor.Olive.diptocolor");
|
||||
}
|
||||
|
||||
QVector<Node::CategoryID> DipToColorTransition::Category() const
|
||||
{
|
||||
return {kCategoryTransition};
|
||||
return { kCategoryTransition };
|
||||
}
|
||||
|
||||
QString DipToColorTransition::Description() const
|
||||
{
|
||||
return tr("Transition between clips by dipping to a color.");
|
||||
return tr("Transition between clips by dipping to a color.");
|
||||
}
|
||||
|
||||
ShaderCode DipToColorTransition::GetShaderCode(const ShaderRequest &request) const
|
||||
ShaderCode
|
||||
DipToColorTransition::GetShaderCode(const ShaderRequest &request) const
|
||||
{
|
||||
Q_UNUSED(request)
|
||||
Q_UNUSED(request)
|
||||
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/diptoblack.frag"), QString());
|
||||
return ShaderCode(
|
||||
FileFunctions::ReadFileAsString(":/shaders/diptoblack.frag"),
|
||||
QString());
|
||||
}
|
||||
|
||||
void DipToColorTransition::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kColorInput, tr("Color"));
|
||||
SetInputName(kColorInput, tr("Color"));
|
||||
}
|
||||
|
||||
void DipToColorTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJob *job) const
|
||||
void DipToColorTransition::ShaderJobEvent(const NodeValueRow &value,
|
||||
ShaderJob *job) const
|
||||
{
|
||||
job->Insert(kColorInput, value);
|
||||
job->Insert(kColorInput, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,30 +23,31 @@
|
||||
|
||||
#include "node/block/transition/transition.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class DipToColorTransition : public TransitionBlock
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class DipToColorTransition : public TransitionBlock {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DipToColorTransition();
|
||||
DipToColorTransition();
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(DipToColorTransition)
|
||||
NODE_DEFAULT_FUNCTIONS(DipToColorTransition)
|
||||
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
virtual QString Name() const override;
|
||||
virtual QString id() const override;
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const ShaderRequest &request) const override;
|
||||
virtual ShaderCode
|
||||
GetShaderCode(const ShaderRequest &request) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
static const QString kColorInput;
|
||||
static const QString kColorInput;
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob *job) const override;
|
||||
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value,
|
||||
ShaderJob *job) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
#include "node/output/track/track.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super Block
|
||||
|
||||
@@ -33,282 +34,310 @@ const QString TransitionBlock::kInBlockInput = QStringLiteral("in_block_in");
|
||||
const QString TransitionBlock::kCurveInput = QStringLiteral("curve_in");
|
||||
const QString TransitionBlock::kCenterInput = QStringLiteral("center_in");
|
||||
|
||||
TransitionBlock::TransitionBlock() :
|
||||
connected_out_block_(nullptr),
|
||||
connected_in_block_(nullptr)
|
||||
TransitionBlock::TransitionBlock()
|
||||
: connected_out_block_(nullptr)
|
||||
, connected_in_block_(nullptr)
|
||||
{
|
||||
AddInput(kOutBlockInput, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(kOutBlockInput, NodeValue::kNone,
|
||||
InputFlags(kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kInBlockInput, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(kInBlockInput, NodeValue::kNone,
|
||||
InputFlags(kInputFlagNotKeyframable));
|
||||
|
||||
AddInput(kCurveInput, NodeValue::kCombo, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
|
||||
AddInput(kCurveInput, NodeValue::kCombo,
|
||||
InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
|
||||
|
||||
AddInput(kCenterInput, NodeValue::kRational, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
|
||||
SetInputProperty(kCenterInput, QStringLiteral("view"), RationalSlider::kTime);
|
||||
SetInputProperty(kCenterInput, QStringLiteral("viewlock"), true);
|
||||
AddInput(kCenterInput, NodeValue::kRational,
|
||||
InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
|
||||
SetInputProperty(kCenterInput, QStringLiteral("view"),
|
||||
RationalSlider::kTime);
|
||||
SetInputProperty(kCenterInput, QStringLiteral("viewlock"), true);
|
||||
|
||||
SetFlag(kDontShowInParamView, false);
|
||||
SetFlag(kDontShowInParamView, false);
|
||||
}
|
||||
|
||||
void TransitionBlock::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kOutBlockInput, tr("From"));
|
||||
SetInputName(kInBlockInput, tr("To"));
|
||||
SetInputName(kCurveInput, tr("Curve"));
|
||||
SetInputName(kCenterInput, tr("Center Offset"));
|
||||
SetInputName(kOutBlockInput, tr("From"));
|
||||
SetInputName(kInBlockInput, tr("To"));
|
||||
SetInputName(kCurveInput, tr("Curve"));
|
||||
SetInputName(kCenterInput, tr("Center Offset"));
|
||||
|
||||
// These must correspond to the CurveType enum
|
||||
SetComboBoxStrings(kCurveInput, { tr("Linear"), tr("Exponential"), tr("Logarithmic") });
|
||||
// These must correspond to the CurveType enum
|
||||
SetComboBoxStrings(kCurveInput,
|
||||
{ tr("Linear"), tr("Exponential"), tr("Logarithmic") });
|
||||
}
|
||||
|
||||
rational TransitionBlock::in_offset() const
|
||||
{
|
||||
if (is_dual_transition()) {
|
||||
return length()/2 + offset_center();
|
||||
} else if (connected_in_block()) {
|
||||
return length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (is_dual_transition()) {
|
||||
return length() / 2 + offset_center();
|
||||
} else if (connected_in_block()) {
|
||||
return length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rational TransitionBlock::out_offset() const
|
||||
{
|
||||
if (is_dual_transition()) {
|
||||
return length()/2 - offset_center();
|
||||
} else if (connected_out_block()) {
|
||||
return length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (is_dual_transition()) {
|
||||
return length() / 2 - offset_center();
|
||||
} else if (connected_out_block()) {
|
||||
return length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rational TransitionBlock::offset_center() const
|
||||
{
|
||||
return GetStandardValue(kCenterInput).value<rational>();
|
||||
return GetStandardValue(kCenterInput).value<rational>();
|
||||
}
|
||||
|
||||
void TransitionBlock::set_offset_center(const rational &r)
|
||||
{
|
||||
SetStandardValue(kCenterInput, QVariant::fromValue(r));
|
||||
SetStandardValue(kCenterInput, QVariant::fromValue(r));
|
||||
}
|
||||
|
||||
void TransitionBlock::set_offsets_and_length(const rational &in_offset, const rational &out_offset)
|
||||
void TransitionBlock::set_offsets_and_length(const rational &in_offset,
|
||||
const rational &out_offset)
|
||||
{
|
||||
rational len = in_offset + out_offset;
|
||||
rational center = len / 2 - in_offset;
|
||||
rational len = in_offset + out_offset;
|
||||
rational center = len / 2 - in_offset;
|
||||
|
||||
set_length_and_media_out(len);
|
||||
set_offset_center(center);
|
||||
set_length_and_media_out(len);
|
||||
set_offset_center(center);
|
||||
}
|
||||
|
||||
Block *TransitionBlock::connected_out_block() const
|
||||
{
|
||||
return connected_out_block_;
|
||||
return connected_out_block_;
|
||||
}
|
||||
|
||||
Block *TransitionBlock::connected_in_block() const
|
||||
{
|
||||
return connected_in_block_;
|
||||
return connected_in_block_;
|
||||
}
|
||||
|
||||
double TransitionBlock::GetTotalProgress(const double &time) const
|
||||
{
|
||||
return GetInternalTransitionTime(time) / length().toDouble();
|
||||
return GetInternalTransitionTime(time) / length().toDouble();
|
||||
}
|
||||
|
||||
double TransitionBlock::GetOutProgress(const double &time) const
|
||||
{
|
||||
if (out_offset() == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (out_offset() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::clamp(1.0 - (GetInternalTransitionTime(time) / out_offset().toDouble()), 0.0, 1.0);
|
||||
return std::clamp(
|
||||
1.0 - (GetInternalTransitionTime(time) / out_offset().toDouble()), 0.0,
|
||||
1.0);
|
||||
}
|
||||
|
||||
double TransitionBlock::GetInProgress(const double &time) const
|
||||
{
|
||||
if (in_offset() == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (in_offset() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::clamp((GetInternalTransitionTime(time) - out_offset().toDouble()) / in_offset().toDouble(), 0.0, 1.0);
|
||||
return std::clamp(
|
||||
(GetInternalTransitionTime(time) - out_offset().toDouble()) /
|
||||
in_offset().toDouble(),
|
||||
0.0, 1.0);
|
||||
}
|
||||
|
||||
double TransitionBlock::GetInternalTransitionTime(const double &time) const
|
||||
{
|
||||
return time;
|
||||
return time;
|
||||
}
|
||||
|
||||
void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &time) const
|
||||
void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job,
|
||||
const double &time) const
|
||||
{
|
||||
// Provides total transition progress from 0.0 (start) - 1.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_all"),
|
||||
NodeValue(NodeValue::kFloat, GetTotalProgress(time), this));
|
||||
// Provides total transition progress from 0.0 (start) - 1.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_all"),
|
||||
NodeValue(NodeValue::kFloat, GetTotalProgress(time), this));
|
||||
|
||||
// Provides progress of out section from 1.0 (start) - 0.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_out"),
|
||||
NodeValue(NodeValue::kFloat, GetOutProgress(time), this));
|
||||
// Provides progress of out section from 1.0 (start) - 0.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_out"),
|
||||
NodeValue(NodeValue::kFloat, GetOutProgress(time), this));
|
||||
|
||||
// Provides progress of in section from 0.0 (start) - 1.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_in"),
|
||||
NodeValue(NodeValue::kFloat, GetInProgress(time), this));
|
||||
// Provides progress of in section from 0.0 (start) - 1.0 (end)
|
||||
job->Insert(QStringLiteral("ove_tprog_in"),
|
||||
NodeValue(NodeValue::kFloat, GetInProgress(time), this));
|
||||
}
|
||||
|
||||
void TransitionBlock::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
void TransitionBlock::Value(const NodeValueRow &value,
|
||||
const NodeGlobals &globals,
|
||||
NodeValueTable *table) const
|
||||
{
|
||||
NodeValue out_buffer = value[kOutBlockInput];
|
||||
NodeValue in_buffer = value[kInBlockInput];
|
||||
NodeValue::Type data_type = (out_buffer.type() != NodeValue::kNone) ? out_buffer.type() : in_buffer.type();
|
||||
NodeValue out_buffer = value[kOutBlockInput];
|
||||
NodeValue in_buffer = value[kInBlockInput];
|
||||
NodeValue::Type data_type = (out_buffer.type() != NodeValue::kNone) ?
|
||||
out_buffer.type() :
|
||||
in_buffer.type();
|
||||
|
||||
NodeValue::Type job_type = NodeValue::kNone;
|
||||
QVariant push_job;
|
||||
NodeValue::Type job_type = NodeValue::kNone;
|
||||
QVariant push_job;
|
||||
|
||||
if (data_type == NodeValue::kTexture) {
|
||||
// This must be a visual transition
|
||||
ShaderJob job;
|
||||
if (data_type == NodeValue::kTexture) {
|
||||
// This must be a visual transition
|
||||
ShaderJob job;
|
||||
|
||||
if (out_buffer.type() != NodeValue::kNone) {
|
||||
job.Insert(kOutBlockInput, out_buffer);
|
||||
} else {
|
||||
job.Insert(kOutBlockInput, NodeValue(NodeValue::kTexture, nullptr));
|
||||
}
|
||||
if (out_buffer.type() != NodeValue::kNone) {
|
||||
job.Insert(kOutBlockInput, out_buffer);
|
||||
} else {
|
||||
job.Insert(kOutBlockInput, NodeValue(NodeValue::kTexture, nullptr));
|
||||
}
|
||||
|
||||
if (in_buffer.type() != NodeValue::kNone) {
|
||||
job.Insert(kInBlockInput, in_buffer);
|
||||
} else {
|
||||
job.Insert(kInBlockInput, NodeValue(NodeValue::kTexture, nullptr));
|
||||
}
|
||||
if (in_buffer.type() != NodeValue::kNone) {
|
||||
job.Insert(kInBlockInput, in_buffer);
|
||||
} else {
|
||||
job.Insert(kInBlockInput, NodeValue(NodeValue::kTexture, nullptr));
|
||||
}
|
||||
|
||||
job.Insert(kCurveInput, value);
|
||||
job.Insert(kCurveInput, value);
|
||||
|
||||
double time = globals.time().in().toDouble();
|
||||
InsertTransitionTimes(&job, time);
|
||||
double time = globals.time().in().toDouble();
|
||||
InsertTransitionTimes(&job, time);
|
||||
|
||||
ShaderJobEvent(value, &job);
|
||||
ShaderJobEvent(value, &job);
|
||||
|
||||
job_type = NodeValue::kTexture;
|
||||
push_job = QVariant::fromValue(Texture::Job(globals.vparams(), job));
|
||||
} else if (data_type == NodeValue::kSamples) {
|
||||
// This must be an audio transition
|
||||
SampleBuffer from_samples = out_buffer.toSamples();
|
||||
SampleBuffer to_samples = in_buffer.toSamples();
|
||||
job_type = NodeValue::kTexture;
|
||||
push_job = QVariant::fromValue(Texture::Job(globals.vparams(), job));
|
||||
} else if (data_type == NodeValue::kSamples) {
|
||||
// This must be an audio transition
|
||||
SampleBuffer from_samples = out_buffer.toSamples();
|
||||
SampleBuffer to_samples = in_buffer.toSamples();
|
||||
|
||||
if (from_samples.is_allocated() || to_samples.is_allocated()) {
|
||||
double time_in = globals.time().in().toDouble();
|
||||
double time_out = globals.time().out().toDouble();
|
||||
if (from_samples.is_allocated() || to_samples.is_allocated()) {
|
||||
double time_in = globals.time().in().toDouble();
|
||||
double time_out = globals.time().out().toDouble();
|
||||
|
||||
const AudioParams& params = (from_samples.is_allocated()) ? from_samples.audio_params() : to_samples.audio_params();
|
||||
const AudioParams ¶ms = (from_samples.is_allocated()) ?
|
||||
from_samples.audio_params() :
|
||||
to_samples.audio_params();
|
||||
|
||||
SampleBuffer out_samples;
|
||||
SampleBuffer out_samples;
|
||||
|
||||
if (params.is_valid()) {
|
||||
int nb_samples = params.time_to_samples(time_out - time_in);
|
||||
if (params.is_valid()) {
|
||||
int nb_samples = params.time_to_samples(time_out - time_in);
|
||||
|
||||
out_samples = SampleBuffer(params, nb_samples);
|
||||
SampleJobEvent(from_samples, to_samples, out_samples, time_in);
|
||||
}
|
||||
out_samples = SampleBuffer(params, nb_samples);
|
||||
SampleJobEvent(from_samples, to_samples, out_samples, time_in);
|
||||
}
|
||||
|
||||
job_type = NodeValue::kSamples;
|
||||
push_job = QVariant::fromValue(out_samples);
|
||||
}
|
||||
}
|
||||
job_type = NodeValue::kSamples;
|
||||
push_job = QVariant::fromValue(out_samples);
|
||||
}
|
||||
}
|
||||
|
||||
if (!push_job.isNull()) {
|
||||
table->Push(job_type, push_job, this);
|
||||
}
|
||||
if (!push_job.isNull()) {
|
||||
table->Push(job_type, push_job, this);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options)
|
||||
void TransitionBlock::InvalidateCache(const TimeRange &range,
|
||||
const QString &from, int element,
|
||||
InvalidateCacheOptions options)
|
||||
{
|
||||
TimeRange r = range;
|
||||
TimeRange r = range;
|
||||
|
||||
if (from == kOutBlockInput || from == kInBlockInput) {
|
||||
Block *n = dynamic_cast<Block*>(GetConnectedOutput(from));
|
||||
if (n) {
|
||||
r = Track::TransformRangeFromBlock(n, r);
|
||||
}
|
||||
}
|
||||
if (from == kOutBlockInput || from == kInBlockInput) {
|
||||
Block *n = dynamic_cast<Block *>(GetConnectedOutput(from));
|
||||
if (n) {
|
||||
r = Track::TransformRangeFromBlock(n, r);
|
||||
}
|
||||
}
|
||||
|
||||
super::InvalidateCache(r, from, element, options);
|
||||
super::InvalidateCache(r, from, element, options);
|
||||
}
|
||||
|
||||
double TransitionBlock::TransformCurve(double linear) const
|
||||
{
|
||||
switch (static_cast<CurveType>(GetStandardValue(kCurveInput).toInt())) {
|
||||
case kLinear:
|
||||
break;
|
||||
case kExponential:
|
||||
linear *= linear;
|
||||
break;
|
||||
case kLogarithmic:
|
||||
linear = std::sqrt(linear);
|
||||
break;
|
||||
}
|
||||
switch (static_cast<CurveType>(GetStandardValue(kCurveInput).toInt())) {
|
||||
case kLinear:
|
||||
break;
|
||||
case kExponential:
|
||||
linear *= linear;
|
||||
break;
|
||||
case kLogarithmic:
|
||||
linear = std::sqrt(linear);
|
||||
break;
|
||||
}
|
||||
|
||||
return linear;
|
||||
return linear;
|
||||
}
|
||||
|
||||
void TransitionBlock::InputConnectedEvent(const QString &input, int element, Node *output)
|
||||
void TransitionBlock::InputConnectedEvent(const QString &input, int element,
|
||||
Node *output)
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(element)
|
||||
|
||||
if (input == kOutBlockInput) {
|
||||
// If node is not a block, this will just be null
|
||||
if ((connected_out_block_ = dynamic_cast<ClipBlock*>(output))) {
|
||||
connected_out_block_->set_out_transition(this);
|
||||
}
|
||||
} else if (input == kInBlockInput) {
|
||||
// If node is not a block, this will just be null
|
||||
if ((connected_in_block_ = dynamic_cast<ClipBlock*>(output))) {
|
||||
connected_in_block_->set_in_transition(this);
|
||||
}
|
||||
}
|
||||
if (input == kOutBlockInput) {
|
||||
// If node is not a block, this will just be null
|
||||
if ((connected_out_block_ = dynamic_cast<ClipBlock *>(output))) {
|
||||
connected_out_block_->set_out_transition(this);
|
||||
}
|
||||
} else if (input == kInBlockInput) {
|
||||
// If node is not a block, this will just be null
|
||||
if ((connected_in_block_ = dynamic_cast<ClipBlock *>(output))) {
|
||||
connected_in_block_->set_in_transition(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InputDisconnectedEvent(const QString &input, int element, Node *output)
|
||||
void TransitionBlock::InputDisconnectedEvent(const QString &input, int element,
|
||||
Node *output)
|
||||
{
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(element)
|
||||
Q_UNUSED(output)
|
||||
|
||||
if (input == kOutBlockInput) {
|
||||
if (connected_out_block_) {
|
||||
connected_out_block_->set_out_transition(nullptr);
|
||||
connected_out_block_ = nullptr;
|
||||
}
|
||||
} else if (input == kInBlockInput) {
|
||||
if (connected_in_block_) {
|
||||
connected_in_block_->set_in_transition(nullptr);
|
||||
connected_in_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
if (input == kOutBlockInput) {
|
||||
if (connected_out_block_) {
|
||||
connected_out_block_->set_out_transition(nullptr);
|
||||
connected_out_block_ = nullptr;
|
||||
}
|
||||
} else if (input == kInBlockInput) {
|
||||
if (connected_in_block_) {
|
||||
connected_in_block_->set_in_transition(nullptr);
|
||||
connected_in_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeRange TransitionBlock::InputTimeAdjustment(const QString &input, int element, const TimeRange &input_time, bool clamp) const
|
||||
TimeRange TransitionBlock::InputTimeAdjustment(const QString &input,
|
||||
int element,
|
||||
const TimeRange &input_time,
|
||||
bool clamp) const
|
||||
{
|
||||
if (input == kInBlockInput || input == kOutBlockInput) {
|
||||
Block* block = dynamic_cast<Block*>(GetConnectedOutput(input));
|
||||
if (block) {
|
||||
// Retransform time as if it came from the track
|
||||
return input_time + in() - block->in();
|
||||
}
|
||||
}
|
||||
if (input == kInBlockInput || input == kOutBlockInput) {
|
||||
Block *block = dynamic_cast<Block *>(GetConnectedOutput(input));
|
||||
if (block) {
|
||||
// Retransform time as if it came from the track
|
||||
return input_time + in() - block->in();
|
||||
}
|
||||
}
|
||||
|
||||
return super::InputTimeAdjustment(input, element, input_time, clamp);
|
||||
return super::InputTimeAdjustment(input, element, input_time, clamp);
|
||||
}
|
||||
|
||||
TimeRange TransitionBlock::OutputTimeAdjustment(const QString &input, int element, const TimeRange &input_time) const
|
||||
TimeRange
|
||||
TransitionBlock::OutputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time) const
|
||||
{
|
||||
if (input == kInBlockInput || input == kOutBlockInput) {
|
||||
Block* block = dynamic_cast<Block*>(GetConnectedOutput(input));
|
||||
if (block) {
|
||||
return input_time + block->in() - in();
|
||||
}
|
||||
}
|
||||
if (input == kInBlockInput || input == kOutBlockInput) {
|
||||
Block *block = dynamic_cast<Block *>(GetConnectedOutput(input));
|
||||
if (block) {
|
||||
return input_time + block->in() - in();
|
||||
}
|
||||
}
|
||||
|
||||
return super::OutputTimeAdjustment(input, element, input_time);
|
||||
return super::OutputTimeAdjustment(input, element, input_time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,22 +23,22 @@
|
||||
|
||||
#include "node/block/block.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ClipBlock;
|
||||
|
||||
class TransitionBlock : public Block
|
||||
{
|
||||
Q_OBJECT
|
||||
class TransitionBlock : public Block {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TransitionBlock();
|
||||
TransitionBlock();
|
||||
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
rational in_offset() const;
|
||||
rational out_offset() const;
|
||||
rational in_offset() const;
|
||||
rational out_offset() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Return the "middle point" of the transition, relative to the transition
|
||||
*
|
||||
* Used to calculate in/out offsets.
|
||||
@@ -46,62 +46,73 @@ public:
|
||||
* 0 means the center of the transition is right in the middle and the in and out offsets will
|
||||
* be equal.
|
||||
*/
|
||||
rational offset_center() const;
|
||||
void set_offset_center(const rational &r);
|
||||
rational offset_center() const;
|
||||
void set_offset_center(const rational &r);
|
||||
|
||||
void set_offsets_and_length(const rational &in_offset, const rational &out_offset);
|
||||
void set_offsets_and_length(const rational &in_offset,
|
||||
const rational &out_offset);
|
||||
|
||||
bool is_dual_transition() const
|
||||
{
|
||||
return connected_out_block() && connected_in_block();
|
||||
}
|
||||
bool is_dual_transition() const
|
||||
{
|
||||
return connected_out_block() && connected_in_block();
|
||||
}
|
||||
|
||||
Block* connected_out_block() const;
|
||||
Block* connected_in_block() const;
|
||||
Block *connected_out_block() const;
|
||||
Block *connected_in_block() const;
|
||||
|
||||
double GetTotalProgress(const double &time) const;
|
||||
double GetOutProgress(const double &time) const;
|
||||
double GetInProgress(const double &time) const;
|
||||
double GetTotalProgress(const double &time) const;
|
||||
double GetOutProgress(const double &time) const;
|
||||
double GetInProgress(const double &time) const;
|
||||
|
||||
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
virtual void Value(const NodeValueRow &value, const NodeGlobals &globals,
|
||||
NodeValueTable *table) const override;
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
virtual void InvalidateCache(
|
||||
const TimeRange &range, const QString &from, int element = -1,
|
||||
InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
|
||||
static const QString kOutBlockInput;
|
||||
static const QString kInBlockInput;
|
||||
static const QString kCurveInput;
|
||||
static const QString kCenterInput;
|
||||
static const QString kOutBlockInput;
|
||||
static const QString kInBlockInput;
|
||||
static const QString kCurveInput;
|
||||
static const QString kCenterInput;
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob *job) const {}
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob *job) const
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SampleJobEvent(const SampleBuffer &from_samples, const SampleBuffer &to_samples, SampleBuffer &out_samples, double time_in) const {}
|
||||
virtual void SampleJobEvent(const SampleBuffer &from_samples,
|
||||
const SampleBuffer &to_samples,
|
||||
SampleBuffer &out_samples, double time_in) const
|
||||
{
|
||||
}
|
||||
|
||||
double TransformCurve(double linear) const;
|
||||
double TransformCurve(double linear) const;
|
||||
|
||||
virtual void InputConnectedEvent(const QString& input, int element, Node *output) override;
|
||||
virtual void InputConnectedEvent(const QString &input, int element,
|
||||
Node *output) override;
|
||||
|
||||
virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override;
|
||||
virtual void InputDisconnectedEvent(const QString &input, int element,
|
||||
Node *output) override;
|
||||
|
||||
virtual TimeRange InputTimeAdjustment(const QString& input, int element, const TimeRange& input_time, bool clamp) const override;
|
||||
virtual TimeRange InputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time,
|
||||
bool clamp) const override;
|
||||
|
||||
virtual TimeRange OutputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const override;
|
||||
virtual TimeRange
|
||||
OutputTimeAdjustment(const QString &input, int element,
|
||||
const TimeRange &input_time) const override;
|
||||
|
||||
private:
|
||||
enum CurveType {
|
||||
kLinear,
|
||||
kExponential,
|
||||
kLogarithmic
|
||||
};
|
||||
enum CurveType { kLinear, kExponential, kLogarithmic };
|
||||
|
||||
double GetInternalTransitionTime(const double &time) const;
|
||||
double GetInternalTransitionTime(const double &time) const;
|
||||
|
||||
void InsertTransitionTimes(AcceleratedJob* job, const double& time) const;
|
||||
void InsertTransitionTimes(AcceleratedJob *job, const double &time) const;
|
||||
|
||||
ClipBlock* connected_out_block_;
|
||||
|
||||
ClipBlock* connected_in_block_;
|
||||
ClipBlock *connected_out_block_;
|
||||
|
||||
ClipBlock *connected_in_block_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user