reworked timeline elements

This commit is contained in:
itsmattkc
2021-08-01 11:05:18 -07:00
parent 8054124924
commit 6995ffe015
18 changed files with 314 additions and 271 deletions
+6
View File
@@ -94,6 +94,12 @@ public:
AVRational toAVRational() const;
#ifdef USE_OTIO
static rational fromRationalTime(const opentime::RationalTime &t)
{
// Is this the best way to do this?
return fromDouble(t.to_seconds());
}
// Convert Olive ratioanls to opentime rationals with the given framerate (defaults to 24)
opentime::RationalTime toRationalTime(double framerate = 24) const;
#endif
+2 -117
View File
@@ -24,7 +24,6 @@
#include "node/output/track/track.h"
#include "transition/transition.h"
#include "widget/slider/floatslider.h"
#include "widget/slider/rationalslider.h"
namespace olive {
@@ -32,18 +31,13 @@ namespace olive {
#define super Node
const QString Block::kLengthInput = QStringLiteral("length_in");
const QString Block::kMediaInInput = QStringLiteral("media_in_in");
const QString Block::kEnabledInput = QStringLiteral("enabled_in");
const QString Block::kSpeedInput = QStringLiteral("speed_in");
const QString Block::kReverseInput = QStringLiteral("reverse_in");
Block::Block() :
previous_(nullptr),
next_(nullptr),
track_(nullptr),
index_(-1),
in_transition_(nullptr),
out_transition_(nullptr)
index_(-1)
{
AddInput(kLengthInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kLengthInput, QStringLiteral("min"), QVariant::fromValue(rational(0, 1)));
@@ -51,21 +45,8 @@ Block::Block() :
SetInputProperty(kLengthInput, QStringLiteral("viewlock"), true);
IgnoreHashingFrom(kLengthInput);
AddInput(kMediaInInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kMediaInInput, QStringLiteral("view"), RationalSlider::kTime);
SetInputProperty(kMediaInInput, QStringLiteral("viewlock"), true);
IgnoreHashingFrom(kMediaInInput);
AddInput(kEnabledInput, NodeValue::kBoolean, true, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
AddInput(kSpeedInput, NodeValue::kFloat, 1.0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kSpeedInput, QStringLiteral("view"), FloatSlider::kPercentage);
SetInputProperty(kSpeedInput, QStringLiteral("min"), 0.0);
IgnoreHashingFrom(kSpeedInput);
AddInput(kReverseInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
IgnoreHashingFrom(kReverseInput);
// A block's length must be greater than 0
set_length_and_media_out(1);
}
@@ -82,47 +63,23 @@ rational Block::length() const
void Block::set_length_and_media_out(const rational &length)
{
Q_ASSERT(length > 0);
if (length == this->length()) {
return;
}
if (reverse()) {
// Calculate media_in adjustment
set_media_in(SequenceToMediaTime(length - this->length(), true));
}
set_length_internal(length);
}
void Block::set_length_and_media_in(const rational &length)
{
Q_ASSERT(length > 0);
if (length == this->length()) {
return;
}
if (!reverse()) {
// Calculate media_in adjustment
set_media_in(SequenceToMediaTime(this->length() - length));
}
// Set the length without setting media out
set_length_internal(length);
}
rational Block::media_in() const
{
return GetStandardValue(kMediaInInput).value<rational>();
}
void Block::set_media_in(const rational &media_in)
{
SetStandardValue(kMediaInInput, QVariant::fromValue(media_in));
}
bool Block::is_enabled() const
{
return GetStandardValue(kEnabledInput).toBool();
@@ -135,65 +92,9 @@ void Block::set_enabled(bool e)
emit EnabledChanged();
}
rational Block::SequenceToMediaTime(const rational &sequence_time, bool ignore_reverse) 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;
}
rational local_time = sequence_time;
double speed_value = speed();
if (qIsNull(speed_value)) {
// Effectively holds the frame at the in point
local_time = 0;
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
local_time = rational::fromDouble(local_time.toDouble() * speed_value);
}
rational media_time = local_time + media_in();
if (reverse() && !ignore_reverse) {
media_time = length() - media_time;
}
return media_time;
}
rational Block::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;
}
rational sequence_time = media_time;
if (reverse()) {
sequence_time = length() - sequence_time;
}
sequence_time -= media_in();
double speed_value = speed();
if (qIsNull(speed_value)) {
// Effectively holds the frame at the in point, also prevents divide by zero
sequence_time = 0;
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
sequence_time = rational::fromDouble(sequence_time.toDouble() / speed_value);
}
return sequence_time;
}
void Block::InputValueChangedEvent(const QString &input, int element)
{
Q_UNUSED(element)
super::InputValueChangedEvent(input, element);
if (input == kLengthInput) {
emit LengthChanged();
@@ -202,19 +103,6 @@ void Block::InputValueChangedEvent(const QString &input, int element)
}
}
void Block::LinkChangeEvent()
{
block_links_.clear();
foreach (Node* n, links()) {
Block* b = dynamic_cast<Block*>(n);
if (b) {
block_links_.append(b);
}
}
}
bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
{
if (IsInputConnected(input)) {
@@ -239,10 +127,7 @@ void Block::Retranslate()
super::Retranslate();
SetInputName(kLengthInput, tr("Length"));
SetInputName(kMediaInInput, tr("Media In"));
SetInputName(kEnabledInput, tr("Enabled"));
SetInputName(kSpeedInput, tr("Speed"));
SetInputName(kReverseInput, tr("Reverse"));
}
void Block::Hash(const QString &, QCryptographicHash &, const rational &, const VideoParams &) const
+2 -54
View File
@@ -62,8 +62,8 @@ public:
}
rational length() const;
void set_length_and_media_out(const rational &length);
void set_length_and_media_in(const rational &length);
virtual void set_length_and_media_out(const rational &length);
virtual void set_length_and_media_in(const rational &length);
TimeRange range() const
{
@@ -90,9 +90,6 @@ public:
next_ = next;
}
rational media_in() const;
void set_media_in(const rational& media_in);
Track* track() const
{
return track_;
@@ -108,26 +105,6 @@ public:
virtual void Retranslate() override;
TransitionBlock* in_transition()
{
return in_transition_;
}
void set_in_transition(TransitionBlock* t)
{
in_transition_ = t;
}
TransitionBlock* out_transition()
{
return out_transition_;
}
void set_out_transition(TransitionBlock* t)
{
out_transition_ = t;
}
int index() const
{
return index_;
@@ -138,30 +115,12 @@ public:
index_ = i;
}
const QVector<Block*>& block_links() const
{
return block_links_;
}
double speed() const
{
return GetStandardValue(kSpeedInput).toDouble();
}
bool reverse() const
{
return GetStandardValue(kReverseInput).toBool();
}
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override;
static const QString kLengthInput;
static const QString kMediaInInput;
static const QString kEnabledInput;
static const QString kSpeedInput;
static const QString kReverseInput;
public slots:
@@ -171,14 +130,8 @@ signals:
void LengthChanged();
protected:
rational SequenceToMediaTime(const rational& sequence_time, bool ignore_reverse = false) const;
rational MediaToSequenceTime(const rational& media_time) const;
virtual void InputValueChangedEvent(const QString& input, int element) override;
virtual void LinkChangeEvent() override;
bool HashPassthrough(const QString &input, const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const;
Block* previous_;
@@ -192,11 +145,6 @@ private:
Track* track_;
int index_;
TransitionBlock* in_transition_;
TransitionBlock* out_transition_;
QVector<Block*> block_links_;
rational last_length_;
};
+132 -5
View File
@@ -20,17 +20,36 @@
#include "clip.h"
#include "widget/slider/floatslider.h"
#include "widget/slider/rationalslider.h"
namespace olive {
#define super Block
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");
ClipBlock::ClipBlock(bool create_buffer_in)
ClipBlock::ClipBlock() :
in_transition_(nullptr),
out_transition_(nullptr)
{
if (create_buffer_in) {
AddInput(kMediaInInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kMediaInInput, QStringLiteral("view"), RationalSlider::kTime);
SetInputProperty(kMediaInInput, QStringLiteral("viewlock"), true);
IgnoreHashingFrom(kMediaInInput);
AddInput(kSpeedInput, NodeValue::kFloat, 1.0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kSpeedInput, QStringLiteral("view"), FloatSlider::kPercentage);
SetInputProperty(kSpeedInput, QStringLiteral("min"), 0.0);
IgnoreHashingFrom(kSpeedInput);
AddInput(kReverseInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
IgnoreHashingFrom(kReverseInput);
AddInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
}
}
Node *ClipBlock::copy() const
@@ -53,6 +72,100 @@ QString ClipBlock::Description() const
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 (reverse()) {
// Calculate media_in adjustment
set_media_in(SequenceToMediaTime(length - this->length(), true));
}
super::set_length_and_media_out(length);
}
void ClipBlock::set_length_and_media_in(const rational &length)
{
if (length == this->length()) {
return;
}
if (!reverse()) {
// Calculate media_in adjustment
set_media_in(SequenceToMediaTime(this->length() - length));
}
super::set_length_and_media_in(length);
}
rational ClipBlock::media_in() const
{
return GetStandardValue(kMediaInInput).value<rational>();
}
void ClipBlock::set_media_in(const rational &media_in)
{
SetStandardValue(kMediaInInput, QVariant::fromValue(media_in));
}
rational ClipBlock::SequenceToMediaTime(const rational &sequence_time, bool ignore_reverse) 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;
}
rational local_time = sequence_time;
double speed_value = speed();
if (qIsNull(speed_value)) {
// Effectively holds the frame at the in point
local_time = 0;
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
local_time = rational::fromDouble(local_time.toDouble() * speed_value);
}
rational media_time = local_time + media_in();
if (reverse() && !ignore_reverse) {
media_time = length() - 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;
}
rational sequence_time = media_time;
if (reverse()) {
sequence_time = length() - sequence_time;
}
sequence_time -= media_in();
double speed_value = speed();
if (qIsNull(speed_value)) {
// Effectively holds the frame at the in point, also prevents divide by zero
sequence_time = 0;
} else if (!qFuzzyCompare(speed_value, 1.0)) {
// Multiply time
sequence_time = rational::fromDouble(sequence_time.toDouble() / speed_value);
}
return sequence_time;
}
void ClipBlock::InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options)
{
Q_UNUSED(element)
@@ -70,6 +183,19 @@ void ClipBlock::InvalidateCache(const TimeRange& range, const QString& from, int
}
}
void ClipBlock::LinkChangeEvent()
{
block_links_.clear();
foreach (Node* n, links()) {
ClipBlock* b = dynamic_cast<ClipBlock*>(n);
if (b) {
block_links_.append(b);
}
}
}
TimeRange ClipBlock::InputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const
{
Q_UNUSED(element)
@@ -110,9 +236,10 @@ void ClipBlock::Retranslate()
{
super::Retranslate();
if (HasInputWithID(kBufferIn)) {
SetInputName(kBufferIn, tr("Buffer"));
}
SetInputName(kMediaInInput, tr("Media In"));
SetInputName(kSpeedInput, tr("Speed"));
SetInputName(kReverseInput, tr("Reverse"));
}
void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
+58 -1
View File
@@ -32,7 +32,7 @@ class ClipBlock : public Block
{
Q_OBJECT
public:
ClipBlock(bool create_buffer_in = true);
ClipBlock();
NODE_DEFAULT_DESTRUCTOR(ClipBlock)
@@ -42,6 +42,12 @@ public:
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;
rational media_in() const;
void set_media_in(const rational& media_in);
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) const override;
@@ -54,7 +60,58 @@ public:
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
double speed() const
{
return GetStandardValue(kSpeedInput).toDouble();
}
bool reverse() const
{
return GetStandardValue(kReverseInput).toBool();
}
TransitionBlock* in_transition()
{
return in_transition_;
}
void set_in_transition(TransitionBlock* t)
{
in_transition_ = t;
}
TransitionBlock* out_transition()
{
return out_transition_;
}
void set_out_transition(TransitionBlock* t)
{
out_transition_ = t;
}
const QVector<Block*>& block_links() const
{
return block_links_;
}
static const QString kBufferIn;
static const QString kMediaInInput;
static const QString kSpeedInput;
static const QString kReverseInput;
protected:
virtual void LinkChangeEvent() override;
private:
rational SequenceToMediaTime(const rational& sequence_time, bool ignore_reverse = false) const;
rational MediaToSequenceTime(const rational& media_time) const;
QVector<Block*> block_links_;
TransitionBlock* in_transition_;
TransitionBlock* out_transition_;
};
+1 -2
View File
@@ -26,8 +26,7 @@ namespace olive {
const QString SubtitleBlock::kTextIn = QStringLiteral("text_in");
SubtitleBlock::SubtitleBlock() :
super(false)
SubtitleBlock::SubtitleBlock()
{
AddInput(kTextIn, NodeValue::kText, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
}
+23 -24
View File
@@ -21,6 +21,7 @@
#include "transition.h"
#include "common/clamp.h"
#include "node/block/clip/clip.h"
#include "node/output/track/track.h"
namespace olive {
@@ -30,6 +31,8 @@ namespace olive {
const QString TransitionBlock::kOutBlockInput = QStringLiteral("out_block_in");
const QString TransitionBlock::kInBlockInput = QStringLiteral("in_block_in");
const QString TransitionBlock::kCurveInput = QStringLiteral("curve_in");
const QString TransitionBlock::kInOffsetInput = QStringLiteral("in_offset_in");
const QString TransitionBlock::kOutOffsetInput = QStringLiteral("out_offset_in");
TransitionBlock::TransitionBlock() :
connected_out_block_(nullptr),
@@ -40,6 +43,12 @@ TransitionBlock::TransitionBlock() :
AddInput(kInBlockInput, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
AddInput(kCurveInput, NodeValue::kCombo, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
AddInput(kInOffsetInput, NodeValue::kRational, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
AddInput(kOutOffsetInput, NodeValue::kRational, InputFlags(kInputFlagNotKeyframable | kInputFlagNotConnectable));
set_length_and_media_out(0);
}
void TransitionBlock::Retranslate()
@@ -49,6 +58,8 @@ void TransitionBlock::Retranslate()
SetInputName(kOutBlockInput, tr("From"));
SetInputName(kInBlockInput, tr("To"));
SetInputName(kCurveInput, tr("Curve"));
SetInputName(kInOffsetInput, tr("In Offset"));
SetInputName(kOutOffsetInput, tr("Out Offset"));
// These must correspond to the CurveType enum
SetComboBoxStrings(kCurveInput, { tr("Linear"), tr("Exponential"), tr("Logarithmic") });
@@ -56,34 +67,22 @@ void TransitionBlock::Retranslate()
rational TransitionBlock::in_offset() const
{
// If no in block is connected, there's no in offset
if (!connected_in_block()) {
return 0;
}
return GetStandardValue(kInOffsetInput).value<rational>();
}
if (!connected_out_block()) {
// Assume only an in block is connected, in which case this entire transition length
return length();
}
// Assume both are connected
return length() + media_in();
void TransitionBlock::set_in_offset(const rational &os)
{
SetStandardValue(kInOffsetInput, QVariant::fromValue(os));
}
rational TransitionBlock::out_offset() const
{
// If no in block is connected, there's no in offset
if (!connected_out_block()) {
return 0;
}
return GetStandardValue(kOutOffsetInput).value<rational>();
}
if (!connected_in_block()) {
// Assume only an in block is connected, in which case this entire transition length
return length();
}
// Assume both are connected
return -media_in();
void TransitionBlock::set_out_offset(const rational &os)
{
SetStandardValue(kOutOffsetInput, QVariant::fromValue(os));
}
Block *TransitionBlock::connected_out_block() const
@@ -267,12 +266,12 @@ void TransitionBlock::InputConnectedEvent(const QString &input, int element, con
if (input == kOutBlockInput) {
// If node is not a block, this will just be null
if ((connected_out_block_ = dynamic_cast<Block*>(output.node()))) {
if ((connected_out_block_ = dynamic_cast<ClipBlock*>(output.node()))) {
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<Block*>(output.node()))) {
if ((connected_in_block_ = dynamic_cast<ClipBlock*>(output.node()))) {
connected_in_block_->set_in_transition(this);
}
}
+8 -2
View File
@@ -25,6 +25,8 @@
namespace olive {
class ClipBlock;
class TransitionBlock : public Block
{
Q_OBJECT
@@ -36,7 +38,9 @@ public:
virtual void Retranslate() override;
rational in_offset() const;
void set_in_offset(const rational &os);
rational out_offset() const;
void set_out_offset(const rational &os);
Block* connected_out_block() const;
Block* connected_in_block() const;
@@ -54,6 +58,8 @@ public:
static const QString kOutBlockInput;
static const QString kInBlockInput;
static const QString kCurveInput;
static const QString kInOffsetInput;
static const QString kOutOffsetInput;
protected:
virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const;
@@ -81,9 +87,9 @@ private:
void InsertTransitionTimes(AcceleratedJob* job, const double& time) const;
Block* connected_out_block_;
ClipBlock* connected_out_block_;
Block* connected_in_block_;
ClipBlock* connected_in_block_;
};
+11 -2
View File
@@ -25,6 +25,8 @@
#include <QVector3D>
#include <QVector4D>
#include "node/block/clip/clip.h"
#include "node/block/transition/transition.h"
#include "node/project/project.h"
#include "rendermanager.h"
@@ -253,6 +255,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
// Loop through active blocks retrieving their audio
foreach (Block* b, active_blocks) {
if (dynamic_cast<ClipBlock*>(b) || dynamic_cast<TransitionBlock*>(b)) {
TimeRange range_for_block(qMax(b->in(), range.in()),
qMin(b->out(), range.out()));
@@ -268,7 +271,11 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
continue;
}
double speed_value = b->GetStandardValue(Block::kSpeedInput).toDouble();
// If this is a clip, we might have extra speed/reverse information
ClipBlock *clip_cast = dynamic_cast<ClipBlock*>(b);
if (clip_cast) {
double speed_value = clip_cast->speed();
bool reversed = clip_cast->reverse();
if (qIsNull(speed_value)) {
// Just silence, don't think there's any other practical application of 0 speed audio
@@ -278,9 +285,10 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
samples_from_this_block->speed(speed_value);
}
if (b->GetStandardValue(Block::kReverseInput).toBool()) {
if (reversed) {
samples_from_this_block->reverse();
}
}
int copy_length = qMin(max_dest_sz, samples_from_this_block->sample_count());
@@ -291,6 +299,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim
NodeValueTable::Merge({merged_table, table});
}
}
if (ticket_->property("enablewaveforms").toBool()) {
// Generate a visual waveform and send it back to the main thread
+6 -6
View File
@@ -168,7 +168,9 @@ bool LoadOTIOTask::Run()
duration =
rational::fromDouble(static_cast<OTIO::Item*>(otio_block)->source_range()->duration().to_seconds());
block->set_media_in(start_time);
if (otio_block->schema_name() == "Clip") {
static_cast<ClipBlock*>(block)->set_media_in(start_time);
}
block->set_length_and_media_out(duration);
}
@@ -183,14 +185,12 @@ bool LoadOTIOTask::Run()
TransitionBlock* transition_block = static_cast<TransitionBlock*>(block);
OTIO::Transition* otio_block_transition = static_cast<OTIO::Transition*>(otio_block);
duration = rational::fromDouble((otio_block_transition->in_offset() + otio_block_transition->out_offset()).to_seconds());
transition_block->set_length_and_media_out(duration);
// Set how far the transition eats into the previous clip
transition_block->set_in_offset(rational::fromRationalTime(otio_block_transition->in_offset()));
transition_block->set_out_offset(rational::fromRationalTime(otio_block_transition->out_offset()));
if (previous_block) {
Node::ConnectEdge(previous_block, NodeInput(transition_block, TransitionBlock::kOutBlockInput));
// Set how far the transition eats into the previous clip
transition_block->set_media_in(rational::fromDouble(-otio_block_transition->out_offset().to_seconds()));
}
prev_block_transition = true;
}
+4 -3
View File
@@ -1190,7 +1190,7 @@ void TimelineWidget::SetViewTransitionOverlay(ClipBlock *out, ClipBlock *in)
}
}
void TimelineWidget::SetBlockLinksSelected(Block* block, bool selected)
void TimelineWidget::SetBlockLinksSelected(ClipBlock* block, bool selected)
{
foreach (Block* link, block->block_links()) {
if (selected) {
@@ -1550,8 +1550,9 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
rubberband_now_selected_.append(b);
}
if (select_links) {
foreach (Block* link, b->block_links()) {
ClipBlock *c = dynamic_cast<ClipBlock*>(b);
if (c && select_links) {
foreach (Block* link, c->block_links()) {
if (!rubberband_now_selected_.contains(link)) {
AddSelection(link);
rubberband_now_selected_.append(link);
+1 -1
View File
@@ -172,7 +172,7 @@ public:
return selected_blocks_.contains(b);
}
void SetBlockLinksSelected(Block *block, bool selected);
void SetBlockLinksSelected(ClipBlock *block, bool selected);
void QueueScroll(int value);
+11 -13
View File
@@ -54,6 +54,7 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
// Determine if item clicked on is selectable
clicked_item_ = parent()->GetItemAtScenePos(event->GetCoordinates());
ClipBlock *clip_clicked_item = dynamic_cast<ClipBlock*>(clicked_item_);
can_rubberband_select_ = false;
@@ -92,9 +93,9 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
deselected_blocks.append(clicked_item_);
// If not holding alt, deselect all links as well
if (!(event->GetModifiers() & Qt::AltModifier)) {
parent()->SetBlockLinksSelected(clicked_item_, false);
deselected_blocks.append(clicked_item_->block_links());
if (clip_clicked_item && !(event->GetModifiers() & Qt::AltModifier)) {
parent()->SetBlockLinksSelected(clip_clicked_item, false);
deselected_blocks.append(clip_clicked_item->block_links());
}
}
@@ -119,9 +120,9 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
selected_blocks.append(clicked_item_);
// If not holding alt, select all links as well
if (!(event->GetModifiers() & Qt::AltModifier)) {
parent()->SetBlockLinksSelected(clicked_item_, true);
selected_blocks.append(clicked_item_->block_links());
if (clip_clicked_item && !(event->GetModifiers() & Qt::AltModifier)) {
parent()->SetBlockLinksSelected(clip_clicked_item, true);
selected_blocks.append(clip_clicked_item->block_links());
}
parent()->SignalSelectedBlocks(selected_blocks);
@@ -329,10 +330,6 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
// Create ghost for this block
AddGhostFromBlock(block, trim_mode, true);
// Create ghosts for this block's transitions if any
AddGhostFromBlock(block->in_transition(), trim_mode, true);
AddGhostFromBlock(block->out_transition(), trim_mode, true);
}
}
@@ -361,15 +358,16 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
// transition than a trim/roll
bool treat_trim_as_slide = false;
if (dynamic_cast<ClipBlock*>(block)) {
ClipBlock *cb = dynamic_cast<ClipBlock*>(block);
if (cb) {
// See if this clip has a transition attached, and move it with the trim if so
TransitionBlock* connected_transition;
// Get appropriate transition for the side of the clip
if (trim_mode == Timeline::kTrimIn) {
connected_transition = block->in_transition();
connected_transition = cb->in_transition();
} else {
connected_transition = block->out_transition();
connected_transition = cb->out_transition();
}
if (connected_transition) {
+3 -2
View File
@@ -70,15 +70,16 @@ void RazorTool::MouseRelease(TimelineViewMouseEvent *event)
Block* block_at_time = track->NearestBlockBefore(split_time);
// Ensure there's a valid block here
ClipBlock *clip_at_time;
if (block_at_time
&& block_at_time->out() != split_time
&& dynamic_cast<ClipBlock*>(block_at_time)
&& (clip_at_time = dynamic_cast<ClipBlock*>(block_at_time))
&& !blocks_to_split.contains(block_at_time)) {
blocks_to_split.append(block_at_time);
// Add links if no alt is held
if (!(event->GetModifiers() & Qt::AltModifier)) {
foreach (Block* link, block_at_time->block_links()) {
foreach (Block* link, clip_at_time->block_links()) {
if (!blocks_to_split.contains(link)) {
blocks_to_split.append(link);
}
+4 -1
View File
@@ -75,7 +75,10 @@ void SlipTool::FinishDrag(TimelineViewMouseEvent *event)
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
Block* b = Node::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
command->add_child(new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn()));
ClipBlock *cb = dynamic_cast<ClipBlock*>(b);
if (cb) {
command->add_child(new BlockSetMediaInCommand(cb, ghost->GetAdjustedMediaIn()));
}
}
Core::instance()->undo_stack()->pushIfHasChildren(command);
@@ -115,8 +115,9 @@ void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
ghost_->GetAdjustedIn()));
if (dual_transition_) {
transition->set_length_and_media_out(ghost_->GetAdjustedLength());
transition->set_media_in(-ghost_->GetAdjustedLength()/2);
rational half_len = ghost_->GetAdjustedLength()/2;
transition->set_in_offset(half_len);
transition->set_out_offset(half_len);
// Block mouse is hovering over
Block* active_block = Node::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
@@ -22,6 +22,7 @@
#define TIMELINEUNDOGENERAL_H
#include "config/config.h"
#include "node/block/clip/clip.h"
#include "node/block/gap/gap.h"
#include "node/output/track/track.h"
#include "node/output/track/tracklist.h"
@@ -81,7 +82,7 @@ private:
class BlockSetMediaInCommand : public UndoCommand {
public:
BlockSetMediaInCommand(Block* block, rational new_media_in) :
BlockSetMediaInCommand(ClipBlock* block, rational new_media_in) :
block_(block),
new_media_in_(new_media_in)
{
@@ -97,7 +98,7 @@ protected:
virtual void undo();
private:
Block* block_;
ClipBlock* block_;
rational old_media_in_;
rational new_media_in_;
@@ -65,7 +65,9 @@ public:
ghost->SetIn(block->in());
ghost->SetOut(block->out());
ghost->SetMediaIn(block->media_in());
if (dynamic_cast<ClipBlock*>(block)) {
ghost->SetMediaIn(static_cast<ClipBlock*>(block)->media_in());
}
ghost->SetTrack(block->track()->ToReference());
ghost->SetData(kAttachedBlock, Node::PtrToValue(block));