nodes: implemented core of manual table value selection

This commit is contained in:
itsmattkc
2021-09-07 15:27:07 -07:00
parent a3ac761b55
commit a0706a78d8
71 changed files with 517 additions and 434 deletions
+2
View File
@@ -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
+6 -11
View File
@@ -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];
+2 -2
View File
@@ -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;
+7 -6
View File
@@ -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);
}
+2 -2
View File
@@ -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;
+7 -4
View File
@@ -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
}
+2 -2
View File
@@ -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_;
+9 -8
View File
@@ -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);
}
}
+2 -2
View File
@@ -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;
};
+12 -16
View File
@@ -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)
+3 -3
View File
@@ -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;
+17 -27
View File
@@ -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;
+3 -3
View File
@@ -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_;
+5 -15
View File
@@ -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;
}
}
+1 -1
View File
@@ -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;
+4 -10
View File
@@ -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
+1 -1
View File
@@ -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;
+5 -14
View File
@@ -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
+1 -1
View File
@@ -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;
+16 -18
View File
@@ -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);
}
+2 -2
View File
@@ -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,
+4 -7
View File
@@ -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
+1 -1
View File
@@ -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;
+4 -9
View File
@@ -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);
}
}
+1 -1
View File
@@ -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;
+3 -6
View File
@@ -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
+1 -1
View File
@@ -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;
+3 -12
View File
@@ -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
+1 -1
View File
@@ -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;
+25
View File
@@ -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 {
}
+62
View File
@@ -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
+9 -13
View File
@@ -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()));
}
}
+2 -2
View File
@@ -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;
};
+4 -5
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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);
}
+2 -2
View File
@@ -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;
+18 -24
View File
@@ -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 &param_a_in, const QString &param_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const
void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBase::Operation operation, const QString &param_a_in, const QString &param_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++) {
+2 -2
View File
@@ -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;
};
+9 -14
View File
@@ -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);
+2 -2
View File
@@ -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_;
+3 -7
View File
@@ -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);
}
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+5 -3
View File
@@ -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);
}
}
+1 -1
View File
@@ -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;
-17
View File
@@ -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;
-3
View File
@@ -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);
};
}
+10 -13
View File
@@ -323,9 +323,9 @@ QString Footage::DescribeAudioStream(const AudioParams &params)
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)
+2 -2
View File
@@ -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);
+5 -2
View File
@@ -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);
}
}
+1 -1
View File
@@ -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
View File
@@ -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 &params, 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
View File
@@ -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 &params, const TimeRange &time);
static NodeGlobals GenerateGlobals(const VideoParams &params, 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:
+7
View File
@@ -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)
+16 -6
View File
@@ -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)