Merge branch 'master' into otio

This commit is contained in:
itsmattkc
2020-10-22 20:26:16 +11:00
149 changed files with 4350 additions and 2079 deletions
+1
View File
@@ -25,6 +25,7 @@ OLIVE_NAMESPACE_ENTER
VolumeNode::VolumeNode()
{
samples_input_ = new NodeInput("samples_in", NodeParam::kSamples);
samples_input_->set_is_keyframable(false);
AddInput(samples_input_);
volume_input_ = new NodeInput("volume_in", NodeParam::kFloat, 1.0);
+5
View File
@@ -122,6 +122,11 @@ void Block::set_length_and_media_in(const rational &length)
LengthChangedEvent(old_length, length, Timeline::kTrimIn);
}
TimeRange Block::range() const
{
return TimeRange(in(), out());
}
Block *Block::previous()
{
return previous_;
+2
View File
@@ -54,6 +54,8 @@ public:
void set_length_and_media_out(const rational &length);
void set_length_and_media_in(const rational &length);
TimeRange range() const;
Block* previous();
Block* next();
void set_previous(Block* previous);
+16 -7
View File
@@ -20,22 +20,31 @@
#include "edge.h"
#include "input.h"
#include "node.h"
#include "output.h"
OLIVE_NAMESPACE_ENTER
NodeEdge::NodeEdge(NodeOutput *output, NodeInput *input) :
output_(output),
input_(input)
NodeEdge::NodeEdge(NodeOutput *output, NodeInput *input)
{
output_ = ParamToConnection(output);
input_ = ParamToConnection(input);
}
NodeOutput *NodeEdge::output()
NodeOutput *NodeEdge::output() const
{
return output_;
return output_.node->GetOutputWithID(output_.id);
}
NodeInput *NodeEdge::input()
NodeInput *NodeEdge::input() const
{
return input_;
return input_.node->GetInputWithID(input_.id);
}
NodeEdge::Connection NodeEdge::ParamToConnection(NodeParam *param)
{
return {param->parentNode(), param->id()};
}
OLIVE_NAMESPACE_EXIT
+26 -5
View File
@@ -22,13 +22,16 @@
#define EDGE_H
#include <memory>
#include <QString>
#include "common/define.h"
OLIVE_NAMESPACE_ENTER
class NodeOutput;
class Node;
class NodeInput;
class NodeOutput;
class NodeParam;
/**
* @brief A connection between two node parameters (a NodeOutput and a NodeInput)
@@ -44,19 +47,37 @@ public:
*/
NodeEdge(NodeOutput* output, NodeInput* input);
Node* output_node() const
{
return output_.node;
}
Node* input_node() const
{
return input_.node;
}
/**
* @brief Return the output parameter this edge is connected to
*/
NodeOutput* output();
NodeOutput* output() const;
/**
* @brief Return the input parameter this edge is connected to
*/
NodeInput* input();
NodeInput* input() const;
private:
NodeOutput* output_;
NodeInput* input_;
struct Connection {
Node* node;
QString id;
};
static Connection ParamToConnection(NodeParam* param);
Connection output_;
Connection input_;
};
using NodeEdgePtr = std::shared_ptr<NodeEdge>;
+87 -2
View File
@@ -22,6 +22,11 @@
OLIVE_NAMESPACE_ENTER
NodeGraph::NodeGraph() :
operation_stack_(0)
{
}
void NodeGraph::Clear()
{
foreach (Node* node, node_children_) {
@@ -38,14 +43,94 @@ void NodeGraph::AddNode(Node *node)
node->setParent(this);
connect(node, &Node::EdgeAdded, this, &NodeGraph::EdgeAdded);
connect(node, &Node::EdgeRemoved, this, &NodeGraph::EdgeRemoved);
connect(node, &Node::EdgeAdded, this, &NodeGraph::SignalEdgeAdded);
connect(node, &Node::EdgeRemoved, this, &NodeGraph::SignalEdgeRemoved);
node_children_.append(node);
emit NodeAdded(node);
}
void NodeGraph::BeginOperation()
{
operation_stack_++;
}
void NodeGraph::EndOperation()
{
operation_stack_--;
if (!operation_stack_) {
// Signal everything that we cached during the operation
// First, signal the removed edges
foreach (NodeEdgePtr e, cached_removed_edges_) {
emit EdgeRemoved(e);
}
cached_removed_edges_.clear();
// Next, signal the removed nodes
foreach (Node* n, cached_removed_nodes_) {
emit NodeRemoved(n);
}
cached_removed_nodes_.clear();
// Next, signal the added nodes
foreach (Node* n, cached_added_nodes_) {
emit NodeAdded(n);
}
cached_added_nodes_.clear();
// Finally, signal the added edges
foreach (NodeEdgePtr e, cached_added_edges_) {
emit EdgeAdded(e);
}
cached_added_edges_.clear();
}
}
void NodeGraph::SignalNodeAdded(Node* node)
{
if (!operation_stack_) {
emit NodeAdded(node);
} else if (!cached_removed_nodes_.removeOne(node)) {
// If we already removed this node during the operation (appending a signal to
// cached_removed_nodes_), we just remove that instead of appending a new signal. However if we
// didn't (removeOne returning false), only then do we append an add signal
cached_added_nodes_.append(node);
}
}
void NodeGraph::SignalNodeRemoved(Node *node)
{
if (!operation_stack_) {
emit NodeRemoved(node);
} else if (!cached_added_nodes_.removeOne(node)) {
// See SignalNodeAdded() for explanation of this
cached_removed_nodes_.append(node);
}
}
void NodeGraph::SignalEdgeAdded(NodeEdgePtr edge)
{
if (!operation_stack_) {
emit EdgeAdded(edge);
} else if (!cached_removed_edges_.removeOne(edge)) {
// See SignalNodeAdded() for explanation of this
cached_added_edges_.append(edge);
}
}
void NodeGraph::SignalEdgeRemoved(NodeEdgePtr edge)
{
if (!operation_stack_) {
emit EdgeRemoved(edge);
} else if (!cached_added_edges_.removeOne(edge)) {
// See SignalNodeAdded() for explanation of this
cached_removed_edges_.append(edge);
}
}
void NodeGraph::TakeNode(Node *node, QObject* new_parent)
{
if (!ContainsNode(node)) {
+19 -1
View File
@@ -37,7 +37,7 @@ public:
/**
* @brief NodeGraph Constructor
*/
NodeGraph() = default;
NodeGraph();
/**
* @brief Destructively destroys all nodes in the graph
@@ -67,6 +67,10 @@ public:
*/
bool ContainsNode(Node* n) const;
void BeginOperation();
void EndOperation();
signals:
/**
* @brief Signal emitted when a Node is added to the graph
@@ -90,6 +94,20 @@ signals:
private:
QList<Node*> node_children_;
int operation_stack_;
QList<Node*> cached_added_nodes_;
QList<Node*> cached_removed_nodes_;
QList<NodeEdgePtr> cached_added_edges_;
QList<NodeEdgePtr> cached_removed_edges_;
private slots:
void SignalNodeAdded(Node *node);
void SignalNodeRemoved(Node* node);
void SignalEdgeAdded(NodeEdgePtr edge);
void SignalEdgeRemoved(NodeEdgePtr edge);
};
OLIVE_NAMESPACE_EXIT
+5
View File
@@ -27,6 +27,11 @@ Node *AudioInput::copy() const
return new AudioInput();
}
Stream::Type AudioInput::type() const
{
return Stream::kAudio;
}
QString AudioInput::Name() const
{
return tr("Audio Input");
+2
View File
@@ -32,6 +32,8 @@ public:
virtual Node* copy() const override;
virtual Stream::Type type() const override;
virtual QString Name() const override;
virtual QString ShortName() const override;
virtual QString id() const override;
+5
View File
@@ -50,6 +50,11 @@ void MediaInput::SetFootage(StreamPtr f)
footage_input_->set_standard_value(QVariant::fromValue(f));
}
bool MediaInput::IsMedia() const
{
return true;
}
void MediaInput::Retranslate()
{
footage_input_->set_name(tr("Footage"));
+6
View File
@@ -23,6 +23,7 @@
#include "codec/decoder.h"
#include "node/node.h"
#include "project/item/footage/stream.h"
OLIVE_NAMESPACE_ENTER
@@ -35,11 +36,16 @@ class MediaInput : public Node
public:
MediaInput();
virtual Stream::Type type() const = 0;
virtual QList<CategoryID> Category() const override;
StreamPtr footage();
void SetFootage(StreamPtr f);
virtual bool IsMedia() const override;
virtual void Retranslate() override;
virtual NodeValueTable Value(NodeValueDatabase& value) const override;
+5
View File
@@ -36,6 +36,11 @@ Node *VideoInput::copy() const
return new VideoInput();
}
Stream::Type VideoInput::type() const
{
return Stream::kVideo;
}
QString VideoInput::Name() const
{
return tr("Video Input");
+2
View File
@@ -35,6 +35,8 @@ public:
virtual Node* copy() const override;
virtual Stream::Type type() const override;
virtual QString Name() const override;
virtual QString ShortName() const override;
virtual QString id() const override;
+19
View File
@@ -33,6 +33,12 @@ NodeInputArray::NodeInputArray(const QString &id, const DataType &type, const QV
{
}
NodeInputArray::~NodeInputArray()
{
// Clear all connected edges (make sure our override is called)
DisconnectAll();
}
bool NodeInputArray::IsArray() const
{
return true;
@@ -58,6 +64,10 @@ void NodeInputArray::SetSize(int size)
if (size < old_size) {
// If the new size is less, delete all extraneous parameters
for (int i=size;i<old_size;i++) {
sub_params_.at(i)->DisconnectAll();
}
for (int i=size;i<old_size;i++) {
delete sub_params_.at(i);
}
@@ -116,6 +126,15 @@ const QVector<NodeInput *> &NodeInputArray::sub_params()
return sub_params_;
}
void NodeInputArray::DisconnectAll()
{
NodeParam::DisconnectAll();
foreach (NodeInput* input, sub_params_) {
input->DisconnectAll();
}
}
void NodeInputArray::InsertAt(int index)
{
// Add another input at the end
+4
View File
@@ -31,6 +31,8 @@ class NodeInputArray : public NodeInput
public:
NodeInputArray(const QString &id, const DataType& type, const QVariant& default_value = 0);
virtual ~NodeInputArray() override;
virtual bool IsArray() const override;
int GetSize() const;
@@ -51,6 +53,8 @@ public:
const QVector<NodeInput*>& sub_params();
virtual void DisconnectAll() override;
signals:
void SizeChanged(int size);
+5
View File
@@ -467,6 +467,11 @@ bool Node::IsTrack() const
return false;
}
bool Node::IsMedia() const
{
return false;
}
const QList<NodeParam *>& Node::parameters() const
{
return params_;
+11
View File
@@ -369,6 +369,15 @@ public:
*/
virtual bool IsTrack() const;
/**
* @brief Returns whether this Node is a "Media" type or not
*
* You shouldn't ever need to override this since all derivatives of Media will automatically have this set to true.
* It's just a more convenient way of checking than dynamic_casting.
*/
virtual bool IsMedia() const;
/**
* @brief The main processing function
*
@@ -568,6 +577,8 @@ QList<T *> Node::FindOutputNode()
return list;
}
using NodePtr = std::shared_ptr<Node>;
OLIVE_NAMESPACE_EXIT
#endif // NODE_H
+6 -15
View File
@@ -55,6 +55,11 @@ TrackOutput::TrackOutput() :
track_height_ = kTrackHeightDefault;
}
TrackOutput::~TrackOutput()
{
DisconnectAll();
}
void TrackOutput::set_track_type(const Timeline::TrackType &track_type)
{
track_type_ = track_type;
@@ -91,15 +96,6 @@ QString TrackOutput::Description() const
"a Sequence.");
}
QString TrackOutput::GetTrackName()
{
if (track_name_.isEmpty()) {
return GetDefaultTrackName(track_type_, index_);
}
return track_name_;
}
const double &TrackOutput::GetTrackHeight() const
{
return track_height_;
@@ -435,11 +431,6 @@ void TrackOutput::Hash(QCryptographicHash &hash, const rational &time) const
}
}
void TrackOutput::SetTrackName(const QString &name)
{
track_name_ = name;
}
void TrackOutput::SetMuted(bool e)
{
muted_input_->set_standard_value(e);
@@ -555,7 +546,7 @@ void TrackOutput::BlockConnected(NodeEdgePtr edge)
void TrackOutput::BlockDisconnected(NodeEdgePtr edge)
{
Block* b = static_cast<Block*>(edge->output()->parentNode());
Block* b = static_cast<Block*>(edge->output_node());
if (block_cache_.contains(b)) {
block_cache_.removeOne(b);
+2 -6
View File
@@ -36,6 +36,8 @@ class TrackOutput : public Node
public:
TrackOutput();
virtual ~TrackOutput() override;
const Timeline::TrackType& track_type() const;
void set_track_type(const Timeline::TrackType& track_type);
@@ -46,8 +48,6 @@ public:
virtual QList<CategoryID> Category() const override;
virtual QString Description() const override;
QString GetTrackName();
const double& GetTrackHeight() const;
void SetTrackHeight(const double& height);
@@ -227,8 +227,6 @@ public:
static const double kTrackHeightInterval;
public slots:
void SetTrackName(const QString& name);
void SetMuted(bool e);
void SetLocked(bool e);
@@ -294,8 +292,6 @@ private:
double track_height_;
QString track_name_;
int index_;
bool locked_;
+16 -6
View File
@@ -134,7 +134,7 @@ TrackOutput* TrackList::AddTrack()
return track;
}
void TrackList::RemoveTrack()
void TrackList::RemoveTrack(QObject* new_parent)
{
if (track_cache_.isEmpty()) {
return;
@@ -144,7 +144,11 @@ void TrackList::RemoveTrack()
GetParentGraph()->TakeNode(track);
delete track;
if (!new_parent) {
delete track;
} else {
track->setParent(new_parent);
}
track_input_->RemoveLast();
}
@@ -184,7 +188,8 @@ void TrackList::TrackConnected(NodeEdgePtr edge)
track_cache_.append(connected_track);
}
connected_track->SetIndex(track_index);
// Update track indexes in the list (including this track)
UpdateTrackIndexesFrom(track_index);
}
connect(connected_track, &TrackOutput::BlockAdded, this, &TrackList::TrackAddedBlock);
@@ -220,9 +225,7 @@ void TrackList::TrackDisconnected(NodeEdgePtr edge)
track_cache_.removeAt(index_of_track);
// Update indices for all subsequent tracks
for (int i=index_of_track; i<track_cache_.size(); i++) {
track_cache_.at(i)->SetIndex(i);
}
UpdateTrackIndexesFrom(index_of_track);
// Traverse through Tracks uncaching and disconnecting them
emit TrackRemoved(track);
@@ -241,6 +244,13 @@ void TrackList::TrackDisconnected(NodeEdgePtr edge)
}
}
void TrackList::UpdateTrackIndexesFrom(int index)
{
for (int i=index; i<track_cache_.size(); i++) {
track_cache_.at(i)->SetIndex(i);
}
}
NodeGraph *TrackList::GetParentGraph() const
{
return static_cast<NodeGraph*>(parent()->parent());
+3 -1
View File
@@ -44,7 +44,7 @@ public:
TrackOutput *AddTrack();
void RemoveTrack();
void RemoveTrack(QObject *new_parent);
const rational& GetTotalLength() const;
@@ -68,6 +68,8 @@ signals:
void TrackHeightChanged(int index, int height);
private:
void UpdateTrackIndexesFrom(int index);
/**
* @brief A cache of connected Tracks
*/
+38 -2
View File
@@ -52,7 +52,7 @@ ViewerOutput::ViewerOutput() :
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::BlockRemoved, this, &ViewerOutput::SignalBlockRemoved);
connect(list, &TrackList::TrackAdded, this, &ViewerOutput::TrackListAddedTrack);
connect(list, &TrackList::TrackRemoved, this, &ViewerOutput::TrackRemoved);
connect(list, &TrackList::TrackHeightChanged, this, &ViewerOutput::TrackHeightChangedSlot);
@@ -62,6 +62,11 @@ ViewerOutput::ViewerOutput() :
uuid_ = QUuid::createUuid();
}
ViewerOutput::~ViewerOutput()
{
DisconnectAll();
}
Node *ViewerOutput::copy() const
{
return new ViewerOutput();
@@ -274,6 +279,27 @@ void ViewerOutput::set_media_name(const QString &name)
emit MediaNameChanged(media_name_);
}
void ViewerOutput::SignalBlockAdded(Block *block, const TrackReference& track)
{
if (!operation_stack_) {
emit BlockAdded(block, track);
} else {
cached_block_removed_.removeOne(block);
cached_block_added_.insert(block, track);
}
}
void ViewerOutput::SignalBlockRemoved(Block *block)
{
if (!operation_stack_) {
emit BlockRemoved({block});
} else {
// We keep track of all blocks that are removed, even if we don't end up signalling them
cached_block_added_.remove(block);
cached_block_removed_.append(block);
}
}
void ViewerOutput::BeginOperation()
{
operation_stack_++;
@@ -285,13 +311,23 @@ void ViewerOutput::EndOperation()
{
operation_stack_--;
if (!operation_stack_) {
for (auto it=cached_block_added_.cbegin(); it!=cached_block_added_.cend(); it++) {
emit BlockAdded(it.key(), it.value());
}
cached_block_added_.clear();
emit BlockRemoved(cached_block_removed_);
cached_block_removed_.clear();
}
Node::EndOperation();
}
void ViewerOutput::TrackListAddedBlock(Block *block, int index)
{
Timeline::TrackType type = static_cast<TrackList*>(sender())->type();
emit BlockAdded(block, TrackReference(type, index));
SignalBlockAdded(block, TrackReference(type, index));
}
void ViewerOutput::TrackListAddedTrack(TrackOutput *track)
+9 -1
View File
@@ -47,6 +47,8 @@ class ViewerOutput : public Node
public:
ViewerOutput();
virtual ~ViewerOutput() override;
virtual Node* copy() const override;
virtual QString Name() const override;
@@ -139,7 +141,7 @@ signals:
void AudioParamsChanged();
void BlockAdded(Block* block, TrackReference track);
void BlockRemoved(Block* block);
void BlockRemoved(const QList<Block*>& blocks);
void TrackAdded(TrackOutput* track, Timeline::TrackType type);
void TrackRemoved(TrackOutput* track);
@@ -149,6 +151,9 @@ signals:
void MediaNameChanged(const QString& name);
private:
QMap<Block*, TrackReference> cached_block_added_;
QList<Block*> cached_block_removed_;
QUuid uuid_;
NodeInput* texture_input_;
@@ -186,6 +191,9 @@ private slots:
void TrackHeightChangedSlot(int index, int height);
void SignalBlockAdded(Block *block, const TrackReference &track);
void SignalBlockRemoved(Block *block);
};
OLIVE_NAMESPACE_EXIT
+2 -4
View File
@@ -43,9 +43,7 @@ NodeParam::NodeParam(const QString &id) :
NodeParam::~NodeParam()
{
// Clear all connected edges
while (!edges_.isEmpty()) {
DisconnectEdge(edges_.last());
}
DisconnectAll();
}
const QString NodeParam::id() const
@@ -111,7 +109,7 @@ const QVector<NodeEdgePtr> &NodeParam::edges()
void NodeParam::DisconnectAll()
{
while (!edges_.isEmpty()) {
DisconnectEdge(edges_.first());
DisconnectEdge(edges_.last());
}
}
+1 -1
View File
@@ -319,7 +319,7 @@ public:
/**
* @brief Disconnect any edges connecting this parameter to other parameters
*/
void DisconnectAll();
virtual void DisconnectAll();
/**
* @brief Connect an output parameter to an input parameter