implemented new block system

Fixes recurring design issue that the Blocks were a frequent exception to the
DAG concept. The Blocks connecting to each others inputs/outputs while not
necessarily being "dependent" on each other to produce an image continually
causes issues while trying to create a rendering code path. This redesign
should provide a more "directed" approach to the directed acyclic graph.
This commit is contained in:
itsmattkc
2019-12-02 00:37:03 +11:00
parent 6314c80cbc
commit 79ee3bc3df
13 changed files with 279 additions and 240 deletions
+199 -145
View File
@@ -32,6 +32,9 @@ TrackOutput::TrackOutput() :
{
block_input_ = new NodeInputArray("block_in");
AddParameter(block_input_);
connect(block_input_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(BlockConnected(NodeEdgePtr)));
connect(block_input_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(BlockDisconnected(NodeEdgePtr)));
connect(block_input_, SIGNAL(SizeChanged(int)), this, SLOT(BlockListSizeChanged(int)));
track_input_ = new NodeInput("track_in");
track_input_->set_data_type(NodeParam::kTrack);
@@ -54,7 +57,7 @@ const TrackType& TrackOutput::track_type()
Block::Type TrackOutput::type()
{
return kEnd;
return kTrack;
}
Block *TrackOutput::copy()
@@ -83,33 +86,6 @@ QString TrackOutput::Description()
"a Sequence.");
}
void TrackOutput::Refresh()
{
QVector<Block*> detect_attached_blocks;
Block* prev = previous();
while (prev != nullptr) {
detect_attached_blocks.prepend(prev);
if (!block_cache_.contains(prev)) {
emit BlockAdded(prev);
}
prev = prev->previous();
}
foreach (Block* b, block_cache_) {
if (!detect_attached_blocks.contains(b)) {
// If the current block was removed, stop referencing it
emit BlockRemoved(b);
}
}
block_cache_ = detect_attached_blocks;
Block::Refresh();
}
const int &TrackOutput::Index()
{
return index_;
@@ -192,87 +168,42 @@ QVariant TrackOutput::Value(NodeOutput *output)
if (output == track_output_) {
// Set track output correctly
return PtrToValue(this);
/*} else if (output == buffer_output()) {
ValidateCurrentBlock(in);
if (current_block_ != this) {
// At this point, we must have found the correct block so we use its texture output to produce the image
return current_block_->buffer_output()->get_value(in, out);
}
// No texture is valid
return 0;*/
}
// Run default node processing
return Block::Value(output);
}
void TrackOutput::InsertBlockBetweenBlocks(Block *block, Block *before, Block *after)
{
AddBlockToGraph(block);
Block::DisconnectBlocks(before, after);
Block::ConnectBlocks(before, block);
Block::ConnectBlocks(block, after);
}
void TrackOutput::InsertBlockBefore(Block* block, Block* after)
{
Block* before = after->previous();
// If a block precedes this one, just insert between them
if (before != nullptr) {
InsertBlockBetweenBlocks(block, before, after);
} else {
AddBlockToGraph(block);
// Otherwise, just connect the block since there's no before clip to insert between
Block::ConnectBlocks(block, after);
}
InsertBlockAtIndex(block, block_cache_.indexOf(after));
}
void TrackOutput::InsertBlockAfter(Block *block, Block *before)
{
InsertBlockBetweenBlocks(block, before, before->next());
int before_index = block_cache_.indexOf(before);
Q_ASSERT(before_index >= 0);
if (before_index == block_cache_.size() - 1) {
AppendBlock(block);
} else {
InsertBlockAtIndex(block, before_index + 1);
}
}
void TrackOutput::PrependBlock(Block *block)
{
AddBlockToGraph(block);
if (block_cache_.isEmpty()) {
ConnectBlockInternal(block);
} else {
Block::ConnectBlocks(block, block_cache_.first());
}
InsertBlockAtIndex(block, 0);
}
void TrackOutput::InsertBlockAtIndex(Block *block, int index)
{
AddBlockToGraph(block);
if (block_cache_.isEmpty()) {
// If there are no blocks connected, the index doesn't matter. Just connect it.
ConnectBlockInternal(block);
} else if (index == 0) {
// If the index is 0, it goes at the very beginning
PrependBlock(block);
} else if (index >= block_cache_.size()) {
// Append Block at the end
AppendBlock(block);
} else {
// Insert Block just before the Block currently at that index so that it becomes the new Block at that index
InsertBlockBetweenBlocks(block, block_cache_.at(index - 1), block_cache_.at(index));
}
block_input_->InsertAt(index);
NodeParam::ConnectEdge(block->block_output(),
block_input_->ParamAt(index));
}
void TrackOutput::AppendBlock(Block *block)
@@ -281,23 +212,15 @@ void TrackOutput::AppendBlock(Block *block)
BlockInvalidateCache();
if (block_cache_.isEmpty()) {
ConnectBlockInternal(block);
} else {
InsertBlockBetweenBlocks(block, block_cache_.last(), this);
}
int last_index = block_input_->GetSize();
block_input_->Append();
NodeParam::ConnectEdge(block->block_output(),
block_input_->ParamAt(last_index));
UnblockInvalidateCache();
// Invalidate area that block was added to
InvalidateCache(block->in(), in());
}
void TrackOutput::ConnectBlockInternal(Block *block)
{
AddBlockToGraph(block);
Block::ConnectBlocks(block, this);
InvalidateCache(block->in(), track_length());
}
void TrackOutput::AddBlockToGraph(Block *block)
@@ -322,18 +245,7 @@ void TrackOutput::RemoveBlock(Block *block)
GapBlock* gap = new GapBlock();
gap->set_length(block->length());
Block* previous = block->previous();
Block* next = block->next();
// Remove block
RippleRemoveBlock(block);
if (previous == nullptr) {
// Block must be at the beginning
PrependBlock(gap);
} else {
InsertBlockBetweenBlocks(gap, previous, next);
}
ReplaceBlock(block, gap);
}
void TrackOutput::RippleRemoveBlock(Block *block)
@@ -342,24 +254,13 @@ void TrackOutput::RippleRemoveBlock(Block *block)
rational remove_in = block->in();
Block* previous = block->previous();
Block* next = block->next();
int index_of_block_to_remove = block_cache_.indexOf(block);
if (previous != nullptr) {
Block::DisconnectBlocks(previous, block);
}
if (next != nullptr) {
Block::DisconnectBlocks(block, next);
}
if (previous != nullptr && next != nullptr) {
Block::ConnectBlocks(previous, next);
}
block_input_->RemoveAt(index_of_block_to_remove);
UnblockInvalidateCache();
InvalidateCache(remove_in, in());
InvalidateCache(remove_in, track_length());
// FIXME: Should there be removing the Blocks from the graph?
}
@@ -368,23 +269,17 @@ void TrackOutput::ReplaceBlock(Block *old, Block *replace)
{
Q_ASSERT(old->length() == replace->length());
Block* previous = old->previous();
Block* next = old->next();
BlockInvalidateCache();
AddBlockToGraph(replace);
// Disconnect old block from its surroundings
if (previous != nullptr) {
Block::DisconnectBlocks(previous, old);
Block::ConnectBlocks(previous, replace);
}
int index_of_old_block = block_cache_.indexOf(old);
if (next != nullptr) {
Block::DisconnectBlocks(old, next);
Block::ConnectBlocks(replace, next);
}
NodeParam::DisconnectEdge(old->block_output(),
block_input_->ParamAt(index_of_old_block));
NodeParam::ConnectEdge(replace->block_output(),
block_input_->ParamAt(index_of_old_block));
UnblockInvalidateCache();
@@ -393,14 +288,173 @@ void TrackOutput::ReplaceBlock(Block *old, Block *replace)
TrackOutput *TrackOutput::TrackFromBlock(Block *block)
{
Block* n = block;
NodeOutput* output = block->block_output();
// Find last valid block in Sequence and assume its a track
while (n->next() != nullptr) {
n = n->next();
foreach (NodeEdgePtr edge, output->edges()) {
TrackOutput* track_test = dynamic_cast<TrackOutput*>(edge->input()->parentNode());
if (track_test) {
return track_test;
}
}
// Downside of this approach is the usage of dynamic_cast, alternative would be looping through all known tracks and
// seeing if the contain the Block, but this seems slower
return dynamic_cast<TrackOutput*>(n);
return nullptr;
}
const rational &TrackOutput::track_length()
{
return track_length_;
}
bool TrackOutput::IsTrack()
{
return true;
}
void TrackOutput::UpdateInOutFrom(int index)
{
Q_ASSERT(index >= 0);
Q_ASSERT(index < block_cache_.size());
rational new_track_length;
for (int i=index;i<block_cache_.size();i++) {
Block* b = block_cache_.at(i);
if (b) {
rational prev_out;
// Find previous block and retrieve its out point (if there isn't one, this in will be set to 0)
for (int j=i-1;j>=0;j--) {
Block* previous = block_cache_.at(j);
if (previous) {
prev_out = previous->out();
break;
}
}
rational new_out = prev_out + b->length();
b->set_in(prev_out);
b->set_out(new_out);
new_track_length = new_out;
emit b->Refreshed();
}
}
// Update track length
if (new_track_length != track_length_) {
track_length_ = new_track_length;
emit TrackLengthChanged();
}
}
void TrackOutput::UpdatePreviousAndNextOfIndex(int index)
{
Block* ref = block_cache_.at(index);
Block* previous = nullptr;
Block* next = nullptr;
// Find previous
for (int i=index-1;i>=0;i--) {
previous = block_cache_.at(i);
if (previous) {
break;
}
}
// Find next
for (int i=index+1;i<block_cache_.size();i++) {
next = block_cache_.at(i);
if (next) {
break;
}
}
if (ref) {
// Link blocks together
ref->set_previous(previous);
ref->set_next(next);
if (previous)
previous->set_next(ref);
if (next)
next->set_previous(ref);
} else {
// Link previous and next together
if (previous)
previous->set_next(next);
if (next)
next->set_previous(previous);
}
}
void TrackOutput::BlockConnected(NodeEdgePtr edge)
{
int block_index = block_input_->IndexOfSubParameter(edge->input());
Q_ASSERT(block_index >= 0);
Block* connected_block = dynamic_cast<Block*>(edge->output()->parentNode());
block_cache_.replace(block_index, connected_block);
UpdatePreviousAndNextOfIndex(block_index);
UpdateInOutFrom(block_index);
if (connected_block) {
connect(connected_block, SIGNAL(LengthChanged(const rational&)), this, SLOT(BlockLengthChanged()));
emit BlockAdded(connected_block);
}
}
void TrackOutput::BlockDisconnected(NodeEdgePtr edge)
{
int block_index = block_input_->IndexOfSubParameter(edge->input());
Q_ASSERT(block_index >= 0);
block_cache_.replace(block_index, nullptr);
UpdatePreviousAndNextOfIndex(block_index);
UpdateInOutFrom(block_index);
Block* connected_block = dynamic_cast<Block*>(edge->output()->parentNode());
if (connected_block) {
disconnect(connected_block, SIGNAL(LengthChanged(const rational&)), this, SLOT(BlockLengthChanged()));
// Update previous and next references
emit BlockRemoved(connected_block);
}
}
void TrackOutput::BlockListSizeChanged(int size)
{
int old_size = block_cache_.size();
block_cache_.resize(size);
if (size > old_size) {
// Fill new slots with nullptr
for (int i=old_size;i<size;i++) {
block_cache_.replace(i, nullptr);
}
}
}
void TrackOutput::BlockLengthChanged()
{
// Assumes sender is a Block
Block* b = static_cast<Block*>(sender());
int index = block_cache_.indexOf(b);
Q_ASSERT(index >= 0);
UpdateInOutFrom(index);
}