began some rewrites to timeline drawing
This commit is contained in:
@@ -29,7 +29,10 @@ namespace olive {
|
||||
|
||||
Block::Block() :
|
||||
previous_(nullptr),
|
||||
next_(nullptr)
|
||||
next_(nullptr),
|
||||
track_(nullptr),
|
||||
in_transition_(nullptr),
|
||||
out_transition_(nullptr)
|
||||
{
|
||||
length_input_ = new NodeInput(this, QStringLiteral("length_in"), NodeValue::kRational);
|
||||
length_input_->SetConnectable(false);
|
||||
@@ -59,26 +62,6 @@ QVector<Node::CategoryID> Block::Category() const
|
||||
return {kCategoryTimeline};
|
||||
}
|
||||
|
||||
const rational &Block::in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
|
||||
const rational &Block::out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
|
||||
void Block::set_in(const rational &in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
|
||||
void Block::set_out(const rational &out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
|
||||
rational Block::length() const
|
||||
{
|
||||
return length_input_->GetStandardValue().value<rational>();
|
||||
@@ -110,31 +93,6 @@ void Block::set_length_and_media_in(const rational &length)
|
||||
set_length_internal(length);
|
||||
}
|
||||
|
||||
TimeRange Block::range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
|
||||
Block *Block::previous()
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
|
||||
Block *Block::next()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
void Block::set_previous(Block *previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
|
||||
void Block::set_next(Block *next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
rational Block::media_in() const
|
||||
{
|
||||
return media_in_input_->GetStandardValue().value<rational>();
|
||||
@@ -309,16 +267,6 @@ bool Block::AreLinked(Block *a, Block *b)
|
||||
return a->linked_clips_.contains(b);
|
||||
}
|
||||
|
||||
const QVector<Block*> &Block::linked_clips()
|
||||
{
|
||||
return linked_clips_;
|
||||
}
|
||||
|
||||
bool Block::HasLinks()
|
||||
{
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
void Block::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
@@ -329,21 +277,6 @@ void Block::Retranslate()
|
||||
speed_input_->set_name(tr("Speed"));
|
||||
}
|
||||
|
||||
NodeInput *Block::length_input() const
|
||||
{
|
||||
return length_input_;
|
||||
}
|
||||
|
||||
NodeInput *Block::media_in_input() const
|
||||
{
|
||||
return media_in_input_;
|
||||
}
|
||||
|
||||
NodeInput *Block::speed_input() const
|
||||
{
|
||||
return speed_input_;
|
||||
}
|
||||
|
||||
void Block::Hash(QCryptographicHash &, const rational &) const
|
||||
{
|
||||
// A block does nothing by default, so we hash nothing
|
||||
|
||||
+102
-14
@@ -26,6 +26,8 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TransitionBlock;
|
||||
|
||||
/**
|
||||
* @brief A Node that represents a block of time, also displayable on a Timeline
|
||||
*/
|
||||
@@ -45,25 +47,68 @@ public:
|
||||
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
|
||||
const rational& in() const;
|
||||
const rational& out() const;
|
||||
void set_in(const rational& in);
|
||||
void set_out(const rational& out);
|
||||
const rational& in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
|
||||
const rational& out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
|
||||
void set_in(const rational& in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
|
||||
void set_out(const rational& out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
|
||||
rational length() const;
|
||||
void set_length_and_media_out(const rational &length);
|
||||
void set_length_and_media_in(const rational &length);
|
||||
|
||||
TimeRange range() const;
|
||||
TimeRange range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
|
||||
Block* previous();
|
||||
Block* next();
|
||||
void set_previous(Block* previous);
|
||||
void set_next(Block* next);
|
||||
Block* previous() const
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
|
||||
Block* next() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
void set_previous(Block* previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
|
||||
void set_next(Block* next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
rational media_in() const;
|
||||
void set_media_in(const rational& media_in);
|
||||
|
||||
Track* track() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void set_track(Track* track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
|
||||
@@ -72,14 +117,53 @@ public:
|
||||
static bool Unlink(Block* a, Block* b);
|
||||
static void Unlink(const QList<Block*>& blocks);
|
||||
static bool AreLinked(Block* a, Block* b);
|
||||
const QVector<Block*>& linked_clips();
|
||||
bool HasLinks();
|
||||
|
||||
const QVector<Block*>& linked_clips() const
|
||||
{
|
||||
return linked_clips_;
|
||||
}
|
||||
|
||||
bool HasLinks() const
|
||||
{
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeInput* length_input() const;
|
||||
NodeInput* media_in_input() const;
|
||||
NodeInput* speed_input() const;
|
||||
NodeInput* length_input() const
|
||||
{
|
||||
return length_input_;
|
||||
}
|
||||
|
||||
NodeInput* media_in_input() const
|
||||
{
|
||||
return media_in_input_;
|
||||
}
|
||||
|
||||
NodeInput* speed_input() const
|
||||
{
|
||||
return speed_input_;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
virtual void Hash(QCryptographicHash &hash, const rational &time) const override;
|
||||
|
||||
@@ -116,6 +200,10 @@ private:
|
||||
|
||||
rational in_point_;
|
||||
rational out_point_;
|
||||
Track* track_;
|
||||
|
||||
TransitionBlock* in_transition_;
|
||||
TransitionBlock* out_transition_;
|
||||
|
||||
QVector<Block*> linked_clips_;
|
||||
|
||||
|
||||
@@ -172,23 +172,43 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t
|
||||
void TransitionBlock::OutBlockConnected(Node *node)
|
||||
{
|
||||
// If node is not a block, this will just be null
|
||||
connected_out_block_ = dynamic_cast<Block*>(node);
|
||||
if ((connected_out_block_ = dynamic_cast<Block*>(node))) {
|
||||
|
||||
Q_ASSERT(connected_out_block_->type() != Block::kTransition
|
||||
&& !connected_out_block_->out_transition()
|
||||
&& connected_out_block_ == this->previous());
|
||||
|
||||
connected_out_block_->set_out_transition(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::OutBlockDisconnected()
|
||||
{
|
||||
connected_out_block_ = nullptr;
|
||||
if (connected_out_block_) {
|
||||
connected_out_block_->set_in_transition(nullptr);
|
||||
connected_out_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InBlockConnected(Node *node)
|
||||
{
|
||||
// If node is not a block, this will just be null
|
||||
connected_in_block_ = dynamic_cast<Block*>(node);
|
||||
if ((connected_in_block_ = dynamic_cast<Block*>(node))) {
|
||||
|
||||
Q_ASSERT(connected_in_block_->type() != Block::kTransition
|
||||
&& !connected_in_block_->in_transition()
|
||||
&& connected_in_block_ == this->next());
|
||||
|
||||
connected_in_block_->set_in_transition(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InBlockDisconnected()
|
||||
{
|
||||
connected_in_block_ = nullptr;
|
||||
if (connected_in_block_) {
|
||||
connected_in_block_->set_in_transition(nullptr);
|
||||
connected_in_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
@@ -251,33 +271,6 @@ NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
return table;
|
||||
}
|
||||
|
||||
TransitionBlock *GetBlockTransitionInternal(Block *block, Timeline::MovementMode mode)
|
||||
{
|
||||
// See if this block outputs to a transition
|
||||
foreach (const NodeConnectable::InputConnection& conn, block->edges()) {
|
||||
TransitionBlock* transition = dynamic_cast<TransitionBlock*>(conn.input->parent());
|
||||
|
||||
if (transition) {
|
||||
if ((mode == Timeline::kTrimIn && conn.input == transition->in_block_input())
|
||||
|| (mode == Timeline::kTrimOut && conn.input == transition->out_block_input())) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TransitionBlock *TransitionBlock::GetBlockInTransition(Block *block)
|
||||
{
|
||||
return GetBlockTransitionInternal(block, Timeline::kTrimIn);
|
||||
}
|
||||
|
||||
TransitionBlock *TransitionBlock::GetBlockOutTransition(Block *block)
|
||||
{
|
||||
return GetBlockTransitionInternal(block, Timeline::kTrimOut);
|
||||
}
|
||||
|
||||
void TransitionBlock::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
|
||||
@@ -52,10 +52,6 @@ public:
|
||||
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
static TransitionBlock* GetBlockInTransition(Block* block);
|
||||
|
||||
static TransitionBlock* GetBlockOutTransition(Block* block);
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const;
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ Track::~Track()
|
||||
DisconnectAll();
|
||||
}
|
||||
|
||||
void Track::set_track_type(const Type &track_type)
|
||||
void Track::set_type(const Type &track_type)
|
||||
{
|
||||
track_type_ = track_type;
|
||||
}
|
||||
|
||||
const Track::Type& Track::track_type() const
|
||||
const Track::Type& Track::type() const
|
||||
{
|
||||
return track_type_;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ TimeRange Track::InputTimeAdjustment(NodeInput *input, int element, const TimeRa
|
||||
{
|
||||
if (input == block_input_ && element >= 0) {
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
const rational& block_in = blocks_.at(cache_index).range.in();
|
||||
const rational& block_in = blocks_.at(cache_index)->in();
|
||||
|
||||
return input_time - block_in;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ TimeRange Track::OutputTimeAdjustment(NodeInput *input, int element, const TimeR
|
||||
{
|
||||
if (input == block_input_ && element >= 0) {
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
const rational& block_in = blocks_.at(cache_index).range.in();
|
||||
const rational& block_in = blocks_.at(cache_index)->in();
|
||||
|
||||
return input_time + block_in;
|
||||
}
|
||||
@@ -155,11 +155,6 @@ void Track::Retranslate()
|
||||
muted_input_->set_name(tr("Muted"));
|
||||
}
|
||||
|
||||
const int &Track::Index()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
void Track::SetIndex(const int &index)
|
||||
{
|
||||
index_ = index;
|
||||
@@ -169,7 +164,7 @@ void Track::SetIndex(const int &index)
|
||||
|
||||
Block *Track::BlockContainingTime(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block->in() < time && block->out() > time) {
|
||||
return block;
|
||||
} else if (block->out() == time) {
|
||||
@@ -182,7 +177,7 @@ Block *Track::BlockContainingTime(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockBefore(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block who's out point is at/after this time is the correct Block
|
||||
if (block->out() >= time) {
|
||||
return block;
|
||||
@@ -194,7 +189,7 @@ Block *Track::NearestBlockBefore(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockBeforeOrAt(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block who's out point is at/after this time is the correct Block
|
||||
if (block->out() > time) {
|
||||
return block;
|
||||
@@ -206,7 +201,7 @@ Block *Track::NearestBlockBeforeOrAt(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockAfterOrAt(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block after this time is the correct Block
|
||||
if (block->in() >= time) {
|
||||
return block;
|
||||
@@ -218,7 +213,7 @@ Block *Track::NearestBlockAfterOrAt(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockAfter(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block after this time is the correct Block
|
||||
if (block->in() > time) {
|
||||
return block;
|
||||
@@ -234,7 +229,7 @@ Block *Track::BlockAtTime(const rational &time) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block
|
||||
&& block->in() <= time
|
||||
&& block->out() > time) {
|
||||
@@ -257,7 +252,7 @@ QVector<Block *> Track::BlocksAtTimeRange(const TimeRange &range) const
|
||||
return list;
|
||||
}
|
||||
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block
|
||||
&& block->is_enabled()
|
||||
&& block->out() > range.in()
|
||||
@@ -293,16 +288,16 @@ void Track::InvalidateCache(const TimeRange& range, const InputConnection& from)
|
||||
|
||||
void Track::InsertBlockBefore(Block* block, Block* after)
|
||||
{
|
||||
InsertBlockAtIndex(block, block_cache_.indexOf(after));
|
||||
InsertBlockAtIndex(block, blocks_.indexOf(after));
|
||||
}
|
||||
|
||||
void Track::InsertBlockAfter(Block *block, Block *before)
|
||||
{
|
||||
int before_index = block_cache_.indexOf(before);
|
||||
int before_index = blocks_.indexOf(before);
|
||||
|
||||
Q_ASSERT(before_index >= 0);
|
||||
|
||||
if (before_index == block_cache_.size() - 1) {
|
||||
if (before_index == blocks_.size() - 1) {
|
||||
AppendBlock(block);
|
||||
} else {
|
||||
InsertBlockAtIndex(block, before_index + 1);
|
||||
@@ -326,7 +321,7 @@ void Track::InsertBlockAtIndex(Block *block, int index)
|
||||
{
|
||||
BeginOperation();
|
||||
|
||||
int insert_index = GetInputIndexFromCacheIndex(index);
|
||||
int insert_index = GetArrayIndexFromCacheIndex(index);
|
||||
block_input_->ArrayInsert(insert_index);
|
||||
Node::ConnectEdge(block, block_input_, insert_index);
|
||||
|
||||
@@ -355,7 +350,7 @@ void Track::RippleRemoveBlock(Block *block)
|
||||
rational remove_in = block->in();
|
||||
rational remove_out = block->out();
|
||||
|
||||
block_input_->ArrayRemove(GetInputIndexFromCacheIndex(block));
|
||||
block_input_->ArrayRemove(GetArrayIndexFromBlock(block));
|
||||
|
||||
EndOperation();
|
||||
|
||||
@@ -366,7 +361,7 @@ void Track::ReplaceBlock(Block *old, Block *replace)
|
||||
{
|
||||
BeginOperation();
|
||||
|
||||
int index_of_old_block = GetInputIndexFromCacheIndex(old);
|
||||
int index_of_old_block = GetArrayIndexFromBlock(old);
|
||||
|
||||
DisconnectEdge(old, block_input_, index_of_old_block);
|
||||
|
||||
@@ -442,11 +437,11 @@ void Track::SetLocked(bool e)
|
||||
void Track::UpdateInOutFrom(int index)
|
||||
{
|
||||
// Find block just before this one to find the last out point
|
||||
rational last_out = (index == 0) ? 0 : block_cache_.at(index - 1)->out();
|
||||
rational last_out = (index == 0) ? 0 : blocks_.at(index - 1)->out();
|
||||
|
||||
// Iterate through all blocks updating their in/outs
|
||||
for (int i=index; i<block_cache_.size(); i++) {
|
||||
Block* b = block_cache_.at(i);
|
||||
for (int i=index; i<blocks_.size(); i++) {
|
||||
Block* b = blocks_.at(i);
|
||||
|
||||
b->set_in(last_out);
|
||||
|
||||
@@ -455,24 +450,25 @@ void Track::UpdateInOutFrom(int index)
|
||||
b->set_out(last_out);
|
||||
}
|
||||
|
||||
emit BlocksRefreshed();
|
||||
|
||||
// Update track length
|
||||
SetLengthInternal(last_out);
|
||||
}
|
||||
|
||||
int Track::GetArrayIndexFromBlock(Block *block) const
|
||||
{
|
||||
return block_array_indexes_.at(blocks_.indexOf(block));
|
||||
}
|
||||
|
||||
int Track::GetArrayIndexFromCacheIndex(int index) const
|
||||
{
|
||||
return blocks_.at(index).array_index;
|
||||
return block_array_indexes_.at(index);
|
||||
}
|
||||
|
||||
int Track::GetCacheIndexFromArrayIndex(int index) const
|
||||
{
|
||||
for (int i=0; i<blocks_.size(); i++) {
|
||||
if (blocks_.at(i).array_index == index) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return block_array_indexes_.indexOf(index);
|
||||
}
|
||||
|
||||
void Track::SetLengthInternal(const rational &r, bool invalidate)
|
||||
@@ -504,36 +500,36 @@ void Track::BlockConnected(Node *node, int element)
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine where in the cache this block will be
|
||||
int cache_index = -1;
|
||||
Block *previous = nullptr, *next = nullptr;
|
||||
|
||||
for (int i=element-1; i>=0; i--) {
|
||||
// Find previous block
|
||||
previous = dynamic_cast<Block*>(block_input_->GetConnectedNode(i));
|
||||
for (int i=element+1; i<block_input_->ArraySize(); i++) {
|
||||
// Find next block because this will be the index that we want to insert at
|
||||
cache_index = GetCacheIndexFromArrayIndex(i);
|
||||
|
||||
if (previous) {
|
||||
if (cache_index >= 0) {
|
||||
next = blocks_.at(cache_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find cache index
|
||||
int cache_index;
|
||||
if (previous) {
|
||||
// Insert block just after the previous block we found
|
||||
cache_index = block_cache_.indexOf(previous) + 1;
|
||||
// If there was no next, this will be inserted at the end
|
||||
if (cache_index == -1) {
|
||||
cache_index = blocks_.size();
|
||||
}
|
||||
|
||||
// Use current previous' next as our next
|
||||
next = previous->next();
|
||||
} else {
|
||||
// Didn't find a previous, so insert block at 0 (prepend it)
|
||||
cache_index = 0;
|
||||
|
||||
if (!block_cache_.isEmpty()) {
|
||||
next = block_cache_.first();
|
||||
}
|
||||
// Determine previous block, either by using next's previous or the last block if there was no
|
||||
// next. If there are neither, they'll both remain null
|
||||
if (next) {
|
||||
previous = next->previous();
|
||||
} else if (!blocks_.isEmpty()) {
|
||||
previous = blocks_.last();
|
||||
}
|
||||
|
||||
// Insert at index
|
||||
block_cache_.insert(cache_index, block);
|
||||
blocks_.insert(cache_index, block);
|
||||
block_array_indexes_.insert(cache_index, element);
|
||||
|
||||
// Update previous/next
|
||||
if (previous) {
|
||||
@@ -546,6 +542,8 @@ void Track::BlockConnected(Node *node, int element)
|
||||
next->set_previous(block);
|
||||
}
|
||||
|
||||
block->set_track(this);
|
||||
|
||||
// Update ins/outs
|
||||
UpdateInOutFrom(cache_index);
|
||||
|
||||
@@ -575,10 +573,16 @@ void Track::BlockDisconnected(Node* node, int element)
|
||||
|
||||
TimeRange invalidate_range(b->in(), track_length());
|
||||
|
||||
// FIXME: What happens if a user connects the same block twice? This must be addressed in the
|
||||
// upcoming timeline rewrite.
|
||||
block_cache_.removeOne(b);
|
||||
// Get cache index
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
|
||||
// Remove block here
|
||||
blocks_.removeAt(cache_index);
|
||||
block_array_indexes_.removeAt(cache_index);
|
||||
|
||||
emit BlockRemoved(b);
|
||||
|
||||
// Update previous/nexts
|
||||
Block* previous = b->previous();
|
||||
Block* next = b->next();
|
||||
|
||||
@@ -592,19 +596,19 @@ void Track::BlockDisconnected(Node* node, int element)
|
||||
|
||||
b->set_previous(nullptr);
|
||||
b->set_next(nullptr);
|
||||
b->set_track(nullptr);
|
||||
|
||||
// Update lengths
|
||||
if (next) {
|
||||
UpdateInOutFrom(block_cache_.indexOf(next));
|
||||
} else if (block_cache_.isEmpty()) {
|
||||
UpdateInOutFrom(blocks_.indexOf(next));
|
||||
} else if (blocks_.isEmpty()) {
|
||||
SetLengthInternal(rational());
|
||||
} else {
|
||||
SetLengthInternal(block_cache_.last()->out());
|
||||
SetLengthInternal(blocks_.last()->out());
|
||||
}
|
||||
|
||||
disconnect(b, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
||||
|
||||
emit BlockRemoved(b);
|
||||
|
||||
Node::InvalidateCache(invalidate_range);
|
||||
}
|
||||
|
||||
@@ -615,7 +619,7 @@ void Track::BlockLengthChanged()
|
||||
|
||||
rational old_out = b->out();
|
||||
|
||||
UpdateInOutFrom(block_cache_.indexOf(b));
|
||||
UpdateInOutFrom(blocks_.indexOf(b));
|
||||
|
||||
rational new_out = b->out();
|
||||
|
||||
@@ -629,4 +633,12 @@ void Track::MutedInputValueChanged()
|
||||
emit MutedChanged(IsMuted());
|
||||
}
|
||||
|
||||
uint qHash(const Track::Reference &r, uint seed)
|
||||
{
|
||||
// Not super efficient, but couldn't think of any better way to ensure a different hash each time
|
||||
return ::qHash(QStringLiteral("%1:%2").arg(QString::number(r.type()),
|
||||
QString::number(r.index())),
|
||||
seed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ public:
|
||||
|
||||
virtual ~Track() override;
|
||||
|
||||
const Track::Type& track_type() const;
|
||||
void set_track_type(const Track::Type& track_type);
|
||||
const Track::Type& type() const;
|
||||
void set_type(const Track::Type& track_type);
|
||||
|
||||
virtual Node* copy() const override;
|
||||
|
||||
@@ -95,7 +95,58 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
const int& Index();
|
||||
class Reference
|
||||
{
|
||||
public:
|
||||
Reference() :
|
||||
type_(kNone),
|
||||
index_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
Reference(const Track::Type& type, const int& index) :
|
||||
type_(type),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
const Track::Type& type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const int& index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
bool operator==(const Reference& ref) const
|
||||
{
|
||||
return type_ == ref.type_ && index_ == ref.index_;
|
||||
}
|
||||
|
||||
bool operator!=(const Reference& ref) const
|
||||
{
|
||||
return !(*this == ref);
|
||||
}
|
||||
|
||||
private:
|
||||
Track::Type type_;
|
||||
|
||||
int index_;
|
||||
|
||||
};
|
||||
|
||||
Reference ToReference() const
|
||||
{
|
||||
return Reference(type(), Index());
|
||||
}
|
||||
|
||||
const int& Index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
void SetIndex(const int& index);
|
||||
|
||||
/**
|
||||
@@ -164,7 +215,7 @@ public:
|
||||
|
||||
const QVector<Block *> &Blocks() const
|
||||
{
|
||||
return block_cache_;
|
||||
return blocks_;
|
||||
}
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const InputConnection& from) override;
|
||||
@@ -273,6 +324,11 @@ signals:
|
||||
*/
|
||||
void PreviewChanged();
|
||||
|
||||
/**
|
||||
* @brief Emitted when a block changes length and all the subsequent blocks had to update
|
||||
*/
|
||||
void BlocksRefreshed();
|
||||
|
||||
protected:
|
||||
virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData& xml_node_data) override;
|
||||
|
||||
@@ -281,13 +337,16 @@ protected:
|
||||
private:
|
||||
void UpdateInOutFrom(int index);
|
||||
|
||||
int GetArrayIndexFromBlock(Block* block) const;
|
||||
|
||||
int GetArrayIndexFromCacheIndex(int index) const;
|
||||
|
||||
int GetCacheIndexFromArrayIndex(int index) const;
|
||||
|
||||
void SetLengthInternal(const rational& r, bool invalidate = true);
|
||||
|
||||
QVector<Block*> block_cache_;
|
||||
QVector<Block*> blocks_;
|
||||
QVector<int> block_array_indexes_;
|
||||
|
||||
NodeInput* block_input_;
|
||||
|
||||
@@ -316,6 +375,8 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
uint qHash(const Track::Reference& r, uint seed = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif // TRACK_H
|
||||
|
||||
@@ -36,26 +36,6 @@ TrackList::TrackList(ViewerOutput *parent, const Track::Type &type, NodeInput *t
|
||||
connect(track_input_, &NodeInput::InputDisconnected, this, &TrackList::TrackDisconnected);
|
||||
}
|
||||
|
||||
const Track::Type &TrackList::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
void TrackList::TrackAddedBlock(Block *block)
|
||||
{
|
||||
emit BlockAdded(block, static_cast<Track*>(sender())->Index());
|
||||
}
|
||||
|
||||
void TrackList::TrackRemovedBlock(Block *block)
|
||||
{
|
||||
emit BlockRemoved(block);
|
||||
}
|
||||
|
||||
const QVector<Track *> &TrackList::GetTracks() const
|
||||
{
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track *TrackList::GetTrackAt(int index) const
|
||||
{
|
||||
if (index < track_cache_.size()) {
|
||||
@@ -65,16 +45,6 @@ Track *TrackList::GetTrackAt(int index) const
|
||||
}
|
||||
}
|
||||
|
||||
const rational &TrackList::GetTotalLength() const
|
||||
{
|
||||
return total_length_;
|
||||
}
|
||||
|
||||
int TrackList::GetTrackCount() const
|
||||
{
|
||||
return track_cache_.size();
|
||||
}
|
||||
|
||||
void TrackList::TrackConnected(Node *node, int element)
|
||||
{
|
||||
if (element == -1) {
|
||||
@@ -114,12 +84,9 @@ void TrackList::TrackConnected(Node *node, int element)
|
||||
// Update track indexes in the list (including this track)
|
||||
UpdateTrackIndexesFrom(track_index);
|
||||
|
||||
connect(track, &Track::BlockAdded, this, &TrackList::TrackAddedBlock);
|
||||
connect(track, &Track::BlockRemoved, this, &TrackList::TrackRemovedBlock);
|
||||
connect(track, &Track::TrackLengthChanged, this, &TrackList::UpdateTotalLength);
|
||||
connect(track, &Track::TrackHeightChangedInPixels, this, &TrackList::TrackHeightChangedSlot);
|
||||
|
||||
track->set_track_type(type_);
|
||||
track->set_type(type_);
|
||||
|
||||
emit TrackListChanged();
|
||||
|
||||
@@ -150,12 +117,9 @@ void TrackList::TrackDisconnected(Node *node, int element)
|
||||
emit TrackRemoved(track);
|
||||
|
||||
track->SetIndex(-1);
|
||||
track->set_track_type(Track::kNone);
|
||||
track->set_type(Track::kNone);
|
||||
|
||||
disconnect(track, &Track::BlockAdded, this, &TrackList::TrackAddedBlock);
|
||||
disconnect(track, &Track::BlockRemoved, this, &TrackList::TrackRemovedBlock);
|
||||
disconnect(track, &Track::TrackLengthChanged, this, &TrackList::UpdateTotalLength);
|
||||
disconnect(track, &Track::TrackHeightChangedInPixels, this, &TrackList::TrackHeightChangedSlot);
|
||||
|
||||
emit TrackListChanged();
|
||||
|
||||
@@ -187,9 +151,4 @@ void TrackList::UpdateTotalLength()
|
||||
emit LengthChanged(total_length_);
|
||||
}
|
||||
|
||||
void TrackList::TrackHeightChangedSlot(int height)
|
||||
{
|
||||
emit TrackHeightChanged(static_cast<Track*>(sender())->Index(), height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,15 +37,27 @@ class TrackList : public QObject
|
||||
public:
|
||||
TrackList(ViewerOutput *parent, const Track::Type& type, NodeInput* track_input);
|
||||
|
||||
const Track::Type& type() const;
|
||||
const Track::Type& type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const QVector<Track*>& GetTracks() const;
|
||||
const QVector<Track*>& GetTracks() const
|
||||
{
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track* GetTrackAt(int index) const;
|
||||
|
||||
const rational& GetTotalLength() const;
|
||||
const rational& GetTotalLength() const
|
||||
{
|
||||
return total_length_;
|
||||
}
|
||||
|
||||
int GetTrackCount() const;
|
||||
int GetTrackCount() const
|
||||
{
|
||||
return track_cache_.size();
|
||||
}
|
||||
|
||||
NodeGraph* GetParentGraph() const;
|
||||
|
||||
@@ -55,19 +67,13 @@ public:
|
||||
}
|
||||
|
||||
signals:
|
||||
void BlockAdded(Block* block, int index);
|
||||
|
||||
void BlockRemoved(Block* block);
|
||||
|
||||
void TrackAdded(Track* track);
|
||||
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
void TrackListChanged();
|
||||
|
||||
void LengthChanged(const rational &length);
|
||||
|
||||
void TrackHeightChanged(int index, int height);
|
||||
void TrackAdded(Track* track);
|
||||
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
private:
|
||||
void UpdateTrackIndexesFrom(int index);
|
||||
@@ -94,26 +100,11 @@ private slots:
|
||||
*/
|
||||
void TrackDisconnected(Node* node, int element);
|
||||
|
||||
/**
|
||||
* @brief Slot for when a connected Track has added a Block so we can update the UI
|
||||
*/
|
||||
void TrackAddedBlock(Block* block);
|
||||
|
||||
/**
|
||||
* @brief Slot for when a connected Track has added a Block so we can update the UI
|
||||
*/
|
||||
void TrackRemovedBlock(Block* block);
|
||||
|
||||
/**
|
||||
* @brief Slot for when any of the track's length changes so we can update the length of the tracklist
|
||||
*/
|
||||
void UpdateTotalLength();
|
||||
|
||||
/**
|
||||
* @brief Slot when a track height changes, transforms to the TrackHeightChanged signal which includes a track index
|
||||
*/
|
||||
void TrackHeightChangedSlot(int height);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,11 +47,8 @@ ViewerOutput::ViewerOutput() :
|
||||
track_lists_.replace(i, list);
|
||||
connect(list, &TrackList::TrackListChanged, this, &ViewerOutput::UpdateTrackCache);
|
||||
connect(list, &TrackList::LengthChanged, this, &ViewerOutput::VerifyLength);
|
||||
connect(list, &TrackList::BlockAdded, this, &ViewerOutput::TrackListAddedBlock);
|
||||
connect(list, &TrackList::BlockRemoved, this, &ViewerOutput::BlockRemoved);
|
||||
connect(list, &TrackList::TrackAdded, this, &ViewerOutput::TrackListAddedTrack);
|
||||
connect(list, &TrackList::TrackAdded, this, &ViewerOutput::TrackAdded);
|
||||
connect(list, &TrackList::TrackRemoved, this, &ViewerOutput::TrackRemoved);
|
||||
connect(list, &TrackList::TrackHeightChanged, this, &ViewerOutput::TrackHeightChangedSlot);
|
||||
}
|
||||
|
||||
// Create UUID for this node
|
||||
@@ -291,21 +288,4 @@ void ViewerOutput::EndOperation()
|
||||
Node::EndOperation();
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackListAddedBlock(Block *block, int index)
|
||||
{
|
||||
Track::Type type = static_cast<TrackList*>(sender())->type();
|
||||
emit BlockAdded(block, TrackReference(type, index));
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackListAddedTrack(Track *track)
|
||||
{
|
||||
Track::Type type = static_cast<TrackList*>(sender())->type();
|
||||
emit TrackAdded(track, type);
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackHeightChangedSlot(int index, int height)
|
||||
{
|
||||
emit TrackHeightChanged(static_cast<TrackList*>(sender())->type(), index, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timeline/trackreference.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -97,7 +96,7 @@ public:
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track* GetTrackFromReference(const TrackReference& track_ref) const
|
||||
Track* GetTrackFromReference(const Track::Reference& track_ref) const
|
||||
{
|
||||
return track_lists_.at(track_ref.type())->GetTrackAt(track_ref.index());
|
||||
}
|
||||
@@ -147,14 +146,9 @@ signals:
|
||||
void VideoParamsChanged();
|
||||
void AudioParamsChanged();
|
||||
|
||||
void BlockAdded(Block* block, TrackReference track);
|
||||
void BlockRemoved(Block* block);
|
||||
|
||||
void TrackAdded(Track* track, Track::Type type);
|
||||
void TrackAdded(Track* track);
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
void TrackHeightChanged(Track::Type type, int index, int height);
|
||||
|
||||
private:
|
||||
QUuid uuid_;
|
||||
|
||||
@@ -185,12 +179,6 @@ private slots:
|
||||
|
||||
void VerifyLength();
|
||||
|
||||
void TrackListAddedBlock(Block* block, int index);
|
||||
|
||||
void TrackListAddedTrack(Track* track);
|
||||
|
||||
void TrackHeightChangedSlot(int index, int height);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -123,12 +123,12 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const rational &in, c
|
||||
NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeRange &range)
|
||||
{
|
||||
// By default, just follow the in point
|
||||
int active_block = track->BlockAtTime(range.in());
|
||||
Block* active_block = track->BlockAtTime(range.in());
|
||||
|
||||
NodeValueTable table;
|
||||
|
||||
if (active_block >= 0) {
|
||||
table = GenerateTable(track->Blocks().at(active_block).block, range);
|
||||
if (active_block) {
|
||||
table = GenerateTable(active_block, range);
|
||||
}
|
||||
|
||||
return table;
|
||||
|
||||
Reference in New Issue
Block a user