moved block links to node links
Seems like it might be useful to have this as part of the node architecture as a whole
This commit is contained in:
@@ -50,7 +50,7 @@ struct XMLNodeData {
|
||||
};
|
||||
|
||||
struct BlockLink {
|
||||
Block* block;
|
||||
Node* block;
|
||||
quintptr link;
|
||||
};
|
||||
|
||||
|
||||
+13
-81
@@ -170,24 +170,6 @@ rational Block::MediaToSequenceTime(const rational &media_time) const
|
||||
return sequence_time;
|
||||
}
|
||||
|
||||
void Block::LoadInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data)
|
||||
{
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("link")) {
|
||||
xml_node_data.block_links.append({this, reader->readElementText().toULongLong()});
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::SaveInternal(QXmlStreamWriter *writer) const
|
||||
{
|
||||
foreach (Block* link, linked_clips_) {
|
||||
writer->writeTextElement(QStringLiteral("link"), QString::number(reinterpret_cast<quintptr>(link)));
|
||||
}
|
||||
}
|
||||
|
||||
QVector<NodeInput *> Block::GetInputsToHash() const
|
||||
{
|
||||
QVector<NodeInput*> inputs = Node::GetInputsToHash();
|
||||
@@ -200,74 +182,24 @@ QVector<NodeInput *> Block::GetInputsToHash() const
|
||||
return inputs;
|
||||
}
|
||||
|
||||
void Block::LinkChangeEvent()
|
||||
{
|
||||
block_links_.clear();
|
||||
|
||||
foreach (Node* n, links()) {
|
||||
Block* b = dynamic_cast<Block*>(n);
|
||||
|
||||
if (b) {
|
||||
block_links_.append(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::set_length_internal(const rational &length)
|
||||
{
|
||||
length_input_->SetStandardValue(QVariant::fromValue(length));
|
||||
}
|
||||
|
||||
bool Block::Link(Block *a, Block *b)
|
||||
{
|
||||
if (a == b || !a || !b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent duplicate link entries (assume that we only need to check one clip since this should be the only function
|
||||
// that adds to the linked array)
|
||||
if (Block::AreLinked(a, b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a->linked_clips_.append(b);
|
||||
b->linked_clips_.append(a);
|
||||
|
||||
emit a->LinksChanged();
|
||||
emit b->LinksChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Block::Link(const QList<Block*>& blocks)
|
||||
{
|
||||
foreach (Block* a, blocks) {
|
||||
foreach (Block* b, blocks) {
|
||||
Link(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::Unlink(Block *a, Block *b)
|
||||
{
|
||||
if (a == b || !a || !b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Block::AreLinked(a, b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a->linked_clips_.removeOne(b);
|
||||
b->linked_clips_.removeOne(a);
|
||||
|
||||
emit a->LinksChanged();
|
||||
emit b->LinksChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Block::Unlink(const QList<Block *> &blocks)
|
||||
{
|
||||
foreach (Block* a, blocks) {
|
||||
foreach (Block* b, blocks) {
|
||||
Unlink(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::AreLinked(Block *a, Block *b)
|
||||
{
|
||||
return a->linked_clips_.contains(b);
|
||||
}
|
||||
|
||||
void Block::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
|
||||
+8
-23
@@ -112,22 +112,6 @@ public:
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
|
||||
static bool Link(Block* a, Block* b);
|
||||
static void Link(const QList<Block*>& blocks);
|
||||
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() const
|
||||
{
|
||||
return linked_clips_;
|
||||
}
|
||||
|
||||
bool HasLinks() const
|
||||
{
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeInput* length_input() const
|
||||
@@ -175,13 +159,16 @@ public:
|
||||
index_ = i;
|
||||
}
|
||||
|
||||
const QVector<Block*>& block_links() const
|
||||
{
|
||||
return block_links_;
|
||||
}
|
||||
|
||||
virtual void Hash(QCryptographicHash &hash, const rational &time) const override;
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void LinksChanged();
|
||||
|
||||
void EnabledChanged();
|
||||
|
||||
void LengthChanged();
|
||||
@@ -191,12 +178,10 @@ protected:
|
||||
|
||||
rational MediaToSequenceTime(const rational& media_time) const;
|
||||
|
||||
virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData& xml_node_data) override;
|
||||
|
||||
virtual void SaveInternal(QXmlStreamWriter* writer) const override;
|
||||
|
||||
virtual QVector<NodeInput*> GetInputsToHash() const override;
|
||||
|
||||
virtual void LinkChangeEvent() override;
|
||||
|
||||
Block* previous_;
|
||||
Block* next_;
|
||||
|
||||
@@ -216,7 +201,7 @@ private:
|
||||
TransitionBlock* in_transition_;
|
||||
TransitionBlock* out_transition_;
|
||||
|
||||
QVector<Block*> linked_clips_;
|
||||
QVector<Block*> block_links_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,14 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const QAto
|
||||
SetLabel(reader->readElementText());
|
||||
} else if (reader->name() == QStringLiteral("color")) {
|
||||
override_color_ = reader->readElementText().toInt();
|
||||
} else if (reader->name() == QStringLiteral("links")) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("link")) {
|
||||
xml_node_data.block_links.append({this, reader->readElementText().toULongLong()});
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("custom")) {
|
||||
LoadInternal(reader, xml_node_data);
|
||||
} else {
|
||||
@@ -136,6 +144,12 @@ void Node::Save(QXmlStreamWriter *writer) const
|
||||
writer->writeEndElement(); // input
|
||||
}
|
||||
|
||||
writer->writeStartElement(QStringLiteral("links"));
|
||||
foreach (Node* link, links_) {
|
||||
writer->writeTextElement(QStringLiteral("link"), QString::number(reinterpret_cast<quintptr>(link)));
|
||||
}
|
||||
writer->writeEndElement(); // links
|
||||
|
||||
writer->writeStartElement(QStringLiteral("custom"));
|
||||
SaveInternal(writer);
|
||||
writer->writeEndElement(); // custom
|
||||
@@ -299,6 +313,51 @@ void Node::InvalidateAll(NodeInput* input, int element)
|
||||
InvalidateCache(TimeRange(RATIONAL_MIN, RATIONAL_MAX), {input, element});
|
||||
}
|
||||
|
||||
bool Node::Link(Node *a, Node *b)
|
||||
{
|
||||
if (a == b || !a || !b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AreLinked(a, b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a->links_.append(b);
|
||||
b->links_.append(a);
|
||||
|
||||
a->LinkChangeEvent();
|
||||
b->LinkChangeEvent();
|
||||
|
||||
emit a->LinksChanged();
|
||||
emit b->LinksChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Node::Unlink(Node *a, Node *b)
|
||||
{
|
||||
if (!AreLinked(a, b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a->links_.removeOne(b);
|
||||
b->links_.removeOne(a);
|
||||
|
||||
a->LinkChangeEvent();
|
||||
b->LinkChangeEvent();
|
||||
|
||||
emit a->LinksChanged();
|
||||
emit b->LinksChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Node::AreLinked(Node *a, Node *b)
|
||||
{
|
||||
return a->links_.contains(b);
|
||||
}
|
||||
|
||||
void Node::IgnoreInvalidationsFrom(NodeInput *input)
|
||||
{
|
||||
ignore_connections_.append(input);
|
||||
|
||||
@@ -425,6 +425,20 @@ public:
|
||||
|
||||
void InvalidateAll(NodeInput *input, int element);
|
||||
|
||||
bool HasLinks() const
|
||||
{
|
||||
return !links_.isEmpty();
|
||||
}
|
||||
|
||||
const QVector<Node*>& links() const
|
||||
{
|
||||
return links_;
|
||||
}
|
||||
|
||||
static bool Link(Node* a, Node* b);
|
||||
static bool Unlink(Node* a, Node* b);
|
||||
static bool AreLinked(Node* a, Node* b);
|
||||
|
||||
protected:
|
||||
void SendInvalidateCache(const TimeRange &range);
|
||||
|
||||
@@ -463,6 +477,8 @@ protected:
|
||||
|
||||
virtual void childEvent(QChildEvent* event) override;
|
||||
|
||||
virtual void LinkChangeEvent(){}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted whenever the position is set through SetPosition()
|
||||
@@ -486,6 +502,8 @@ signals:
|
||||
|
||||
void OutputDisconnected(NodeInput* destination, int element);
|
||||
|
||||
void LinksChanged();
|
||||
|
||||
private:
|
||||
template<class T>
|
||||
static void FindInputNodeInternal(const Node* n, QVector<T *>& list);
|
||||
@@ -521,6 +539,11 @@ private:
|
||||
*/
|
||||
int override_color_;
|
||||
|
||||
/**
|
||||
* @brief Nodes that are linked with this one
|
||||
*/
|
||||
QVector<Node*> links_;
|
||||
|
||||
private slots:
|
||||
void ParameterValueChanged(const olive::TimeRange &range, int element);
|
||||
|
||||
|
||||
@@ -113,9 +113,8 @@ void NodeRemoveAndDisconnectCommand::prep()
|
||||
command_ = new QUndoCommand();
|
||||
|
||||
// If this is a block, remove all links
|
||||
Block* block = dynamic_cast<Block*>(node_);
|
||||
if (block) {
|
||||
new BlockUnlinkAllCommand(block, command_);
|
||||
if (node_->HasLinks()) {
|
||||
new NodeUnlinkAllCommand(node_, command_);
|
||||
}
|
||||
|
||||
// Disconnect everything
|
||||
|
||||
@@ -230,6 +230,114 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NodeLinkCommand : public UndoCommand {
|
||||
public:
|
||||
NodeLinkCommand(Node* a, Node* b, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
a_(a),
|
||||
b_(b),
|
||||
link_(link)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return a_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
if (link_) {
|
||||
done_ = Node::Link(a_, b_);
|
||||
} else {
|
||||
done_ = Node::Unlink(a_, b_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
if (done_) {
|
||||
if (link_) {
|
||||
Node::Unlink(a_, b_);
|
||||
} else {
|
||||
Node::Link(a_, b_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Node* a_;
|
||||
Node* b_;
|
||||
bool link_;
|
||||
bool done_;
|
||||
|
||||
};
|
||||
|
||||
class NodeUnlinkAllCommand : public UndoCommand {
|
||||
public:
|
||||
NodeUnlinkAllCommand(Node* node, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
node_(node)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return node_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
unlinked_ = node_->links();
|
||||
|
||||
foreach (Node* link, unlinked_) {
|
||||
Node::Unlink(node_, link);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
foreach (Node* link, unlinked_) {
|
||||
Node::Link(node_, link);
|
||||
}
|
||||
|
||||
unlinked_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Node* node_;
|
||||
|
||||
QVector<Node*> unlinked_;
|
||||
|
||||
};
|
||||
|
||||
class NodeLinkManyCommand : public UndoCommand {
|
||||
public:
|
||||
NodeLinkManyCommand(const QVector<Node*> nodes, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
nodes_(nodes)
|
||||
{
|
||||
foreach (Node* a, nodes_) {
|
||||
foreach (Node* b, nodes_) {
|
||||
if (a != b) {
|
||||
new NodeLinkCommand(a, b, link, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return nodes_.first()->parent()->project();
|
||||
}
|
||||
|
||||
private:
|
||||
QVector<Node*> nodes_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEVIEWUNDO_H
|
||||
|
||||
@@ -500,117 +500,6 @@ private:
|
||||
Block* before_;
|
||||
};
|
||||
|
||||
class BlockLinkCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkCommand(Block* a, Block* b, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
a_(a),
|
||||
b_(b),
|
||||
link_(link)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return a_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
if (link_) {
|
||||
done_ = Block::Link(a_, b_);
|
||||
} else {
|
||||
done_ = Block::Unlink(a_, b_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
if (done_) {
|
||||
if (link_) {
|
||||
Block::Unlink(a_, b_);
|
||||
} else {
|
||||
Block::Link(a_, b_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Block* a_;
|
||||
|
||||
Block* b_;
|
||||
|
||||
bool link_;
|
||||
|
||||
bool done_;
|
||||
|
||||
};
|
||||
|
||||
class BlockUnlinkAllCommand : public UndoCommand {
|
||||
public:
|
||||
BlockUnlinkAllCommand(Block* block, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
block_(block)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return static_cast<Sequence*>(block_->parent())->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
unlinked_ = block_->linked_clips();
|
||||
|
||||
foreach (Block* link, unlinked_) {
|
||||
Block::Unlink(block_, link);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
foreach (Block* link, unlinked_) {
|
||||
Block::Link(block_, link);
|
||||
}
|
||||
|
||||
unlinked_.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
|
||||
QVector<Block*> unlinked_;
|
||||
|
||||
};
|
||||
|
||||
class BlockLinkManyCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkManyCommand(const QVector<Block*> blocks, bool link, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
blocks_(blocks)
|
||||
{
|
||||
foreach (Block* a, blocks_) {
|
||||
foreach (Block* b, blocks_) {
|
||||
if (a != b) {
|
||||
new BlockLinkCommand(a, b, link, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return blocks_.first()->parent()->project();
|
||||
}
|
||||
|
||||
private:
|
||||
QVector<Block*> blocks_;
|
||||
|
||||
};
|
||||
|
||||
class BlockSplitCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitCommand(Block* block, rational point, QUndoCommand* parent = nullptr) :
|
||||
@@ -833,7 +722,7 @@ protected:
|
||||
// These blocks are linked, ensure all the splits are linked too
|
||||
|
||||
foreach (const QVector<Block*>& split_list, split_blocks) {
|
||||
BlockLinkCommand* blc = new BlockLinkCommand(split_list.at(i), split_list.at(j), true);
|
||||
NodeLinkCommand* blc = new NodeLinkCommand(split_list.at(i), split_list.at(j), true);
|
||||
blc->redo();
|
||||
commands_.append(blc);
|
||||
}
|
||||
|
||||
@@ -530,7 +530,7 @@ void TimelineWidget::OverwriteFootageAtPlayhead(const QVector<Footage *> &footag
|
||||
|
||||
void TimelineWidget::ToggleLinksOnSelected()
|
||||
{
|
||||
QVector<Block*> blocks;
|
||||
QVector<Node*> blocks;
|
||||
bool link = true;
|
||||
|
||||
foreach (Block* item, GetSelectedBlocks()) {
|
||||
@@ -551,7 +551,7 @@ void TimelineWidget::ToggleLinksOnSelected()
|
||||
return;
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(new BlockLinkManyCommand(blocks, link));
|
||||
Core::instance()->undo_stack()->push(new NodeLinkManyCommand(blocks, link));
|
||||
}
|
||||
|
||||
void TimelineWidget::CopySelected(bool cut)
|
||||
@@ -1050,7 +1050,7 @@ void TimelineWidget::SetViewBeamCursor(const TimelineCoordinate &coord)
|
||||
|
||||
void TimelineWidget::SetBlockLinksSelected(Block* block, bool selected)
|
||||
{
|
||||
foreach (Block* link, block->linked_clips()) {
|
||||
foreach (Block* link, block->block_links()) {
|
||||
if (selected) {
|
||||
AddSelection(link);
|
||||
} else {
|
||||
@@ -1385,7 +1385,7 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
}
|
||||
|
||||
if (select_links) {
|
||||
foreach (Block* link, b->linked_clips()) {
|
||||
foreach (Block* link, b->block_links()) {
|
||||
if (!rubberband_now_selected_.contains(link)) {
|
||||
AddSelection(link);
|
||||
rubberband_now_selected_.append(link);
|
||||
|
||||
@@ -93,7 +93,7 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
// If not holding alt, deselect all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_, false);
|
||||
deselected_blocks.append(clicked_item_->linked_clips());
|
||||
deselected_blocks.append(clicked_item_->block_links());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
// If not holding alt, select all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_, true);
|
||||
selected_blocks.append(clicked_item_->linked_clips());
|
||||
selected_blocks.append(clicked_item_->block_links());
|
||||
}
|
||||
|
||||
parent()->SignalSelectedBlocks(selected_blocks);
|
||||
|
||||
@@ -77,7 +77,7 @@ void RazorTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
|
||||
// Add links if no alt is held
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
foreach (Block* link, block_at_time->linked_clips()) {
|
||||
foreach (Block* link, block_at_time->block_links()) {
|
||||
if (!blocks_to_split.contains(link)) {
|
||||
blocks_to_split.append(link);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user