nodes: implemented core of manual table value selection
This commit is contained in:
@@ -30,6 +30,8 @@ set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
node/factory.cpp
|
||||
node/factory.h
|
||||
node/globals.cpp
|
||||
node/globals.h
|
||||
node/graph.cpp
|
||||
node/graph.h
|
||||
node/inputdragger.cpp
|
||||
|
||||
@@ -62,16 +62,13 @@ QString PanNode::Description() const
|
||||
return tr("Adjust the stereo panning of an audio source.");
|
||||
}
|
||||
|
||||
NodeValueTable PanNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void PanNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(globals)
|
||||
|
||||
// Create a sample job
|
||||
SampleJob job(kSamplesInput, value);
|
||||
job.InsertValue(this, kPanningInput, value);
|
||||
|
||||
// Push it to our table
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (job.HasSamples()) {
|
||||
bool push_job = false;
|
||||
@@ -95,18 +92,16 @@ NodeValueTable PanNode::Value(const QString &output, NodeValueDatabase &value) c
|
||||
}
|
||||
|
||||
if (push_job) {
|
||||
table.Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
table.Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this);
|
||||
table->Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void PanNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void PanNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
float pan_val = values[kPanningInput].Get(NodeValue::kFloat).toFloat();
|
||||
float pan_val = values[kPanningInput].data().toFloat();
|
||||
|
||||
for (int i=0;i<input->audio_params().channel_count();i++) {
|
||||
output->data(i)[index] = input->data(i)[index];
|
||||
|
||||
@@ -40,9 +40,9 @@ public:
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
@@ -61,20 +61,21 @@ QString VolumeNode::Description() const
|
||||
return tr("Adjusts the volume of an audio source.");
|
||||
}
|
||||
|
||||
NodeValueTable VolumeNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void VolumeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
return ValueInternal(value,
|
||||
kOpMultiply,
|
||||
return ValueInternal(kOpMultiply,
|
||||
kPairSampleNumber,
|
||||
kSamplesInput,
|
||||
value[kSamplesInput].TakeWithMeta(NodeValue::kSamples),
|
||||
value[kSamplesInput],
|
||||
kVolumeInput,
|
||||
value[kVolumeInput].TakeWithMeta(NodeValue::kFloat));
|
||||
value[kVolumeInput],
|
||||
globals,
|
||||
table);
|
||||
}
|
||||
|
||||
void VolumeNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void VolumeNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
return ProcessSamplesInternal(values, kOpMultiply, kSamplesInput, kVolumeInput, input, output, index);
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ public:
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
@@ -100,13 +100,16 @@ void Block::InputValueChangedEvent(const QString &input, int element)
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
if (IsInputConnected(input)) {
|
||||
rational t = InputTimeAdjustment(input, -1, TimeRange(time, time)).in();
|
||||
TimeRange t = InputTimeAdjustment(input, -1, globals.time());
|
||||
|
||||
NodeGlobals new_globals = globals;
|
||||
new_globals.set_time(t);
|
||||
|
||||
NodeOutput out = GetConnectedOutput(input);
|
||||
out.node()->Hash(out.output(), hash, t, video_params);
|
||||
out.node()->Hash(out.output(), hash, new_globals, video_params);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -127,7 +130,7 @@ void Block::Retranslate()
|
||||
SetInputName(kEnabledInput, tr("Enabled"));
|
||||
}
|
||||
|
||||
void Block::Hash(const QString &, QCryptographicHash &, const rational &, const VideoParams &) const
|
||||
void Block::Hash(const QString &, QCryptographicHash &, const NodeGlobals &, const VideoParams &) const
|
||||
{
|
||||
// A block does nothing by default, so we hash nothing
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
index_ = i;
|
||||
}
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
|
||||
@@ -134,7 +134,7 @@ signals:
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
|
||||
bool HashPassthrough(const QString &input, const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const;
|
||||
bool HashPassthrough(const QString &input, const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const;
|
||||
|
||||
Block* previous_;
|
||||
Block* next_;
|
||||
|
||||
@@ -49,7 +49,8 @@ ClipBlock::ClipBlock() :
|
||||
AddInput(kReverseInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
IgnoreHashingFrom(kReverseInput);
|
||||
|
||||
AddInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
|
||||
PrependInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable));
|
||||
SetValueHintForInput(kBufferIn, {NodeValue::kBuffer, -1, QString()});
|
||||
}
|
||||
|
||||
Node *ClipBlock::copy() const
|
||||
@@ -231,18 +232,18 @@ TimeRange ClipBlock::OutputTimeAdjustment(const QString& input, int element, con
|
||||
return super::OutputTimeAdjustment(input, element, input_time);
|
||||
}
|
||||
|
||||
NodeValueTable ClipBlock::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void ClipBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(globals)
|
||||
|
||||
// We discard most values here except for the buffer we received
|
||||
NodeValue data = value[kBufferIn].GetWithMeta(NodeValue::kBuffer);
|
||||
NodeValue data = value[kBufferIn];
|
||||
|
||||
NodeValueTable table;
|
||||
table->Clear();
|
||||
if (data.type() != NodeValue::kNone) {
|
||||
table.Push(data);
|
||||
table->Push(data);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
void ClipBlock::Retranslate()
|
||||
@@ -255,9 +256,9 @@ void ClipBlock::Retranslate()
|
||||
SetInputName(kReverseInput, tr("Reverse"));
|
||||
}
|
||||
|
||||
void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
HashPassthrough(kBufferIn, out, hash, time, video_params);
|
||||
HashPassthrough(kBufferIn, out, hash, globals, video_params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,11 +55,11 @@ public:
|
||||
|
||||
virtual TimeRange OutputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
double speed() const
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ ShaderCode CrossDissolveTransition::GetShaderCode(const QString &shader_id) cons
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/crossdissolve.frag"), QString());
|
||||
}
|
||||
|
||||
void CrossDissolveTransition::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const
|
||||
void CrossDissolveTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
virtual ShaderCode GetShaderCode(const QString& shader_id) const override;
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(NodeValueDatabase& value, ShaderJob& job) const override;
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override;
|
||||
|
||||
virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const override;
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ ShaderCode DipToColorTransition::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/diptoblack.frag"), QString());
|
||||
}
|
||||
|
||||
void DipToColorTransition::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const
|
||||
void DipToColorTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const
|
||||
{
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
job.InsertValue(kColorInput, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
static const QString kColorInput;
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const override;
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -137,12 +137,12 @@ double TransitionBlock::GetInProgress(const double &time) const
|
||||
return clamp((GetInternalTransitionTime(time) - out_offset().toDouble()) / in_offset().toDouble(), 0.0, 1.0);
|
||||
}
|
||||
|
||||
void TransitionBlock::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void TransitionBlock::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
if (HashPassthrough(kInBlockInput, output, hash, time, video_params) || HashPassthrough(kOutBlockInput, output, hash, time, video_params)) {
|
||||
if (HashPassthrough(kInBlockInput, output, hash, globals, video_params) || HashPassthrough(kOutBlockInput, output, hash, globals, video_params)) {
|
||||
HashAddNodeSignature(hash, output);
|
||||
|
||||
double time_dbl = time.toDouble();
|
||||
double time_dbl = globals.time().in().toDouble();
|
||||
double all_prog = GetTotalProgress(time_dbl);
|
||||
double in_prog = GetInProgress(time_dbl);
|
||||
double out_prog = GetOutProgress(time_dbl);
|
||||
@@ -173,12 +173,12 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t
|
||||
NodeValue(NodeValue::kFloat, GetInProgress(time), this));
|
||||
}
|
||||
|
||||
NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void TransitionBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
NodeValue out_buffer = value[kOutBlockInput].TakeWithMeta(NodeValue::kBuffer);
|
||||
NodeValue in_buffer = value[kInBlockInput].TakeWithMeta(NodeValue::kBuffer);
|
||||
NodeValue out_buffer = value[kOutBlockInput];
|
||||
NodeValue in_buffer = value[kInBlockInput];
|
||||
NodeValue::Type data_type = (out_buffer.type() != NodeValue::kNone) ? out_buffer.type() : in_buffer.type();
|
||||
|
||||
NodeValue::Type job_type = NodeValue::kNone;
|
||||
@@ -196,9 +196,9 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase &
|
||||
job.InsertValue(kInBlockInput, in_buffer);
|
||||
}
|
||||
|
||||
job.InsertValue(this, kCurveInput, value);
|
||||
job.InsertValue(kCurveInput, value);
|
||||
|
||||
double time = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")).toDouble();
|
||||
double time = globals.time().in().toDouble();
|
||||
InsertTransitionTimes(&job, time);
|
||||
|
||||
ShaderJobEvent(value, job);
|
||||
@@ -211,8 +211,8 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase &
|
||||
SampleBufferPtr to_samples = in_buffer.data().value<SampleBufferPtr>();
|
||||
|
||||
if (from_samples || to_samples) {
|
||||
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();
|
||||
double time_in = globals.time().in().toDouble();
|
||||
double time_out = globals.time().out().toDouble();
|
||||
|
||||
const AudioParams& params = (from_samples) ? from_samples->audio_params() : to_samples->audio_params();
|
||||
|
||||
@@ -226,13 +226,9 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase &
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!push_job.isNull()) {
|
||||
table.Push(job_type, push_job, this);
|
||||
table->Push(job_type, push_job, this);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options)
|
||||
@@ -249,7 +245,7 @@ void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &fro
|
||||
super::InvalidateCache(r, from, element, options);
|
||||
}
|
||||
|
||||
void TransitionBlock::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const
|
||||
void TransitionBlock::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
Q_UNUSED(job)
|
||||
|
||||
@@ -65,9 +65,9 @@ public:
|
||||
double GetOutProgress(const double &time) const;
|
||||
double GetInProgress(const double &time) const;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override;
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
static const QString kCenterInput;
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const;
|
||||
virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const;
|
||||
|
||||
virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const;
|
||||
|
||||
|
||||
@@ -55,35 +55,25 @@ void CropDistortNode::Retranslate()
|
||||
SetInputName(kFeatherInput, tr("Feather"));
|
||||
}
|
||||
|
||||
NodeValueTable CropDistortNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void CropDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(this, kTextureInput, value);
|
||||
job.InsertValue(this, kLeftInput, value);
|
||||
job.InsertValue(this, kTopInput, value);
|
||||
job.InsertValue(this, kRightInput, value);
|
||||
job.InsertValue(this, kBottomInput, value);
|
||||
job.InsertValue(this, kFeatherInput, value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"),
|
||||
NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this));
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!job.GetValue(kTextureInput).data().isNull()) {
|
||||
if (!qIsNull(job.GetValue(kLeftInput).data().toDouble())
|
||||
|| !qIsNull(job.GetValue(kRightInput).data().toDouble())
|
||||
|| !qIsNull(job.GetValue(kTopInput).data().toDouble())
|
||||
|| !qIsNull(job.GetValue(kBottomInput).data().toDouble())) {
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
table.Push(NodeValue::kTexture, job.GetValue(kTextureInput).data(), this);
|
||||
table->Push(NodeValue::kTexture, job.GetValue(kTextureInput).data(), this);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
ShaderCode CropDistortNode::GetShaderCode(const QString &shader_id) const
|
||||
@@ -92,18 +82,18 @@ ShaderCode CropDistortNode::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/crop.frag")));
|
||||
}
|
||||
|
||||
void CropDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
void CropDistortNode::DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p)
|
||||
{
|
||||
QVector2D resolution = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value<QVector2D>();
|
||||
const QVector2D &resolution = globals.resolution();
|
||||
|
||||
const double handle_radius = GetGizmoHandleRadius(p->transform());
|
||||
|
||||
p->setPen(QPen(Qt::white, 0));
|
||||
|
||||
double left_pt = resolution.x() * db[kLeftInput].Get(NodeValue::kFloat).toDouble();
|
||||
double top_pt = resolution.y() * db[kTopInput].Get(NodeValue::kFloat).toDouble();
|
||||
double right_pt = resolution.x() * (1.0 - db[kRightInput].Get(NodeValue::kFloat).toDouble());
|
||||
double bottom_pt = resolution.y() * (1.0 - db[kBottomInput].Get(NodeValue::kFloat).toDouble());
|
||||
double left_pt = resolution.x() * row[kLeftInput].data().toDouble();
|
||||
double top_pt = resolution.y() * row[kTopInput].data().toDouble();
|
||||
double right_pt = resolution.x() * (1.0 - row[kRightInput].data().toDouble());
|
||||
double bottom_pt = resolution.y() * (1.0 - row[kBottomInput].data().toDouble());
|
||||
double center_x_pt = lerp(left_pt, right_pt, 0.5);
|
||||
double center_y_pt = lerp(top_pt, bottom_pt, 0.5);
|
||||
|
||||
@@ -124,7 +114,7 @@ void CropDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
DrawAndExpandGizmoHandles(p, handle_radius, gizmo_resize_handle_, kGizmoScaleCount);
|
||||
}
|
||||
|
||||
bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
bool CropDistortNode::GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p)
|
||||
{
|
||||
bool found_handle = false;
|
||||
|
||||
@@ -150,7 +140,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
|| in_rect) {
|
||||
gizmo_drag_ |= kGizmoLeft;
|
||||
|
||||
gizmo_start_.append(db[kLeftInput].Get(NodeValue::kFloat));
|
||||
gizmo_start_.append(row[kLeftInput].data());
|
||||
}
|
||||
|
||||
if (gizmo_active[kGizmoScaleTopLeft]
|
||||
@@ -159,7 +149,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
|| in_rect) {
|
||||
gizmo_drag_ |= kGizmoTop;
|
||||
|
||||
gizmo_start_.append(db[kTopInput].Get(NodeValue::kFloat));
|
||||
gizmo_start_.append(row[kTopInput].data());
|
||||
}
|
||||
|
||||
if (gizmo_active[kGizmoScaleTopRight]
|
||||
@@ -168,7 +158,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
|| in_rect) {
|
||||
gizmo_drag_ |= kGizmoRight;
|
||||
|
||||
gizmo_start_.append(db[kRightInput].Get(NodeValue::kFloat));
|
||||
gizmo_start_.append(row[kRightInput].data());
|
||||
}
|
||||
|
||||
if (gizmo_active[kGizmoScaleBottomLeft]
|
||||
@@ -177,11 +167,11 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
|| in_rect) {
|
||||
gizmo_drag_ |= kGizmoBottom;
|
||||
|
||||
gizmo_start_.append(db[kBottomInput].Get(NodeValue::kFloat));
|
||||
gizmo_start_.append(row[kBottomInput].data());
|
||||
}
|
||||
|
||||
if (gizmo_drag_ > kGizmoNone) {
|
||||
gizmo_res_ = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value<QVector2D>();
|
||||
gizmo_res_ = globals.resolution();
|
||||
gizmo_drag_start_ = p;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
|
||||
@@ -72,9 +72,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) override;
|
||||
virtual void DrawGizmos(const NodeValueRow& row, const NodeGlobals &globals, QPainter *p) override;
|
||||
|
||||
virtual bool GizmoPress(NodeValueDatabase& db, const QPointF &p) override;
|
||||
virtual bool GizmoPress(const NodeValueRow& row, const NodeGlobals &globals, const QPointF &p) override;
|
||||
virtual void GizmoMove(const QPointF &p, const rational &time) override;
|
||||
virtual void GizmoRelease() override;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ void TransformDistortNode::Retranslate()
|
||||
SetComboBoxStrings(kInterpolationInput, {tr("Nearest Neighbor"), tr("Bilinear"), tr("Mipmapped Bilinear")});
|
||||
}
|
||||
|
||||
NodeValueTable TransformDistortNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void TransformDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
@@ -62,36 +62,31 @@ NodeValueTable TransformDistortNode::Value(const QString &output, NodeValueDatab
|
||||
QMatrix4x4 generated_matrix = GenerateMatrix(value, true, false, false, false);
|
||||
|
||||
// Pop texture
|
||||
NodeValue texture_meta = value[kTextureInput].TakeWithMeta(NodeValue::kTexture);
|
||||
NodeValue texture_meta = value[kTextureInput];
|
||||
TexturePtr texture = texture_meta.data().value<TexturePtr>();
|
||||
|
||||
// Merge table
|
||||
NodeValueTable table = value[kTextureInput];
|
||||
|
||||
// If we have a texture, generate a matrix and make it happen
|
||||
if (texture) {
|
||||
// Adjust our matrix by the resolutions involved
|
||||
QMatrix4x4 real_matrix = GenerateAutoScaledMatrix(generated_matrix, value, texture->params());
|
||||
QMatrix4x4 real_matrix = GenerateAutoScaledMatrix(generated_matrix, value, globals, texture->params());
|
||||
|
||||
if (real_matrix.isIdentity()) {
|
||||
// We don't expect any changes, just push as normal
|
||||
table.Push(texture_meta);
|
||||
table->Push(texture_meta);
|
||||
} else {
|
||||
// The matrix will transform things
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture), this));
|
||||
job.InsertValue(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, real_matrix, this));
|
||||
job.SetInterpolation(QStringLiteral("ove_maintex"), static_cast<Texture::Interpolation>(value[kInterpolationInput].Get(NodeValue::kCombo).toInt()));
|
||||
job.SetInterpolation(QStringLiteral("ove_maintex"), static_cast<Texture::Interpolation>(value[kInterpolationInput].data().toInt()));
|
||||
|
||||
// FIXME: This should be optimized, we can use matrix math to determine if this operation will
|
||||
// end up with gaps in the screen that will require an alpha channel.
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
ShaderCode TransformDistortNode::GetShaderCode(const QString &shader_id) const
|
||||
@@ -102,9 +97,9 @@ ShaderCode TransformDistortNode::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode();
|
||||
}
|
||||
|
||||
bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
bool TransformDistortNode::GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p)
|
||||
{
|
||||
TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
TexturePtr tex = row[kTextureInput].data().value<TexturePtr>();
|
||||
if (!tex) {
|
||||
return false;
|
||||
}
|
||||
@@ -128,10 +123,10 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
if (scaling) {
|
||||
|
||||
// Dragging scale handle
|
||||
gizmo_start_ = {db[kScaleInput].Get(NodeValue::kVec2)};
|
||||
gizmo_start_ = {row[kScaleInput].data()};
|
||||
gizmo_drag_ = kScaleInput;
|
||||
|
||||
gizmo_scale_uniform_ = db[kUniformScaleInput].Get(NodeValue::kBoolean).toBool();
|
||||
gizmo_scale_uniform_ = row[kUniformScaleInput].data().toBool();
|
||||
|
||||
if (gizmo_scale_active[kGizmoScaleTopLeft] || gizmo_scale_active[kGizmoScaleTopRight]
|
||||
|| gizmo_scale_active[kGizmoScaleBottomLeft] || gizmo_scale_active[kGizmoScaleBottomRight]) {
|
||||
@@ -145,7 +140,7 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
// Store texture size
|
||||
VideoParams texture_params = tex->params();
|
||||
QVector2D texture_sz(texture_params.square_pixel_width(), texture_params.height());
|
||||
gizmo_scale_anchor_ = db[kAnchorInput].Get(NodeValue::kVec2).value<QVector2D>() + texture_sz/2;
|
||||
gizmo_scale_anchor_ = row[kAnchorInput].data().value<QVector2D>() + texture_sz/2;
|
||||
|
||||
if (gizmo_scale_active[kGizmoScaleTopRight]
|
||||
|| gizmo_scale_active[kGizmoScaleBottomRight]
|
||||
@@ -162,26 +157,26 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
}
|
||||
|
||||
// Store current matrix
|
||||
gizmo_matrix_ = GenerateMatrix(db, false, true, true, true);
|
||||
gizmo_matrix_ = GenerateMatrix(row, false, true, true, true);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (gizmo_anchor_pt_.contains(p)) {
|
||||
|
||||
// Dragging the anchor point specifically
|
||||
gizmo_start_ = {db[kAnchorInput].Get(NodeValue::kVec2),
|
||||
db[kPositionInput].Get(NodeValue::kVec2)};
|
||||
gizmo_start_ = {row[kAnchorInput].data(),
|
||||
row[kPositionInput].data()};
|
||||
gizmo_drag_ = kAnchorInput;
|
||||
|
||||
// Store current matrix
|
||||
gizmo_matrix_ = GenerateMatrix(db, false, true, true, false);
|
||||
gizmo_matrix_ = GenerateMatrix(row, false, true, true, false);
|
||||
|
||||
return true;
|
||||
|
||||
} else if (gizmo_rect_.containsPoint(p, Qt::OddEvenFill)) {
|
||||
|
||||
// Dragging the main rectangle
|
||||
gizmo_start_ = {db[kPositionInput].Get(NodeValue::kVec2)};
|
||||
gizmo_start_ = {row[kPositionInput].data()};
|
||||
gizmo_drag_ = kPositionInput;
|
||||
|
||||
return true;
|
||||
@@ -189,7 +184,7 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p)
|
||||
} else {
|
||||
|
||||
// Dragging rotation
|
||||
gizmo_start_ = {db[kRotationInput].Get(NodeValue::kFloat)};
|
||||
gizmo_start_ = {row[kRotationInput].data()};
|
||||
gizmo_drag_ = kRotationInput;
|
||||
gizmo_start_angle_ = qAtan2(gizmo_drag_pos_.y() - gizmo_anchor_pt_.center().y(),
|
||||
gizmo_drag_pos_.x() - gizmo_anchor_pt_.center().x());
|
||||
@@ -314,7 +309,7 @@ void TransformDistortNode::GizmoRelease()
|
||||
gizmo_drag_ = nullptr;
|
||||
}
|
||||
|
||||
void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
// If not connected to output, this will produce nothing
|
||||
NodeOutput out = GetConnectedOutput(kTextureInput);
|
||||
@@ -326,12 +321,12 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash,
|
||||
NodeTraverser traverser;
|
||||
traverser.SetCacheVideoParams(video_params);
|
||||
|
||||
NodeValueDatabase db = traverser.GenerateDatabase(this, output, TimeRange(time, time + video_params.frame_rate_as_time_base()));
|
||||
TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
NodeValueRow db = traverser.GenerateRow(this, output, globals.time());
|
||||
TexturePtr tex = db[kTextureInput].data().value<TexturePtr>();
|
||||
if (tex) {
|
||||
VideoParams tex_params = tex->params();
|
||||
QMatrix4x4 matrix = GenerateMatrix(db, true, false, false, false);
|
||||
matrix = GenerateAutoScaledMatrix(matrix, db, tex_params);
|
||||
matrix = GenerateAutoScaledMatrix(matrix, db, globals, tex_params);
|
||||
|
||||
if (!matrix.isIdentity()) {
|
||||
// Add fingerprint
|
||||
@@ -340,7 +335,7 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash,
|
||||
}
|
||||
}
|
||||
|
||||
out.node()->Hash(out.output(), hash, time, video_params);
|
||||
out.node()->Hash(out.output(), hash, globals, video_params);
|
||||
}
|
||||
|
||||
QMatrix4x4 TransformDistortNode::AdjustMatrixByResolutions(const QMatrix4x4 &mat, const QVector2D &sequence_res, const QVector2D &texture_res, AutoScaleType autoscale_type)
|
||||
@@ -393,11 +388,11 @@ QPointF TransformDistortNode::CreateScalePoint(double x, double y, const QPointF
|
||||
return mat.map(QPointF(x, y)) + half_res;
|
||||
}
|
||||
|
||||
QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& generated_matrix, NodeValueDatabase& value, const VideoParams& texture_params) const
|
||||
QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& generated_matrix, const NodeValueRow& value, const NodeGlobals &globals, const VideoParams& texture_params) const
|
||||
{
|
||||
QVector2D sequence_res = value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value<QVector2D>();
|
||||
const QVector2D &sequence_res = globals.resolution();
|
||||
QVector2D texture_res(texture_params.square_pixel_width(), texture_params.height());
|
||||
AutoScaleType autoscale = static_cast<AutoScaleType>(value[kAutoscaleInput].Get(NodeValue::kCombo).toInt());
|
||||
AutoScaleType autoscale = static_cast<AutoScaleType>(value[kAutoscaleInput].data().toInt());
|
||||
|
||||
return AdjustMatrixByResolutions(generated_matrix,
|
||||
sequence_res,
|
||||
@@ -405,9 +400,9 @@ QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& gene
|
||||
autoscale);
|
||||
}
|
||||
|
||||
void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
void TransformDistortNode::DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p)
|
||||
{
|
||||
TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
TexturePtr tex = row[kTextureInput].data().value<TexturePtr>();
|
||||
if (!tex) {
|
||||
return;
|
||||
}
|
||||
@@ -416,7 +411,7 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
p->setPen(QPen(Qt::white, 0));
|
||||
|
||||
// Get the sequence resolution
|
||||
QVector2D sequence_res = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value<QVector2D>();
|
||||
const QVector2D &sequence_res = globals.resolution();
|
||||
QVector2D sequence_half_res = sequence_res/2;
|
||||
QPointF sequence_half_res_pt = sequence_half_res.toPointF();
|
||||
|
||||
@@ -425,12 +420,12 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
QVector2D tex_sz(tex_params.square_pixel_width(), tex_params.height());
|
||||
|
||||
// Retrieve autoscale value
|
||||
AutoScaleType autoscale = static_cast<AutoScaleType>(db[kAutoscaleInput].Get(NodeValue::kCombo).toInt());
|
||||
AutoScaleType autoscale = static_cast<AutoScaleType>(row[kAutoscaleInput].data().toInt());
|
||||
|
||||
// Fold values into a matrix for the rectangle
|
||||
QMatrix4x4 rectangle_matrix;
|
||||
rectangle_matrix.scale(sequence_half_res);
|
||||
rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(db, false, false, false, false),
|
||||
rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false, false),
|
||||
sequence_res,
|
||||
tex_sz,
|
||||
autoscale);
|
||||
@@ -454,7 +449,7 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p)
|
||||
// Draw anchor point
|
||||
QMatrix4x4 anchor_matrix;
|
||||
anchor_matrix.scale(sequence_half_res);
|
||||
anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(db, false, true, false, false),
|
||||
anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, true, false, false),
|
||||
sequence_res,
|
||||
tex_sz,
|
||||
autoscale);
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString& shader_id) const override;
|
||||
|
||||
@@ -74,13 +74,13 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) override;
|
||||
virtual void DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p) override;
|
||||
|
||||
virtual bool GizmoPress(NodeValueDatabase& db, const QPointF &p) override;
|
||||
virtual bool GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p) override;
|
||||
virtual void GizmoMove(const QPointF &p, const rational &time) override;
|
||||
virtual void GizmoRelease() override;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
enum AutoScaleType {
|
||||
kAutoScaleNone,
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
private:
|
||||
static QPointF CreateScalePoint(double x, double y, const QPointF& half_res, const QMatrix4x4& mat);
|
||||
|
||||
QMatrix4x4 GenerateAutoScaledMatrix(const QMatrix4x4 &generated_matrix, NodeValueDatabase &db, const VideoParams &texture_params) const;
|
||||
QMatrix4x4 GenerateAutoScaledMatrix(const QMatrix4x4 &generated_matrix, const NodeValueRow &db, const NodeGlobals &globals, const VideoParams &texture_params) const;
|
||||
|
||||
// Gizmo variables
|
||||
QString gizmo_drag_;
|
||||
|
||||
@@ -87,22 +87,14 @@ ShaderCode BlurFilterNode::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/blur.frag"));
|
||||
}
|
||||
|
||||
NodeValueTable BlurFilterNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void BlurFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(this, kTextureInput, value);
|
||||
job.InsertValue(this, kMethodInput, value);
|
||||
job.InsertValue(this, kRadiusInput, value);
|
||||
job.InsertValue(this, kHorizInput, value);
|
||||
job.InsertValue(this, kVertInput, value);
|
||||
job.InsertValue(this, kRepeatEdgePixelsInput, value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"),
|
||||
NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this));
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
|
||||
// If there's no texture, no need to run an operation
|
||||
if (!job.GetValue(kTextureInput).data().isNull()) {
|
||||
@@ -121,16 +113,14 @@ NodeValueTable BlurFilterNode::Value(const QString &output, NodeValueDatabase &v
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
}
|
||||
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
|
||||
} else {
|
||||
// If we're not performing the blur job, just push the texture
|
||||
table.Push(job.GetValue(kTextureInput));
|
||||
table->Push(job.GetValue(kTextureInput));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static const QString kTextureInput;
|
||||
static const QString kMethodInput;
|
||||
|
||||
@@ -44,34 +44,28 @@ void MosaicFilterNode::Retranslate()
|
||||
SetInputName(kVertInput, tr("Vertical"));
|
||||
}
|
||||
|
||||
NodeValueTable MosaicFilterNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void MosaicFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(this, kTextureInput, value);
|
||||
job.InsertValue(this, kHorizInput, value);
|
||||
job.InsertValue(this, kVertInput, value);
|
||||
job.InsertValue(value);
|
||||
|
||||
// Mipmapping makes this look weird, so we just use bilinear for finding the color of each block
|
||||
job.SetInterpolation(kTextureInput, Texture::kLinear);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!job.GetValue(kTextureInput).data().isNull()) {
|
||||
TexturePtr texture = job.GetValue(kTextureInput).data().value<TexturePtr>();
|
||||
|
||||
if (texture
|
||||
&& job.GetValue(kHorizInput).data().toInt() != texture->width()
|
||||
&& job.GetValue(kVertInput).data().toInt() != texture->height()) {
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
table.Push(job.GetValue(kTextureInput));
|
||||
table->Push(job.GetValue(kTextureInput));
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
ShaderCode MosaicFilterNode::GetShaderCode(const QString &shader_id) const
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
|
||||
static const QString kTextureInput;
|
||||
|
||||
@@ -82,32 +82,23 @@ void StrokeFilterNode::Retranslate()
|
||||
SetInputName(kInnerInput, tr("Inner"));
|
||||
}
|
||||
|
||||
NodeValueTable StrokeFilterNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void StrokeFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(this, kTextureInput, value);
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
job.InsertValue(this, kRadiusInput, value);
|
||||
job.InsertValue(this, kOpacityInput, value);
|
||||
job.InsertValue(this, kInnerInput, value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"),
|
||||
NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this));
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
|
||||
if (!job.GetValue(kTextureInput).data().isNull()) {
|
||||
if (job.GetValue(kRadiusInput).data().toDouble() > 0.0
|
||||
&& job.GetValue(kOpacityInput).data().toDouble() > 0.0) {
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
table.Push(job.GetValue(kTextureInput));
|
||||
table->Push(job.GetValue(kTextureInput));
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
ShaderCode StrokeFilterNode::GetShaderCode(const QString &shader_id) const
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
|
||||
static const QString kTextureInput;
|
||||
|
||||
@@ -88,18 +88,16 @@ void MatrixGenerator::Retranslate()
|
||||
SetInputName(kAnchorInput, tr("Anchor Point"));
|
||||
}
|
||||
|
||||
NodeValueTable MatrixGenerator::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void MatrixGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
// Push matrix output
|
||||
QMatrix4x4 mat = GenerateMatrix(value, true, false, false, false);
|
||||
NodeValueTable out = value.Merge();
|
||||
out.Push(NodeValue::kMatrix, mat, this);
|
||||
return out;
|
||||
table->Push(NodeValue::kMatrix, mat, this);
|
||||
}
|
||||
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const
|
||||
{
|
||||
QVector2D anchor;
|
||||
QVector2D position;
|
||||
@@ -108,47 +106,47 @@ QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value, bool take,
|
||||
if (!ignore_anchor) {
|
||||
if (take) {
|
||||
// Take and store
|
||||
anchor = value[kAnchorInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
anchor = value[kAnchorInput].data().value<QVector2D>();
|
||||
} else {
|
||||
// Get and store
|
||||
anchor = value[kAnchorInput].Get(NodeValue::kVec2).value<QVector2D>();
|
||||
anchor = value[kAnchorInput].data().value<QVector2D>();
|
||||
}
|
||||
} else if (take) {
|
||||
// Just take
|
||||
value[kAnchorInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
value[kAnchorInput].data().value<QVector2D>();
|
||||
}
|
||||
|
||||
if (!ignore_scale) {
|
||||
if (take) {
|
||||
scale = value[kScaleInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
scale = value[kScaleInput].data().value<QVector2D>();
|
||||
} else {
|
||||
scale = value[kScaleInput].Get(NodeValue::kVec2).value<QVector2D>();
|
||||
scale = value[kScaleInput].data().value<QVector2D>();
|
||||
}
|
||||
} else if (take) {
|
||||
value[kScaleInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
value[kScaleInput].data().value<QVector2D>();
|
||||
}
|
||||
|
||||
if (!ignore_position) {
|
||||
if (take) {
|
||||
position = value[kPositionInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
position = value[kPositionInput].data().value<QVector2D>();
|
||||
} else {
|
||||
position = value[kPositionInput].Get(NodeValue::kVec2).value<QVector2D>();
|
||||
position = value[kPositionInput].data().value<QVector2D>();
|
||||
}
|
||||
} else if (take) {
|
||||
value[kPositionInput].Take(NodeValue::kVec2).value<QVector2D>();
|
||||
value[kPositionInput].data().value<QVector2D>();
|
||||
}
|
||||
|
||||
if (take) {
|
||||
return GenerateMatrix(position,
|
||||
value[kRotationInput].Take(NodeValue::kFloat).toFloat(),
|
||||
value[kRotationInput].data().toFloat(),
|
||||
scale,
|
||||
value[kUniformScaleInput].Take(NodeValue::kBoolean).toBool(),
|
||||
value[kUniformScaleInput].data().toBool(),
|
||||
anchor);
|
||||
} else {
|
||||
return GenerateMatrix(position,
|
||||
value[kRotationInput].Get(NodeValue::kFloat).toFloat(),
|
||||
value[kRotationInput].data().toFloat(),
|
||||
scale,
|
||||
value[kUniformScaleInput].Get(NodeValue::kBoolean).toBool(),
|
||||
value[kUniformScaleInput].data().toBool(),
|
||||
anchor);
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static const QString kPositionInput;
|
||||
static const QString kRotationInput;
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
static const QString kAnchorInput;
|
||||
|
||||
protected:
|
||||
QMatrix4x4 GenerateMatrix(NodeValueDatabase &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const;
|
||||
QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const;
|
||||
static QMatrix4x4 GenerateMatrix(const QVector2D &pos,
|
||||
const float &rot,
|
||||
const QVector2D &scale,
|
||||
|
||||
@@ -86,20 +86,17 @@ ShaderCode PolygonGenerator::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/polygon.frag")));
|
||||
}
|
||||
|
||||
NodeValueTable PolygonGenerator::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void PolygonGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(this, kPointsInput, value);
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), value[QStringLiteral("global")].GetWithMeta(NodeValue::kVec2, QStringLiteral("resolution")));
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
return table;
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
bool PolygonGenerator::HasGizmos() const
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString& shader_id) const override;
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual bool HasGizmos() const override;
|
||||
//virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) const override;
|
||||
|
||||
@@ -68,22 +68,17 @@ ShaderCode ShapeNode::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/shape.frag")));
|
||||
}
|
||||
|
||||
NodeValueTable ShapeNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void ShapeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(this, kTypeInput, value);
|
||||
job.InsertValue(this, kPositionInput, value);
|
||||
job.InsertValue(this, kSizeInput, value);
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), value[QStringLiteral("global")].GetWithMeta(NodeValue::kVec2, QStringLiteral("resolution")));
|
||||
job.InsertValue(value);
|
||||
job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
return table;
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString& shader_id) const override;
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static QString kTypeInput;
|
||||
|
||||
|
||||
@@ -62,16 +62,13 @@ void SolidGenerator::Retranslate()
|
||||
SetInputName(kColorInput, tr("Color"));
|
||||
}
|
||||
|
||||
NodeValueTable SolidGenerator::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void SolidGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
return table;
|
||||
job.InsertValue(value);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
ShaderCode SolidGenerator::GetShaderCode(const QString &shader_id) const
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
|
||||
static const QString kColorInput;
|
||||
|
||||
@@ -89,26 +89,17 @@ void TextGenerator::Retranslate()
|
||||
SetComboBoxStrings(kVAlignInput, {tr("Top"), tr("Center"), tr("Bottom")});
|
||||
}
|
||||
|
||||
NodeValueTable TextGenerator::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void TextGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
GenerateJob job;
|
||||
job.InsertValue(this, kTextInput, value);
|
||||
job.InsertValue(this, kHtmlInput, value);
|
||||
job.InsertValue(this, kColorInput, value);
|
||||
job.InsertValue(this, kVAlignInput, value);
|
||||
job.InsertValue(this, kFontInput, value);
|
||||
job.InsertValue(this, kFontSizeInput, value);
|
||||
job.InsertValue(value);
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!job.GetValue(kTextInput).data().toString().isEmpty()) {
|
||||
table.Push(NodeValue::kGenerateJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kGenerateJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void TextGenerator::GenerateFrame(FramePtr frame, const GenerateJob& job) const
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODEGLOBALS_H
|
||||
#define NODEGLOBALS_H
|
||||
|
||||
#include <QVector2D>
|
||||
|
||||
#include "common/timerange.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeGlobals
|
||||
{
|
||||
public:
|
||||
NodeGlobals(const QVector2D &resolution, const TimeRange &time) :
|
||||
resolution_(resolution),
|
||||
time_(time)
|
||||
{}
|
||||
|
||||
const QVector2D &resolution() const
|
||||
{
|
||||
return resolution_;
|
||||
}
|
||||
|
||||
const TimeRange &time() const
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
void set_time(const TimeRange &time)
|
||||
{
|
||||
time_ = time;
|
||||
}
|
||||
|
||||
private:
|
||||
QVector2D resolution_;
|
||||
|
||||
TimeRange time_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // NODEGLOBALS_H
|
||||
@@ -51,27 +51,23 @@ QString TimeInput::Description() const
|
||||
return tr("Generates the time (in seconds) at this frame.");
|
||||
}
|
||||
|
||||
NodeValueTable TimeInput::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void TimeInput::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
table.Push(NodeValue::kFloat,
|
||||
value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")),
|
||||
this,
|
||||
false,
|
||||
QStringLiteral("time"));
|
||||
|
||||
return table;
|
||||
table->Push(NodeValue::kFloat,
|
||||
globals.time().in().toDouble(),
|
||||
this,
|
||||
false,
|
||||
QStringLiteral("time"));
|
||||
}
|
||||
|
||||
void TimeInput::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void TimeInput::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
Node::Hash(output, hash, time, video_params);
|
||||
Node::Hash(output, hash, globals, video_params);
|
||||
|
||||
// Make sure time is hashed
|
||||
hash.addData(NodeValue::ValueToBytes(NodeValue::kRational, QVariant::fromValue(time)));
|
||||
hash.addData(NodeValue::ValueToBytes(NodeValue::kFloat, globals.time().in().toDouble()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ public:
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const rational& time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -59,14 +59,13 @@ void ValueNode::Retranslate()
|
||||
SetComboBoxStrings(kTypeInput, type_names);
|
||||
}
|
||||
|
||||
NodeValueTable ValueNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void ValueNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(globals)
|
||||
Q_UNUSED(output)
|
||||
|
||||
// Pop combobox value off table because no other node will need it
|
||||
value[kTypeInput].Take(NodeValue::kCombo);
|
||||
|
||||
return value.Merge();
|
||||
// Ensure value is pushed onto the table
|
||||
table->Push(value[kValueInput]);
|
||||
}
|
||||
|
||||
void ValueNode::InputValueChangedEvent(const QString &input, int element)
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString &output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString &input, int element) override;
|
||||
|
||||
+13
-15
@@ -88,35 +88,33 @@ ShaderCode MathNode::GetShaderCode(const QString &shader_id) const
|
||||
return GetShaderCodeInternal(shader_id, kParamAIn, kParamBIn);
|
||||
}
|
||||
|
||||
NodeValueTable MathNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void MathNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
// Auto-detect what values to operate with
|
||||
// FIXME: Add manual override for this
|
||||
PairingCalculator calc(value[kParamAIn], value[kParamBIn]);
|
||||
// FIXME: Very inefficient
|
||||
NodeValueTable at, bt;
|
||||
at.Push(value[kParamAIn]);
|
||||
bt.Push(value[kParamBIn]);
|
||||
PairingCalculator calc(at, bt);
|
||||
|
||||
// Do nothing if no pairing was found
|
||||
if (!calc.FoundMostLikelyPairing()) {
|
||||
return value.Merge();
|
||||
return;
|
||||
}
|
||||
|
||||
NodeValue val_a = calc.GetMostLikelyValueA();
|
||||
value[kParamAIn].Remove(val_a);
|
||||
|
||||
NodeValue val_b = calc.GetMostLikelyValueB();
|
||||
value[kParamBIn].Remove(val_b);
|
||||
|
||||
return ValueInternal(value,
|
||||
GetOperation(),
|
||||
return ValueInternal(GetOperation(),
|
||||
calc.GetMostLikelyPairing(),
|
||||
kParamAIn,
|
||||
val_a,
|
||||
calc.GetMostLikelyValueA(),
|
||||
kParamBIn,
|
||||
val_b);
|
||||
calc.GetMostLikelyValueB(),
|
||||
globals,
|
||||
table);
|
||||
}
|
||||
|
||||
void MathNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void MathNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
return ProcessSamplesInternal(values, GetOperation(), kParamAIn, kParamBIn, input, output, index);
|
||||
}
|
||||
|
||||
@@ -54,9 +54,9 @@ public:
|
||||
SetStandardValue(kMethodIn, o);
|
||||
}
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
static const QString kMethodIn;
|
||||
static const QString kParamAIn;
|
||||
|
||||
@@ -163,21 +163,19 @@ void MathNodeBase::PushVector(NodeValueTable *output, olive::NodeValue::Type typ
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue& val_a, const QString& param_b_in, const NodeValue& val_b) const
|
||||
void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue& val_a, const QString& param_b_in, const NodeValue& val_b, const NodeGlobals &globals, NodeValueTable *output) const
|
||||
{
|
||||
NodeValueTable output = value.Merge();
|
||||
|
||||
switch (pairing) {
|
||||
|
||||
case kPairNumberNumber:
|
||||
{
|
||||
if (val_a.type() == NodeValue::kRational && val_b.type() == NodeValue::kRational && operation != kOpPower) {
|
||||
// Preserve rationals
|
||||
output.Push(NodeValue::kRational,
|
||||
output->Push(NodeValue::kRational,
|
||||
QVariant::fromValue(PerformAddSubMultDiv<rational, rational>(operation, val_a.data().value<rational>(), val_b.data().value<rational>())),
|
||||
this);
|
||||
} else {
|
||||
output.Push(NodeValue::kFloat,
|
||||
output->Push(NodeValue::kFloat,
|
||||
PerformAll<float, float>(operation, RetrieveNumber(val_a), RetrieveNumber(val_b)),
|
||||
this);
|
||||
}
|
||||
@@ -188,7 +186,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
{
|
||||
// We convert all vectors to QVector4D just for simplicity and exploit the fact that kVec4 is higher than kVec2 in
|
||||
// the enum to find the largest data type
|
||||
PushVector(&output,
|
||||
PushVector(output,
|
||||
qMax(val_a.type(), val_b.type()),
|
||||
PerformAddSubMultDiv<QVector4D, QVector4D>(operation, RetrieveVector(val_a), RetrieveVector(val_b)));
|
||||
break;
|
||||
@@ -200,7 +198,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
QVector4D vec = (val_a.type() == NodeValue::kMatrix) ? RetrieveVector(val_b) : RetrieveVector(val_a);
|
||||
|
||||
// Only valid operation is multiply
|
||||
PushVector(&output,
|
||||
PushVector(output,
|
||||
qMax(val_a.type(), val_b.type()),
|
||||
PerformMult<QVector4D, QMatrix4x4>(operation, vec, matrix));
|
||||
break;
|
||||
@@ -212,7 +210,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
float number = RetrieveNumber((val_a.type() & NodeValue::kMatrix) ? val_b : val_a);
|
||||
|
||||
// Only multiply and divide are valid operations
|
||||
PushVector(&output, val_a.type(), PerformMultDiv<QVector4D, float>(operation, vec, number));
|
||||
PushVector(output, val_a.type(), PerformMultDiv<QVector4D, float>(operation, vec, number));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -220,7 +218,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
{
|
||||
QMatrix4x4 mat_a = val_a.data().value<QMatrix4x4>();
|
||||
QMatrix4x4 mat_b = val_b.data().value<QMatrix4x4>();
|
||||
output.Push(NodeValue::kMatrix, PerformAddSubMult<QMatrix4x4, QMatrix4x4>(operation, mat_a, mat_b), this);
|
||||
output->Push(NodeValue::kMatrix, PerformAddSubMult<QMatrix4x4, QMatrix4x4>(operation, mat_a, mat_b), this);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -230,7 +228,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
Color col_b = val_b.data().value<Color>();
|
||||
|
||||
// Only add and subtract are valid operations
|
||||
output.Push(NodeValue::kColor, QVariant::fromValue(PerformAddSub<Color, Color>(operation, col_a, col_b)), this);
|
||||
output->Push(NodeValue::kColor, QVariant::fromValue(PerformAddSub<Color, Color>(operation, col_a, col_b)), this);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -241,7 +239,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
float num = (val_a.type() == NodeValue::kColor) ? val_b.data().toFloat() : val_a.data().toFloat();
|
||||
|
||||
// Only multiply and divide are valid operations
|
||||
output.Push(NodeValue::kColor, QVariant::fromValue(PerformMult<Color, float>(operation, col, num)), this);
|
||||
output->Push(NodeValue::kColor, QVariant::fromValue(PerformMult<Color, float>(operation, col, num)), this);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -275,7 +273,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
}
|
||||
}
|
||||
|
||||
output.Push(NodeValue::kSamples, QVariant::fromValue(mixed_samples), this);
|
||||
output->Push(NodeValue::kSamples, QVariant::fromValue(mixed_samples), this);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -307,7 +305,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
}
|
||||
} else if (pairing == kPairTextureMatrix) {
|
||||
// Only allow matrix multiplication
|
||||
QVector2D sequence_res = value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value<QVector2D>();
|
||||
const QVector2D &sequence_res = globals.resolution();
|
||||
QVector2D texture_res(texture->params().width() * texture->pixel_aspect_ratio().toDouble(), texture->params().height());
|
||||
|
||||
QMatrix4x4 adjusted_matrix = TransformDistortNode::AdjustMatrixByResolutions(number_val.data().value<QMatrix4x4>(),
|
||||
@@ -328,10 +326,10 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
|
||||
if (operation_is_noop) {
|
||||
// Just push texture as-is
|
||||
output.Push(texture_val);
|
||||
output->Push(texture_val);
|
||||
} else {
|
||||
// Push shader job
|
||||
output.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
output->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -357,9 +355,9 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
}
|
||||
}
|
||||
|
||||
output.Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this);
|
||||
output->Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this);
|
||||
} else {
|
||||
output.Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
output->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -369,17 +367,15 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o
|
||||
case kPairCount:
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void MathNodeBase::ProcessSamplesInternal(NodeValueDatabase &values, MathNodeBase::Operation operation, const QString ¶m_a_in, const QString ¶m_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBase::Operation operation, const QString ¶m_a_in, const QString ¶m_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
// This function is only used for sample+number pairing
|
||||
NodeValue number_val = values[param_a_in].GetWithMeta(NodeValue::kNumber);
|
||||
NodeValue number_val = values[param_a_in];
|
||||
|
||||
if (number_val.type() == NodeValue::kNone) {
|
||||
number_val = values[param_b_in].GetWithMeta(NodeValue::kNumber);
|
||||
number_val = values[param_b_in];
|
||||
|
||||
if (number_val.type() == NodeValue::kNone) {
|
||||
return;
|
||||
@@ -460,8 +456,6 @@ MathNodeBase::PairingCalculator::PairingCalculator(const NodeValueTable &table_a
|
||||
|
||||
QVector<int> MathNodeBase::PairingCalculator::GetPairLikelihood(const NodeValueTable &table)
|
||||
{
|
||||
// FIXME: When we introduce a manual override, placing it here would be the least problematic
|
||||
|
||||
QVector<int> likelihood(kPairCount, -1);
|
||||
|
||||
for (int i=0;i<table.Count();i++) {
|
||||
|
||||
@@ -115,9 +115,9 @@ protected:
|
||||
|
||||
void PushVector(NodeValueTable* output, NodeValue::Type type, const QVector4D& vec) const;
|
||||
|
||||
NodeValueTable ValueInternal(NodeValueDatabase &value, Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue &val_a, const QString& param_b_in, const NodeValue& val_b) const;
|
||||
void ValueInternal(Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue &val_a, const QString& param_b_in, const NodeValue& val_b, const NodeGlobals &globals, NodeValueTable *output) const;
|
||||
|
||||
void ProcessSamplesInternal(NodeValueDatabase &values, Operation operation, const QString& param_a_in, const QString& param_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
void ProcessSamplesInternal(const NodeValueRow &values, Operation operation, const QString& param_a_in, const QString& param_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -73,15 +73,12 @@ ShaderCode MergeNode::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/alphaover.frag"));
|
||||
}
|
||||
|
||||
NodeValueTable MergeNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void MergeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
ShaderJob job;
|
||||
job.InsertValue(this, kBaseIn, value);
|
||||
job.InsertValue(this, kBlendIn, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
job.InsertValue(value);
|
||||
|
||||
TexturePtr base_tex = job.GetValue(kBaseIn).data().value<TexturePtr>();
|
||||
TexturePtr blend_tex = job.GetValue(kBlendIn).data().value<TexturePtr>();
|
||||
@@ -89,10 +86,10 @@ NodeValueTable MergeNode::Value(const QString &output, NodeValueDatabase &value)
|
||||
if (base_tex || blend_tex) {
|
||||
if (!base_tex || (blend_tex && blend_tex->channel_count() < VideoParams::kRGBAChannelCount)) {
|
||||
// We only have a blend texture or the blend texture is RGB only, no need to alpha over
|
||||
table.Push(job.GetValue(kBlendIn));
|
||||
table->Push(job.GetValue(kBlendIn));
|
||||
} else if (!blend_tex) {
|
||||
// We only have a base texture, no need to alpha over
|
||||
table.Push(job.GetValue(kBaseIn));
|
||||
table->Push(job.GetValue(kBaseIn));
|
||||
} else {
|
||||
// We have both textures, push the job
|
||||
if (base_tex->channel_count() < VideoParams::kRGBAChannelCount) {
|
||||
@@ -100,19 +97,17 @@ NodeValueTable MergeNode::Value(const QString &output, NodeValueDatabase &value)
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOff);
|
||||
}
|
||||
|
||||
table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
NodeTraverser traverser;
|
||||
traverser.SetCacheVideoParams(video_params);
|
||||
|
||||
NodeValueDatabase db = traverser.GenerateDatabase(this, output, TimeRange(time, time+video_params.frame_rate_as_time_base()));
|
||||
NodeValueDatabase db = traverser.GenerateDatabase(this, output, globals.time());
|
||||
|
||||
TexturePtr base_tex = db[kBaseIn].Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
TexturePtr blend_tex = db[kBlendIn].Get(NodeValue::kTexture).value<TexturePtr>();
|
||||
@@ -128,12 +123,12 @@ void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const rati
|
||||
|
||||
if (!passthrough_base) {
|
||||
NodeOutput blend_output = GetConnectedOutput(kBlendIn);
|
||||
blend_output.node()->Hash(blend_output.output(), hash, time, video_params);
|
||||
blend_output.node()->Hash(blend_output.output(), hash, globals, video_params);
|
||||
}
|
||||
|
||||
if (!passthrough_blend) {
|
||||
NodeOutput base_output = GetConnectedOutput(kBaseIn);
|
||||
base_output.node()->Hash(base_output.output(), hash, time, video_params);
|
||||
base_output.node()->Hash(base_output.output(), hash, globals, video_params);
|
||||
}
|
||||
|
||||
Q_ASSERT(!passthrough_base || !passthrough_blend);
|
||||
|
||||
@@ -43,12 +43,12 @@ public:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QString &shader_id) const override;
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static const QString kBaseIn;
|
||||
static const QString kBlendIn;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
private:
|
||||
NodeInput* base_in_;
|
||||
|
||||
@@ -76,13 +76,11 @@ void TrigonometryNode::Retranslate()
|
||||
SetInputName(kMethodIn, tr("Method"));
|
||||
}
|
||||
|
||||
NodeValueTable TrigonometryNode::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void TrigonometryNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
float x = value[kXIn].Take(NodeValue::kFloat).toFloat();
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
double x = value[kXIn].data().toFloat();
|
||||
|
||||
switch (static_cast<Operation>(GetStandardValue(kMethodIn).toInt())) {
|
||||
case kOpSine:
|
||||
@@ -114,9 +112,7 @@ NodeValueTable TrigonometryNode::Value(const QString &output, NodeValueDatabase
|
||||
break;
|
||||
}
|
||||
|
||||
table.Push(NodeValue::kFloat, x, this);
|
||||
|
||||
return table;
|
||||
table->Push(NodeValue::kFloat, x, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override;
|
||||
virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static const QString kMethodIn;
|
||||
static const QString kXIn;
|
||||
|
||||
+18
-16
@@ -43,16 +43,14 @@ namespace olive {
|
||||
|
||||
const QString Node::kDefaultOutput = QStringLiteral("output");
|
||||
|
||||
Node::Node(bool create_default_output) :
|
||||
Node::Node() :
|
||||
can_be_deleted_(true),
|
||||
override_color_(-1),
|
||||
folder_(nullptr),
|
||||
operation_stack_(0),
|
||||
cache_result_(false)
|
||||
{
|
||||
if (create_default_output) {
|
||||
AddOutput();
|
||||
}
|
||||
AddOutput();
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
@@ -1015,11 +1013,13 @@ Node::InputFlags Node::GetInputFlags(const QString &input) const
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable Node::Value(const QString& output, NodeValueDatabase &value) const
|
||||
void Node::Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
// Do nothing
|
||||
Q_UNUSED(output)
|
||||
|
||||
return value.Merge();
|
||||
Q_UNUSED(value)
|
||||
Q_UNUSED(globals)
|
||||
Q_UNUSED(table)
|
||||
}
|
||||
|
||||
void Node::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options)
|
||||
@@ -1422,11 +1422,11 @@ bool Node::HasGizmos() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void Node::DrawGizmos(NodeValueDatabase &, QPainter *)
|
||||
void Node::DrawGizmos(const NodeValueRow &, const NodeGlobals &, QPainter *)
|
||||
{
|
||||
}
|
||||
|
||||
bool Node::GizmoPress(NodeValueDatabase &, const QPointF &)
|
||||
bool Node::GizmoPress(const NodeValueRow &, const NodeGlobals &, const QPointF &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1453,7 +1453,7 @@ void Node::SetLabel(const QString &s)
|
||||
}
|
||||
}
|
||||
|
||||
void Node::Hash(const QString &output, QCryptographicHash &hash, const rational& time, const VideoParams &video_params) const
|
||||
void Node::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
// Add this Node's ID and output being used
|
||||
HashAddNodeSignature(hash, output);
|
||||
@@ -1467,7 +1467,7 @@ void Node::Hash(const QString &output, QCryptographicHash &hash, const rational&
|
||||
|
||||
int arr_sz = InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
HashInputElement(hash, input, i, time, video_params);
|
||||
HashInputElement(hash, input, i, globals, video_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1589,20 +1589,22 @@ QVector<Node *> Node::GetDependenciesInternal(bool traverse, bool exclusive_only
|
||||
return list;
|
||||
}
|
||||
|
||||
void Node::HashInputElement(QCryptographicHash &hash, const QString& input, int element, const rational &time, const VideoParams& video_params) const
|
||||
void Node::HashInputElement(QCryptographicHash &hash, const QString& input, int element, const NodeGlobals &globals, const VideoParams& video_params) const
|
||||
{
|
||||
// Get time adjustment
|
||||
// For a single frame, we only care about one of the times
|
||||
rational input_time = InputTimeAdjustment(input, element, TimeRange(time, time)).in();
|
||||
TimeRange input_time = InputTimeAdjustment(input, element, globals.time());
|
||||
|
||||
if (IsInputConnected(input, element)) {
|
||||
// Traverse down this edge
|
||||
NodeOutput output = GetConnectedOutput(input, element);
|
||||
|
||||
output.node()->Hash(output.output(), hash, input_time, video_params);
|
||||
NodeGlobals new_globals = globals;
|
||||
new_globals.set_time(input_time);
|
||||
output.node()->Hash(output.output(), hash, new_globals, video_params);
|
||||
} else {
|
||||
// Grab the value at this time
|
||||
QVariant value = GetValueAtTime(input, input_time, element);
|
||||
QVariant value = GetValueAtTime(input, input_time.in(), element);
|
||||
hash.addData(NodeValue::ValueToBytes(GetInputDataType(input), value));
|
||||
}
|
||||
}
|
||||
@@ -1629,7 +1631,7 @@ ShaderCode Node::GetShaderCode(const QString &shader_id) const
|
||||
return ShaderCode(QString(), QString());
|
||||
}
|
||||
|
||||
void Node::ProcessSamples(NodeValueDatabase &, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
void Node::ProcessSamples(const NodeValueRow &, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+26
-7
@@ -34,6 +34,7 @@
|
||||
#include "common/rational.h"
|
||||
#include "common/timerange.h"
|
||||
#include "common/xmlutils.h"
|
||||
#include "node/globals.h"
|
||||
#include "node/keyframe.h"
|
||||
#include "node/inputimmediate.h"
|
||||
#include "node/param.h"
|
||||
@@ -92,7 +93,7 @@ public:
|
||||
kCategoryCount
|
||||
};
|
||||
|
||||
Node(bool create_default_output = true);
|
||||
Node();
|
||||
|
||||
virtual ~Node() override;
|
||||
|
||||
@@ -487,6 +488,22 @@ public:
|
||||
|
||||
int InputArraySize(const QString& id) const;
|
||||
|
||||
struct ValueHint {
|
||||
QVector<NodeValue::Type> type;
|
||||
int index = -1;
|
||||
QString tag;
|
||||
};
|
||||
|
||||
ValueHint GetValueHintForInput(const QString &input) const
|
||||
{
|
||||
return value_hints_.value(input);
|
||||
}
|
||||
|
||||
void SetValueHintForInput(const QString &input, const ValueHint &hint)
|
||||
{
|
||||
value_hints_.insert(input, hint);
|
||||
}
|
||||
|
||||
const NodeKeyframeTrack& GetTrackFromKeyframe(NodeKeyframe* key) const;
|
||||
|
||||
using InputConnections = std::map<NodeInput, NodeOutput>;
|
||||
@@ -542,7 +559,7 @@ public:
|
||||
/**
|
||||
* @brief If Value() pushes a ShaderJob, this is the function that will process them.
|
||||
*/
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
|
||||
/**
|
||||
* @brief If Value() pushes a GenerateJob, override this function for the image to create
|
||||
@@ -722,20 +739,20 @@ public:
|
||||
* corresponding output if it's connected to one. If your node doesn't directly deal with time, the default behavior
|
||||
* of the NodeParam objects will handle everything related to it automatically.
|
||||
*/
|
||||
virtual NodeValueTable Value(const QString &output, NodeValueDatabase& value) const;
|
||||
virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const;
|
||||
|
||||
virtual bool HasGizmos() const;
|
||||
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter* p);
|
||||
virtual void DrawGizmos(const NodeValueRow& row, const NodeGlobals &globals, QPainter* p);
|
||||
|
||||
virtual bool GizmoPress(NodeValueDatabase& db, const QPointF& p);
|
||||
virtual bool GizmoPress(const NodeValueRow& row, const NodeGlobals &globals, const QPointF& p);
|
||||
virtual void GizmoMove(const QPointF& p, const rational &time);
|
||||
virtual void GizmoRelease();
|
||||
|
||||
const QString& GetLabel() const;
|
||||
void SetLabel(const QString& s);
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const;
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const;
|
||||
|
||||
void InvalidateAll(const QString& input, int element = -1);
|
||||
|
||||
@@ -1151,7 +1168,7 @@ private:
|
||||
|
||||
QVector<Node*> GetDependenciesInternal(bool traverse, bool exclusive_only) const;
|
||||
|
||||
void HashInputElement(QCryptographicHash& hash, const QString &input, int element, const rational& time, const VideoParams &video_params) const;
|
||||
void HashInputElement(QCryptographicHash& hash, const QString &input, int element, const NodeGlobals &globals, const VideoParams &video_params) const;
|
||||
|
||||
void ParameterValueChanged(const QString &input, int element, const olive::TimeRange &range);
|
||||
void ParameterValueChanged(const NodeInput& input, const olive::TimeRange &range)
|
||||
@@ -1220,6 +1237,8 @@ private:
|
||||
|
||||
bool cache_result_;
|
||||
|
||||
QMap<QString, ValueHint> value_hints_;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
|
||||
|
||||
@@ -580,15 +580,17 @@ bool Track::IsLocked() const
|
||||
return locked_;
|
||||
}
|
||||
|
||||
void Track::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void Track::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
|
||||
Block* b = BlockAtTime(time);
|
||||
Block* b = BlockAtTime(globals.time().in());
|
||||
|
||||
// Defer to block at this time, don't add any of our own information to the hash
|
||||
if (b) {
|
||||
b->Hash(kDefaultOutput, hash, TransformTimeForBlock(b, time), video_params);
|
||||
NodeGlobals new_globals = globals;
|
||||
new_globals.set_time(TransformRangeForBlock(b, globals.time()));
|
||||
b->Hash(kDefaultOutput, hash, new_globals, video_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ public:
|
||||
|
||||
bool IsLocked() const;
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
static const double kTrackHeightDefault;
|
||||
static const double kTrackHeightMinimum;
|
||||
|
||||
@@ -546,23 +546,6 @@ int ViewerOutput::AddStream(Track::Type type, const QVariant& value)
|
||||
return index;
|
||||
}
|
||||
|
||||
void ViewerOutput::InputResized(const QString &input, int old_size, int new_size)
|
||||
{
|
||||
if (input == kVideoParamsInput || input == kAudioParamsInput) {
|
||||
Track::Type type = (input == kVideoParamsInput) ? Track::kVideo : Track::kAudio;
|
||||
|
||||
if (new_size > old_size) {
|
||||
for (int i=old_size; i<new_size; i++) {
|
||||
AddOutput(Track::Reference(type, i).ToString());
|
||||
}
|
||||
} else if (new_size < old_size) {
|
||||
for (int i=new_size; i<old_size; i++) {
|
||||
RemoveOutput(Track::Reference(type, i).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<VideoParams> ViewerOutput::GetEnabledVideoStreams() const
|
||||
{
|
||||
QVector<VideoParams> streams;
|
||||
|
||||
@@ -245,9 +245,6 @@ private:
|
||||
bool video_cache_enabled_;
|
||||
bool audio_cache_enabled_;
|
||||
|
||||
private slots:
|
||||
void InputResized(const QString& input, int old_size, int new_size);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -323,9 +323,9 @@ QString Footage::DescribeAudioStream(const AudioParams ¶ms)
|
||||
QString::number(params.sample_rate()));
|
||||
}
|
||||
|
||||
void Footage::Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void Footage::Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
super::Hash(output, hash, time, video_params);
|
||||
super::Hash(output, hash, globals, video_params);
|
||||
|
||||
// Footage last modified date
|
||||
hash.addData(QString::number(timestamp()).toUtf8());
|
||||
@@ -356,7 +356,7 @@ void Footage::Hash(const QString& output, QCryptographicHash &hash, const ration
|
||||
|
||||
// Footage timestamp
|
||||
if (params.video_type() != VideoParams::kVideoTypeStill) {
|
||||
rational adjusted_time = AdjustTimeByLoopMode(time, loop_mode(), GetLength(), params.video_type(), params.frame_rate_as_time_base());
|
||||
rational adjusted_time = AdjustTimeByLoopMode(globals.time().in(), loop_mode(), GetLength(), params.video_type(), params.frame_rate_as_time_base());
|
||||
|
||||
if (!adjusted_time.isNaN()) {
|
||||
int64_t video_ts = Timecode::time_to_timestamp(adjusted_time, params.time_base());
|
||||
@@ -374,17 +374,16 @@ void Footage::Hash(const QString& output, QCryptographicHash &hash, const ration
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable Footage::Value(const QString &output, NodeValueDatabase &value) const
|
||||
void Footage::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
Q_UNUSED(globals)
|
||||
|
||||
Track::Reference ref = Track::Reference::FromString(output);
|
||||
|
||||
// Pop filename from table
|
||||
QString file = value[kFilenameInput].Take(NodeValue::kFile).toString();
|
||||
QString file = value[kFilenameInput].data().toString();
|
||||
|
||||
LoopMode loop_mode = static_cast<LoopMode>(value[kLoopModeInput].Take(NodeValue::kCombo).toInt());
|
||||
|
||||
// Merge table
|
||||
NodeValueTable table = value.Merge();
|
||||
LoopMode loop_mode = static_cast<LoopMode>(value[kLoopModeInput].data().toInt());
|
||||
|
||||
// If the file exists and the reference is valid, push a footage job to the renderer
|
||||
if (QFileInfo(file).exists()) {
|
||||
@@ -403,11 +402,9 @@ NodeValueTable Footage::Value(const QString &output, NodeValueDatabase &value) c
|
||||
job.set_cache_path(project()->cache_path());
|
||||
}
|
||||
|
||||
table.Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length"));
|
||||
table.Push(NodeValue::kFootageJob, QVariant::fromValue(job), this);
|
||||
table->Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length"));
|
||||
table->Push(NodeValue::kFootageJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
QString Footage::GetStreamTypeName(Track::Type type)
|
||||
|
||||
@@ -181,9 +181,9 @@ public:
|
||||
static QString DescribeVideoStream(const VideoParams& params);
|
||||
static QString DescribeAudioStream(const AudioParams& params);
|
||||
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
virtual NodeValueTable Value(const QString &output, NodeValueDatabase& value) const override;
|
||||
virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static QString GetStreamTypeName(Track::Type type);
|
||||
|
||||
|
||||
@@ -98,13 +98,16 @@ QVector<QString> TimeRemapNode::inputs_for_output(const QString &output) const
|
||||
return {kInputInput};
|
||||
}
|
||||
|
||||
void TimeRemapNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const
|
||||
void TimeRemapNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
// Don't hash anything of our own, just pass-through to the connected node at the remapped tmie
|
||||
Q_UNUSED(output)
|
||||
if (IsInputConnected(kInputInput)) {
|
||||
NodeOutput out = GetConnectedOutput(kInputInput);
|
||||
out.node()->Hash(out.output(), hash, GetRemappedTime(time), video_params);
|
||||
|
||||
NodeGlobals new_globals = globals;
|
||||
new_globals.set_time(TimeRange(GetRemappedTime(globals.time().in()), GetRemappedTime(globals.time().out())));
|
||||
out.node()->Hash(out.output(), hash, new_globals, video_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
virtual QVector<QString> inputs_for_output(const QString &output) const override;
|
||||
|
||||
virtual void Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override;
|
||||
virtual void Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override;
|
||||
|
||||
static const QString kTimeInput;
|
||||
static const QString kInputInput;
|
||||
|
||||
+66
-15
@@ -40,11 +40,65 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const QStrin
|
||||
database.Insert(input, ProcessInput(node, input, range));
|
||||
}
|
||||
|
||||
AddGlobalsToDatabase(database, range);
|
||||
|
||||
return database;
|
||||
}
|
||||
|
||||
NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node *node, const QString &output, const TimeRange &range)
|
||||
{
|
||||
// Generate row
|
||||
NodeValueRow row;
|
||||
for (auto it=database->begin(); it!=database->end(); it++) {
|
||||
// Get hint for which value should be pulled
|
||||
row.insert(it.key(), GenerateRowValue(node, it.key(), &it.value()));
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
NodeValueRow NodeTraverser::GenerateRow(const Node *node, const QString &output, const TimeRange &range)
|
||||
{
|
||||
// Generate database of input values of node
|
||||
NodeValueDatabase database = GenerateDatabase(node, output, range);
|
||||
|
||||
return GenerateRow(&database, node, output, range);
|
||||
}
|
||||
|
||||
NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table)
|
||||
{
|
||||
Node::ValueHint hint = node->GetValueHintForInput(input);
|
||||
QVector<NodeValue::Type> types = hint.type;
|
||||
|
||||
if (types.isEmpty()) {
|
||||
types.append(node->GetInputDataType(input));
|
||||
}
|
||||
|
||||
if (hint.index == -1) {
|
||||
// Get most recent value with this type and tag
|
||||
return table->TakeWithMeta(types, hint.tag);
|
||||
} else {
|
||||
// Try to find value at this index
|
||||
int index = table->Count() - hint.index;
|
||||
int diff = 0;
|
||||
|
||||
while (index + diff < table->Count() && index - diff >= 0) {
|
||||
if (index + diff < table->Count() && types.contains(table->at(index + diff).type())) {
|
||||
return table->TakeAt(index + diff);
|
||||
}
|
||||
if (index - diff >= 0 && types.contains(table->at(index - diff).type())) {
|
||||
return table->TakeAt(index - diff);
|
||||
}
|
||||
diff++;
|
||||
}
|
||||
|
||||
return NodeValue();
|
||||
}
|
||||
}
|
||||
|
||||
NodeGlobals NodeTraverser::GenerateGlobals(const VideoParams ¶ms, const TimeRange &time)
|
||||
{
|
||||
return NodeGlobals(QVector2D(params.width(), params.height()), time);
|
||||
}
|
||||
|
||||
int NodeTraverser::GetChannelCountFromJob(const GenerateJob &job)
|
||||
{
|
||||
switch (job.GetAlphaChannelRequired()) {
|
||||
@@ -132,12 +186,20 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const QString& output
|
||||
|
||||
// FIXME: Cache certain values here if we've already processed them before
|
||||
|
||||
// Generate database of input values of node
|
||||
// Generate row for node
|
||||
NodeValueDatabase database = GenerateDatabase(n, output, range);
|
||||
NodeValueRow row = GenerateRow(&database, n, output, range);
|
||||
|
||||
// Pre-process row
|
||||
qDebug() << "FIXME: Implement pre-process of row";
|
||||
|
||||
// Generate output table
|
||||
NodeValueTable table = database.Merge();
|
||||
|
||||
// By this point, the node should have all the inputs it needs to render correctly
|
||||
NodeValueTable table = n->Value(output, database);
|
||||
n->Value(output, row, GenerateGlobals(video_params_, range), &table);
|
||||
|
||||
// Post-process table
|
||||
PostProcessTable(n, output, range, table);
|
||||
|
||||
return table;
|
||||
@@ -218,17 +280,6 @@ QVariant NodeTraverser::GetCachedTexture(const QByteArray& hash)
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void NodeTraverser::AddGlobalsToDatabase(NodeValueDatabase &db, const TimeRange& range) const
|
||||
{
|
||||
// Insert global variables
|
||||
NodeValueTable global;
|
||||
global.Push(NodeValue::kFloat, range.in().toDouble(), nullptr, false, QStringLiteral("time_in"));
|
||||
global.Push(NodeValue::kFloat, range.out().toDouble(), nullptr, false, QStringLiteral("time_out"));
|
||||
global.Push(NodeValue::kVec2, GenerateResolution(), nullptr, false, QStringLiteral("resolution"));
|
||||
|
||||
db.Insert(QStringLiteral("global"), global);
|
||||
}
|
||||
|
||||
QVector2D NodeTraverser::GenerateResolution() const
|
||||
{
|
||||
return QVector2D(video_params_.square_pixel_width(), video_params_.height());
|
||||
|
||||
+11
-2
@@ -44,6 +44,17 @@ public:
|
||||
|
||||
NodeValueDatabase GenerateDatabase(const Node *node, const QString &output, const TimeRange &range);
|
||||
|
||||
NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const QString &output, const TimeRange &range);
|
||||
NodeValueRow GenerateRow(const Node *node, const QString &output, const TimeRange &range);
|
||||
|
||||
NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table);
|
||||
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time);
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time)
|
||||
{
|
||||
return GenerateGlobals(params, TimeRange(time, time + params.frame_rate_as_time_base()));
|
||||
}
|
||||
|
||||
const VideoParams& GetCacheVideoParams() const
|
||||
{
|
||||
return video_params_;
|
||||
@@ -80,8 +91,6 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddGlobalsToDatabase(NodeValueDatabase& db, const TimeRange &range) const;
|
||||
|
||||
QVector2D GenerateResolution() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -381,6 +381,11 @@ public:
|
||||
bool Has(NodeValue::Type type) const;
|
||||
void Remove(const NodeValue& v);
|
||||
|
||||
void Clear()
|
||||
{
|
||||
values_.clear();
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return values_.isEmpty();
|
||||
@@ -395,6 +400,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
using NodeValueRow = QHash<QString, NodeValue>;
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::NodeValue)
|
||||
|
||||
@@ -43,30 +43,40 @@ public:
|
||||
|
||||
NodeValueTable Merge() const;
|
||||
|
||||
using const_iterator = QHash<QString, NodeValueTable>::const_iterator;
|
||||
using Tables = QHash<QString, NodeValueTable>;
|
||||
using const_iterator = Tables::const_iterator;
|
||||
using iterator = Tables::iterator;
|
||||
|
||||
inline QHash<QString, NodeValueTable>::const_iterator begin() const
|
||||
inline const_iterator cbegin() const
|
||||
{
|
||||
return tables_.cbegin();
|
||||
}
|
||||
|
||||
inline QHash<QString, NodeValueTable>::const_iterator end() const
|
||||
inline const_iterator cend() const
|
||||
{
|
||||
return tables_.cend();
|
||||
}
|
||||
|
||||
inline iterator begin()
|
||||
{
|
||||
return tables_.begin();
|
||||
}
|
||||
|
||||
inline iterator end()
|
||||
{
|
||||
return tables_.end();
|
||||
}
|
||||
|
||||
inline bool contains(const QString& s) const
|
||||
{
|
||||
return tables_.contains(s);
|
||||
}
|
||||
|
||||
private:
|
||||
QHash<QString, NodeValueTable> tables_;
|
||||
Tables tables_;
|
||||
|
||||
};
|
||||
|
||||
using NodeValueMap = QHash<QString, NodeValue>;
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::NodeValueDatabase)
|
||||
|
||||
Reference in New Issue
Block a user