began new infrastructure
Yep, this is another one of my "famous" sweeping rewrites. Expect things to break. Goals for this are: - Greatly simplify node connections (particularly with arrays) so the code requires less maintenance/is more stable - Redesign node structure to address issues where UI would stall for lengthy periods of time - Less reliance on shared ptrs/greater reliance on QObject system for inheritance/memory management - General code cleanup and improvements
This commit is contained in:
+22
-31
@@ -31,28 +31,24 @@ Block::Block() :
|
||||
previous_(nullptr),
|
||||
next_(nullptr)
|
||||
{
|
||||
length_input_ = new NodeInput("length_in", NodeParam::kRational);
|
||||
length_input_->set_connectable(false);
|
||||
length_input_->set_is_keyframable(false);
|
||||
AddInput(length_input_);
|
||||
length_input_ = new NodeInput(this, QStringLiteral("length_in"), NodeValue::kRational);
|
||||
length_input_->SetConnectable(false);
|
||||
length_input_->SetKeyframable(false);
|
||||
disconnect(length_input_, &NodeInput::ValueChanged, this, &Block::InputChanged);
|
||||
connect(length_input_, &NodeInput::ValueChanged, this, &Block::LengthInputChanged);
|
||||
|
||||
media_in_input_ = new NodeInput("media_in_in", NodeParam::kRational);
|
||||
media_in_input_->set_connectable(false);
|
||||
media_in_input_->set_is_keyframable(false);
|
||||
AddInput(media_in_input_);
|
||||
media_in_input_ = new NodeInput(this, QStringLiteral("media_in_in"), NodeValue::kRational);
|
||||
media_in_input_->SetConnectable(false);
|
||||
media_in_input_->SetKeyframable(false);
|
||||
|
||||
enabled_input_ = new NodeInput("enabled_in", NodeParam::kBoolean);
|
||||
enabled_input_->set_connectable(false);
|
||||
enabled_input_->set_is_keyframable(false);
|
||||
enabled_input_->set_standard_value(true);
|
||||
AddInput(enabled_input_);
|
||||
enabled_input_ = new NodeInput(this, QStringLiteral("enabled_in"), NodeValue::kBoolean);
|
||||
enabled_input_->SetConnectable(false);
|
||||
enabled_input_->SetKeyframable(false);
|
||||
enabled_input_->SetStandardValue(true);
|
||||
|
||||
speed_input_ = new NodeInput("speed_in", NodeParam::kFloat);
|
||||
speed_input_->set_standard_value(1.0);
|
||||
speed_input_ = new NodeInput(this, QStringLiteral("speed_in"), NodeValue::kFloat);
|
||||
speed_input_->SetStandardValue(1.0);
|
||||
speed_input_->setProperty("view", QStringLiteral("percent"));
|
||||
AddInput(speed_input_);
|
||||
|
||||
// A block's length must be greater than 0
|
||||
set_length_and_media_out(1);
|
||||
@@ -85,7 +81,7 @@ void Block::set_out(const rational &out)
|
||||
|
||||
rational Block::length() const
|
||||
{
|
||||
return length_input_->get_standard_value().value<rational>();
|
||||
return length_input_->GetStandardValue().value<rational>();
|
||||
}
|
||||
|
||||
void Block::set_length_and_media_out(const rational &length)
|
||||
@@ -149,22 +145,22 @@ void Block::set_next(Block *next)
|
||||
|
||||
rational Block::media_in() const
|
||||
{
|
||||
return media_in_input_->get_standard_value().value<rational>();
|
||||
return media_in_input_->GetStandardValue().value<rational>();
|
||||
}
|
||||
|
||||
void Block::set_media_in(const rational &media_in)
|
||||
{
|
||||
media_in_input_->set_standard_value(QVariant::fromValue(media_in));
|
||||
media_in_input_->SetStandardValue(QVariant::fromValue(media_in));
|
||||
}
|
||||
|
||||
bool Block::is_enabled() const
|
||||
{
|
||||
return enabled_input_->get_standard_value().toBool();
|
||||
return enabled_input_->GetStandardValue().toBool();
|
||||
}
|
||||
|
||||
void Block::set_enabled(bool e)
|
||||
{
|
||||
enabled_input_->set_standard_value(e);
|
||||
enabled_input_->SetStandardValue(e);
|
||||
|
||||
emit EnabledChanged();
|
||||
}
|
||||
@@ -179,10 +175,10 @@ rational Block::SequenceToMediaTime(const rational &sequence_time) const
|
||||
rational local_time = sequence_time - in();
|
||||
|
||||
// FIXME: Doesn't handle reversing
|
||||
if (speed_input_->is_keyframing() || speed_input_->is_connected()) {
|
||||
if (speed_input_->IsKeyframing() || speed_input_->IsConnected()) {
|
||||
// FIXME: We'll need to calculate the speed hoo boy
|
||||
} else {
|
||||
double speed_value = speed_input_->get_standard_value().toDouble();
|
||||
double speed_value = speed_input_->GetStandardValue().toDouble();
|
||||
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point
|
||||
@@ -206,10 +202,10 @@ rational Block::MediaToSequenceTime(const rational &media_time) const
|
||||
rational sequence_time = media_time - media_in();
|
||||
|
||||
// FIXME: Doesn't handle reversing
|
||||
if (speed_input_->is_keyframing() || speed_input_->is_connected()) {
|
||||
if (speed_input_->IsKeyframing() || speed_input_->IsConnected()) {
|
||||
// FIXME: We'll need to calculate the speed hoo boy
|
||||
} else {
|
||||
double speed_value = speed_input_->get_standard_value().toDouble();
|
||||
double speed_value = speed_input_->GetStandardValue().toDouble();
|
||||
|
||||
if (qIsNull(speed_value)) {
|
||||
// Effectively holds the frame at the in point, also prevents divide by zero
|
||||
@@ -259,7 +255,7 @@ void Block::LengthChangedEvent(const rational &, const rational &, const Timelin
|
||||
|
||||
void Block::set_length_internal(const rational &length)
|
||||
{
|
||||
length_input_->set_standard_value(QVariant::fromValue(length));
|
||||
length_input_->SetStandardValue (QVariant::fromValue(length));
|
||||
}
|
||||
|
||||
void Block::LengthInputChanged()
|
||||
@@ -340,11 +336,6 @@ bool Block::HasLinks()
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
bool Block::IsBlock() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Block::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
|
||||
@@ -75,8 +75,6 @@ public:
|
||||
const QVector<Block*>& linked_clips();
|
||||
bool HasLinks();
|
||||
|
||||
virtual bool IsBlock() const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeInput* length_input() const;
|
||||
|
||||
@@ -24,9 +24,8 @@ namespace olive {
|
||||
|
||||
ClipBlock::ClipBlock()
|
||||
{
|
||||
texture_input_ = new NodeInput("buffer_in", NodeInput::kBuffer);
|
||||
texture_input_->set_is_keyframable(false);
|
||||
AddInput(texture_input_);
|
||||
texture_input_ = new NodeInput(this, QStringLiteral("buffer_in"), NodeValue::kNone);
|
||||
texture_input_->SetKeyframable(false);
|
||||
}
|
||||
|
||||
Node *ClipBlock::copy() const
|
||||
@@ -59,18 +58,18 @@ NodeInput *ClipBlock::texture_input() const
|
||||
return texture_input_;
|
||||
}
|
||||
|
||||
void ClipBlock::InvalidateCache(const TimeRange &range, NodeInput *from, NodeInput *source)
|
||||
void ClipBlock::InvalidateCache(const TimeRange& range, const InputConnection& from)
|
||||
{
|
||||
// If signal is from texture input, transform all times from media time to sequence time
|
||||
if (from == texture_input_) {
|
||||
if (from.input == texture_input_) {
|
||||
// Adjust range from media time to sequence time
|
||||
rational start = MediaToSequenceTime(range.in());
|
||||
rational end = MediaToSequenceTime(range.out());
|
||||
|
||||
Block::InvalidateCache(TimeRange(start, end), from, source);
|
||||
Block::InvalidateCache(TimeRange(start, end), from);
|
||||
} else {
|
||||
// Otherwise, pass signal along normally
|
||||
Block::InvalidateCache(range, from, source);
|
||||
Block::InvalidateCache(range, from);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,10 +94,10 @@ TimeRange ClipBlock::OutputTimeAdjustment(NodeInput *input, const TimeRange &inp
|
||||
NodeValueTable ClipBlock::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
// We discard most values here except for the buffer we received
|
||||
NodeValue data = value[texture_input()].GetWithMeta(NodeParam::kBuffer);
|
||||
NodeValue data = value[texture_input()].GetWithMeta(NodeValue::kBuffer);
|
||||
|
||||
NodeValueTable table;
|
||||
if (data.type() != NodeParam::kNone) {
|
||||
if (data.type() != NodeValue::kNone) {
|
||||
table.Push(data);
|
||||
}
|
||||
return table;
|
||||
@@ -113,10 +112,10 @@ void ClipBlock::Retranslate()
|
||||
|
||||
void ClipBlock::Hash(QCryptographicHash &hash, const rational &time) const
|
||||
{
|
||||
if (texture_input_->is_connected()) {
|
||||
if (texture_input_->IsConnected()) {
|
||||
rational t = InputTimeAdjustment(texture_input_, TimeRange(time, time)).in();
|
||||
|
||||
texture_input_->get_connected_node()->Hash(hash, t);
|
||||
texture_input_->GetConnectedNode()->Hash(hash, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
NodeInput* texture_input() const;
|
||||
|
||||
virtual void InvalidateCache(const TimeRange &range, NodeInput *from, NodeInput* source) override;
|
||||
virtual void InvalidateCache(const TimeRange& range, const InputConnection& from) override;
|
||||
|
||||
virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override;
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ namespace olive {
|
||||
|
||||
DipToColorTransition::DipToColorTransition()
|
||||
{
|
||||
color_input_ = new NodeInput(QStringLiteral("color_in"), NodeParam::kColor, QVariant::fromValue(Color(0, 0, 0)));
|
||||
AddInput(color_input_);
|
||||
color_input_ = new NodeInput(this, QStringLiteral("color_in"), NodeValue::kColor, QVariant::fromValue(Color(0, 0, 0)));
|
||||
}
|
||||
|
||||
Node *DipToColorTransition::copy() const
|
||||
|
||||
@@ -28,22 +28,19 @@ TransitionBlock::TransitionBlock() :
|
||||
connected_out_block_(nullptr),
|
||||
connected_in_block_(nullptr)
|
||||
{
|
||||
out_block_input_ = new NodeInput(QStringLiteral("out_block_in"), NodeParam::kBuffer);
|
||||
out_block_input_->set_is_keyframable(false);
|
||||
connect(out_block_input_, &NodeParam::EdgeAdded, this, &TransitionBlock::BlockConnected);
|
||||
connect(out_block_input_, &NodeParam::EdgeRemoved, this, &TransitionBlock::BlockDisconnected);
|
||||
AddInput(out_block_input_);
|
||||
out_block_input_ = new NodeInput(this, QStringLiteral("out_block_in"), NodeValue::kNone);
|
||||
out_block_input_->SetKeyframable(false);
|
||||
connect(out_block_input_, &NodeInput::InputConnected, this, &TransitionBlock::InBlockConnected);
|
||||
connect(out_block_input_, &NodeInput::InputDisconnected, this, &TransitionBlock::InBlockDisconnected);
|
||||
|
||||
in_block_input_ = new NodeInput(QStringLiteral("in_block_in"), NodeParam::kBuffer);
|
||||
in_block_input_->set_is_keyframable(false);
|
||||
connect(in_block_input_, &NodeParam::EdgeAdded, this, &TransitionBlock::BlockConnected);
|
||||
connect(in_block_input_, &NodeParam::EdgeRemoved, this, &TransitionBlock::BlockDisconnected);
|
||||
AddInput(in_block_input_);
|
||||
in_block_input_ = new NodeInput(this, QStringLiteral("in_block_in"), NodeValue::kNone);
|
||||
in_block_input_->SetKeyframable(false);
|
||||
connect(in_block_input_, &NodeInput::InputConnected, this, &TransitionBlock::OutBlockConnected);
|
||||
connect(in_block_input_, &NodeInput::InputDisconnected, this, &TransitionBlock::OutBlockDisconnected);
|
||||
|
||||
curve_input_ = new NodeInput(QStringLiteral("curve_in"), NodeParam::kCombo);
|
||||
curve_input_->set_is_keyframable(false);
|
||||
curve_input_->set_connectable(false);
|
||||
AddInput(curve_input_);
|
||||
curve_input_ = new NodeInput(this, QStringLiteral("curve_in"), NodeValue::kCombo);
|
||||
curve_input_->SetKeyframable(false);
|
||||
curve_input_->SetConnectable(false);
|
||||
}
|
||||
|
||||
Block::Type TransitionBlock::type() const
|
||||
@@ -161,57 +158,55 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t
|
||||
{
|
||||
// Provides total transition progress from 0.0 (start) - 1.0 (end)
|
||||
job->InsertValue(QStringLiteral("ove_tprog_all"),
|
||||
ShaderValue(GetTotalProgress(time), NodeParam::kFloat));
|
||||
NodeValue(NodeValue::kFloat, GetTotalProgress(time), this));
|
||||
|
||||
// Provides progress of out section from 1.0 (start) - 0.0 (end)
|
||||
job->InsertValue(QStringLiteral("ove_tprog_out"),
|
||||
ShaderValue(GetOutProgress(time), NodeParam::kFloat));
|
||||
NodeValue(NodeValue::kFloat, GetOutProgress(time), this));
|
||||
|
||||
// Provides progress of in section from 0.0 (start) - 1.0 (end)
|
||||
job->InsertValue(QStringLiteral("ove_tprog_in"),
|
||||
ShaderValue(GetInProgress(time), NodeParam::kFloat));
|
||||
NodeValue(NodeValue::kFloat, GetInProgress(time), this));
|
||||
}
|
||||
|
||||
void TransitionBlock::BlockConnected(NodeEdgePtr edge)
|
||||
void TransitionBlock::OutBlockConnected(Node *node)
|
||||
{
|
||||
if (!edge->output()->parentNode()->IsBlock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block* block = static_cast<Block*>(edge->output()->parentNode());
|
||||
|
||||
if (edge->input() == out_block_input_) {
|
||||
connected_out_block_ = block;
|
||||
} else {
|
||||
connected_in_block_ = block;
|
||||
}
|
||||
// If node is not a block, this will just be null
|
||||
connected_out_block_ = dynamic_cast<Block*>(node);
|
||||
}
|
||||
|
||||
void TransitionBlock::BlockDisconnected(NodeEdgePtr edge)
|
||||
void TransitionBlock::OutBlockDisconnected()
|
||||
{
|
||||
if (edge->input() == out_block_input_) {
|
||||
connected_out_block_ = nullptr;
|
||||
} else {
|
||||
connected_in_block_ = 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);
|
||||
}
|
||||
|
||||
void TransitionBlock::InBlockDisconnected()
|
||||
{
|
||||
connected_in_block_ = nullptr;
|
||||
}
|
||||
|
||||
NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
NodeParam::DataType data_type;
|
||||
NodeValue::Type data_type;
|
||||
|
||||
if (out_block_input()->is_connected()) {
|
||||
data_type = value[out_block_input()].GetWithMeta(NodeParam::kBuffer).type();
|
||||
} else if (in_block_input()->is_connected()) {
|
||||
data_type = value[in_block_input()].GetWithMeta(NodeParam::kBuffer).type();
|
||||
if (out_block_input()->IsConnected()) {
|
||||
data_type = value[out_block_input()].GetWithMeta(NodeValue::kBuffer).type();
|
||||
} else if (in_block_input()->IsConnected()) {
|
||||
data_type = value[in_block_input()].GetWithMeta(NodeValue::kBuffer).type();
|
||||
} else {
|
||||
data_type = NodeParam::kNone;
|
||||
data_type = NodeValue::kNone;
|
||||
}
|
||||
|
||||
NodeParam::DataType job_type;
|
||||
NodeValue::Type job_type;
|
||||
QVariant push_job;
|
||||
|
||||
if (data_type == NodeParam::kTexture) {
|
||||
if (data_type == NodeValue::kTexture) {
|
||||
// This must be a visual transition
|
||||
ShaderJob job;
|
||||
|
||||
@@ -219,21 +214,21 @@ NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
job.InsertValue(in_block_input(), value);
|
||||
job.InsertValue(curve_input_, value);
|
||||
|
||||
double time = value[QStringLiteral("global")].Get(NodeParam::kFloat, QStringLiteral("time_in")).toDouble();
|
||||
double time = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")).toDouble();
|
||||
InsertTransitionTimes(&job, time);
|
||||
|
||||
ShaderJobEvent(value, job);
|
||||
|
||||
job_type = NodeParam::kShaderJob;
|
||||
job_type = NodeValue::kShaderJob;
|
||||
push_job = QVariant::fromValue(job);
|
||||
} else if (data_type == NodeParam::kSamples) {
|
||||
} else if (data_type == NodeValue::kSamples) {
|
||||
// This must be an audio transition
|
||||
SampleBufferPtr from_samples = value[out_block_input()].Take(NodeParam::kBuffer).value<SampleBufferPtr>();
|
||||
SampleBufferPtr to_samples = value[in_block_input()].Take(NodeParam::kBuffer).value<SampleBufferPtr>();
|
||||
SampleBufferPtr from_samples = value[out_block_input()].Take(NodeValue::kSamples).value<SampleBufferPtr>();
|
||||
SampleBufferPtr to_samples = value[in_block_input()].Take(NodeValue::kSamples).value<SampleBufferPtr>();
|
||||
|
||||
if (from_samples || to_samples) {
|
||||
double time_in = value[QStringLiteral("global")].Get(NodeParam::kFloat, QStringLiteral("time_in")).toDouble();
|
||||
double time_out = value[QStringLiteral("global")].Get(NodeParam::kFloat, QStringLiteral("time_out")).toDouble();
|
||||
double time_in = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")).toDouble();
|
||||
double time_out = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_out")).toDouble();
|
||||
|
||||
const AudioParams& params = (from_samples) ? from_samples->audio_params() : to_samples->audio_params();
|
||||
|
||||
@@ -242,7 +237,7 @@ NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
SampleBufferPtr out_samples = SampleBuffer::CreateAllocated(params, nb_samples);
|
||||
SampleJobEvent(from_samples, to_samples, out_samples, time_in);
|
||||
|
||||
job_type = NodeParam::kSamples;
|
||||
job_type = NodeValue::kSamples;
|
||||
push_job = QVariant::fromValue(out_samples);
|
||||
}
|
||||
}
|
||||
@@ -259,19 +254,13 @@ NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
TransitionBlock *GetBlockTransitionInternal(Block *block, Timeline::MovementMode mode)
|
||||
{
|
||||
// See if this block outputs to a transition
|
||||
foreach (NodeEdgePtr edge, block->output()->edges()) {
|
||||
Node* connected_node = edge->input()->parentNode();
|
||||
foreach (const NodeConnectable::InputConnection& conn, block->edges()) {
|
||||
TransitionBlock* transition = dynamic_cast<TransitionBlock*>(conn.input->parent());
|
||||
|
||||
if (connected_node->IsBlock()) {
|
||||
Block* connected_block = static_cast<Block*>(connected_node);
|
||||
|
||||
if (connected_block->type() == Block::kTransition) {
|
||||
TransitionBlock* connected_transition = static_cast<TransitionBlock*>(connected_block);
|
||||
|
||||
if ((mode == Timeline::kTrimIn && edge->input() == connected_transition->in_block_input())
|
||||
|| (mode == Timeline::kTrimOut && edge->input() == connected_transition->out_block_input())) {
|
||||
return connected_transition;
|
||||
}
|
||||
if (transition) {
|
||||
if ((mode == Timeline::kTrimIn && conn.input == transition->in_block_input())
|
||||
|| (mode == Timeline::kTrimOut && conn.input == transition->out_block_input())) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,7 +294,7 @@ void TransitionBlock::SampleJobEvent(SampleBufferPtr from_samples, SampleBufferP
|
||||
|
||||
double TransitionBlock::TransformCurve(double linear) const
|
||||
{
|
||||
switch (static_cast<CurveType>(curve_input_->get_standard_value().toInt())) {
|
||||
switch (static_cast<CurveType>(curve_input_->GetStandardValue().toInt())) {
|
||||
case kLinear:
|
||||
break;
|
||||
case kExponential:
|
||||
|
||||
@@ -85,9 +85,13 @@ private:
|
||||
Block* connected_in_block_;
|
||||
|
||||
private slots:
|
||||
void BlockConnected(NodeEdgePtr edge);
|
||||
void OutBlockConnected(Node* node);
|
||||
|
||||
void BlockDisconnected(NodeEdgePtr edge);
|
||||
void OutBlockDisconnected();
|
||||
|
||||
void InBlockConnected(Node* node);
|
||||
|
||||
void InBlockDisconnected();
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user