diff --git a/app/node/block/CMakeLists.txt b/app/node/block/CMakeLists.txt
index ac6857879..92c3b27ea 100644
--- a/app/node/block/CMakeLists.txt
+++ b/app/node/block/CMakeLists.txt
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+add_subdirectory(gap)
add_subdirectory(timeline)
set(OLIVE_SOURCES
diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp
index 813bb2056..f8c9a6f8f 100644
--- a/app/node/block/block.cpp
+++ b/app/node/block/block.cpp
@@ -48,24 +48,14 @@ QString Block::Category()
return tr("Block");
}
-rational Block::in()
+const rational &Block::in()
{
- rational in_point = 0;
-
- Block* block = previous();
-
- while (block != nullptr) {
- in_point += block->length();
-
- block = previous();
- }
-
- return in_point;
+ return in_point_;
}
-rational Block::out()
+const rational &Block::out()
{
- return in() + length();
+ return out_point_;
}
Block *Block::previous()
@@ -87,6 +77,36 @@ void Block::Process(const rational &time)
next_output_->set_value(PtrToValue(this));
}
+void Block::Refresh()
+{
+ // Set in point to the out point of the previous Node
+ if (previous() != nullptr) {
+ in_point_ = previous()->out();
+ } else {
+ in_point_ = 0;
+ }
+
+ // Update out point by adding this clip's length to the just calculated in point
+ out_point_ = in_point_ + length();
+}
+
+void Block::RefreshSurrounds()
+{
+ Block* acting_node = previous();
+
+ while (acting_node != nullptr) {
+ acting_node->Refresh();
+ acting_node = acting_node->previous();
+ }
+
+ acting_node = next();
+
+ while (acting_node != nullptr) {
+ acting_node->Refresh();
+ acting_node = acting_node->next();
+ }
+}
+
NodeOutput *Block::texture_output()
{
return texture_output_;
diff --git a/app/node/block/block.h b/app/node/block/block.h
index af9961c80..a613332a8 100644
--- a/app/node/block/block.h
+++ b/app/node/block/block.h
@@ -23,6 +23,12 @@
#include "node/node.h"
+/**
+ * @brief A Node that represents a block of time, also displayable on a Timeline
+ *
+ * This is an abstract function. Since different types of Block will provide their lengths in different ways, it's
+ * necessary to subclass and override the length() function for a Block to be usable.
+ */
class Block : public Node
{
Q_OBJECT
@@ -31,10 +37,11 @@ public:
virtual QString Category() override;
- virtual rational in();
- virtual rational out();
+ const rational& in();
+ const rational& out();
virtual rational length() = 0;
+ virtual void set_length(const rational& length) = 0;
virtual Block* previous();
virtual Block* next();
@@ -44,6 +51,24 @@ public:
public slots:
virtual void Process(const rational &time) override;
+ /**
+ * @brief Refreshes internal cache of in/out points up to date
+ *
+ * A block can only know truly know its in point by adding all the lengths of the clips before it. Since this can
+ * become timeconsuming, blocks cache their in and out points for easy access, however this does mean their caches
+ * need to stay up to date to provide accurate results. Whenever this or any surrounding Block is changed, it's
+ * recommended to call Refresh().
+ *
+ * This function specifically sets the in point to the out point of the previous clip and sets its out point to the
+ * in point + this block's length. Therefore, before calling Refresh() on a Block, it's necessary that all the
+ * Blocks before it are accurate and up to date. You may need to traverse through the Block list (using previous())
+ * and run Refresh() on all Blocks sequentially.
+ */
+ void Refresh();
+
+protected:
+ void RefreshSurrounds();
+
private:
NodeInput* previous_input_;
NodeInput* next_input_;
@@ -51,6 +76,9 @@ private:
NodeOutput* next_output_;
NodeOutput* texture_output_;
+
+ rational in_point_;
+ rational out_point_;
};
#endif // BLOCK_H
diff --git a/app/node/block/gap/CMakeLists.txt b/app/node/block/gap/CMakeLists.txt
new file mode 100644
index 000000000..f66cee93c
--- /dev/null
+++ b/app/node/block/gap/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 Olive Team
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ node/block/gap/gap.h
+ node/block/gap/gap.cpp
+ PARENT_SCOPE
+)
diff --git a/app/node/block/gap/gap.cpp b/app/node/block/gap/gap.cpp
new file mode 100644
index 000000000..3c9a61582
--- /dev/null
+++ b/app/node/block/gap/gap.cpp
@@ -0,0 +1,17 @@
+#include "gap.h"
+
+GapBlock::GapBlock()
+{
+}
+
+rational GapBlock::length()
+{
+ return length_;
+}
+
+void GapBlock::set_length(const rational &length)
+{
+ length_ = length;
+
+ RefreshSurrounds();
+}
diff --git a/app/node/block/gap/gap.h b/app/node/block/gap/gap.h
new file mode 100644
index 000000000..62f7d7f2e
--- /dev/null
+++ b/app/node/block/gap/gap.h
@@ -0,0 +1,41 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 Olive Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+***/
+
+#ifndef TIMELINEBLOCK_H
+#define TIMELINEBLOCK_H
+
+#include "node/block/block.h"
+
+/**
+ * @brief Node that represents the end of the Timeline as well as a time traversal Node
+ */
+class GapBlock : public Block
+{
+public:
+ GapBlock();
+
+ virtual rational length() override;
+ virtual void set_length(const rational &length) override;
+
+private:
+ rational length_;
+};
+
+#endif // TIMELINEBLOCK_H
diff --git a/app/node/block/timeline/timeline.cpp b/app/node/block/timeline/timeline.cpp
index 8ca50e2fd..76cbbc6f8 100644
--- a/app/node/block/timeline/timeline.cpp
+++ b/app/node/block/timeline/timeline.cpp
@@ -5,6 +5,11 @@ TimelineBlock::TimelineBlock() :
{
}
+rational TimelineBlock::length()
+{
+ return 0;
+}
+
void TimelineBlock::Process(const rational &time)
{
// Run default process function
@@ -28,10 +33,10 @@ void TimelineBlock::Process(const rational &time)
}
// If the time requested is in a later Block, traverse later
- while (time > current_block_->out()) {
+ while (time >= current_block_->out()) {
current_block_ = current_block_->next();
}
// At this point, we must have found the correct block so we use its texture output to produce the image
- current_block_->texture_output()->get_value(time);
+ texture_output_->set_value(current_block_->texture_output()->get_value(time));
}
diff --git a/app/node/block/timeline/timeline.h b/app/node/block/timeline/timeline.h
index db45718a7..316737830 100644
--- a/app/node/block/timeline/timeline.h
+++ b/app/node/block/timeline/timeline.h
@@ -31,12 +31,12 @@ class TimelineBlock : public Block
public:
TimelineBlock();
+ virtual rational length() override;
+
public slots:
virtual void Process(const rational &time) override;
private:
- NodeOutput* texture_output_;
-
Block* current_block_;
};