nodes: minor overhaul to functionality
The nodes now have more control over how their accelerated shaders/sample functions are run, as well as how items are popped off the value tables. This allows for various optimizations that we didn't have access to before.
This commit is contained in:
@@ -59,17 +59,23 @@ QString PanNode::Description() const
|
||||
return tr("Adjust the stereo panning of an audio source.");
|
||||
}
|
||||
|
||||
Node::Capabilities PanNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
NodeValueTable PanNode::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return kSampleProcessor;
|
||||
// Create a sample job
|
||||
SampleJob job(samples_input_);
|
||||
job.InsertValue(panning_input_, value);
|
||||
|
||||
// Push it to our table
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!qIsNull(job.GetValue(samples_input_).data().toDouble())) {
|
||||
table.Push(NodeParam::kSampleJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
NodeInput *PanNode::ProcessesSamplesFrom(const NodeValueDatabase &) const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
void PanNode::ProcessSamples(const NodeValueDatabase &values, const AudioParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void PanNode::ProcessSamples(NodeValueDatabase &values, const AudioParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
if (params.channel_count() != 2) {
|
||||
// This node currently only works for stereo audio
|
||||
|
||||
@@ -37,9 +37,9 @@ public:
|
||||
virtual QList<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase& values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
@@ -58,17 +58,21 @@ QString VolumeNode::Description() const
|
||||
return tr("Adjusts the volume of an audio source.");
|
||||
}
|
||||
|
||||
Node::Capabilities VolumeNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
NodeValueTable VolumeNode::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return kSampleProcessor;
|
||||
SampleJob job(samples_input_);
|
||||
job.InsertValue(volume_input_, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (qFuzzyCompare(job.GetValue(volume_input_).data().toDouble(), 1.0)) {
|
||||
table.Push(NodeParam::kSampleJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
NodeInput *VolumeNode::ProcessesSamplesFrom(const NodeValueDatabase &) const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
void VolumeNode::ProcessSamples(const NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void VolumeNode::ProcessSamples(NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
float volume_val = values[volume_input_].Get(NodeParam::kFloat).toFloat();
|
||||
|
||||
@@ -83,9 +87,4 @@ void VolumeNode::Retranslate()
|
||||
volume_input_->set_name(tr("Volume"));
|
||||
}
|
||||
|
||||
NodeInput *VolumeNode::samples_input() const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -37,13 +37,16 @@ public:
|
||||
virtual QList<CategoryID> Category() const override;
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase& values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeInput* samples_input() const;
|
||||
NodeInput* samples_input() const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeInput* samples_input_;
|
||||
|
||||
@@ -80,25 +80,52 @@ void BlurFilterNode::Retranslate()
|
||||
repeat_edge_pixels_input_->set_name(tr("Repeat Edge Pixels"));
|
||||
}
|
||||
|
||||
Node::Capabilities BlurFilterNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
ShaderCode BlurFilterNode::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return kShader;
|
||||
Q_UNUSED(shader_id)
|
||||
return ShaderCode(ReadFileAsString(":/shaders/blur.frag"), QString());
|
||||
}
|
||||
|
||||
QString BlurFilterNode::ShaderFragmentCode(const NodeValueDatabase &) const
|
||||
NodeValueTable BlurFilterNode::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/blur.frag");
|
||||
}
|
||||
ShaderJob job;
|
||||
|
||||
int BlurFilterNode::ShaderIterations() const
|
||||
{
|
||||
// FIXME: Optimize if horiz_in or vert_in is disabled
|
||||
return 2;
|
||||
}
|
||||
job.InsertValue(texture_input_, value);
|
||||
job.InsertValue(method_input_, value);
|
||||
job.InsertValue(radius_input_, value);
|
||||
job.InsertValue(horiz_input_, value);
|
||||
job.InsertValue(vert_input_, value);
|
||||
job.InsertValue(repeat_edge_pixels_input_, value);
|
||||
|
||||
NodeInput *BlurFilterNode::ShaderIterativeInput() const
|
||||
{
|
||||
return texture_input_;
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
// If there's no texture, no need to run an operation
|
||||
if (!job.GetValue(texture_input_).data().isNull()) {
|
||||
|
||||
// Check if radius > 0, and both "horiz" and/or "vert" are enabled
|
||||
if ((job.GetValue(horiz_input_).data().toBool() || job.GetValue(vert_input_).data().toBool())
|
||||
&& job.GetValue(radius_input_).data().toDouble() > 0.0) {
|
||||
|
||||
// Set iteration count to 2 if we're blurring both horizontally and vertically
|
||||
if (job.GetValue(horiz_input_).data().toBool() && job.GetValue(vert_input_).data().toBool()) {
|
||||
job.SetIterations(2, texture_input_);
|
||||
}
|
||||
|
||||
// If we're not repeating pixels, expect an alpha channel to appear
|
||||
if (!job.GetValue(repeat_edge_pixels_input_).data().toBool()) {
|
||||
job.SetAlphaChannelRequired(true);
|
||||
}
|
||||
|
||||
table.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
|
||||
} else {
|
||||
// If we're not performing the blur job, just push the texture
|
||||
table.Push(job.GetValue(texture_input_));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -39,11 +39,8 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
|
||||
virtual int ShaderIterations() const override;
|
||||
virtual NodeInput* ShaderIterativeInput() const override;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray &shader_id) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
private:
|
||||
NodeInput* texture_input_;
|
||||
|
||||
@@ -82,14 +82,35 @@ void StrokeFilterNode::Retranslate()
|
||||
inner_input_->set_name(tr("Inner"));
|
||||
}
|
||||
|
||||
Node::Capabilities StrokeFilterNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
NodeValueTable StrokeFilterNode::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return kShader;
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(tex_input_, value);
|
||||
job.InsertValue(color_input_, value);
|
||||
job.InsertValue(radius_input_, value);
|
||||
job.InsertValue(opacity_input_, value);
|
||||
job.InsertValue(inner_input_, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!job.GetValue(tex_input_).data().isNull()) {
|
||||
if (job.GetValue(radius_input_).data().toDouble() > 0.0
|
||||
&& job.GetValue(opacity_input_).data().toDouble() > 0.0) {
|
||||
table.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
table.Push(job.GetValue(tex_input_));
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
QString StrokeFilterNode::ShaderFragmentCode(const NodeValueDatabase &) const
|
||||
ShaderCode StrokeFilterNode::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/stroke.frag");
|
||||
Q_UNUSED(shader_id)
|
||||
|
||||
return ShaderCode(ReadFileAsString(":/shaders/stroke.frag"), QString());
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray &shader_id) const override;
|
||||
|
||||
private:
|
||||
NodeInput* tex_input_;
|
||||
|
||||
@@ -100,7 +100,7 @@ NodeValueTable MatrixGenerator::Value(NodeValueDatabase &value) const
|
||||
return output;
|
||||
}
|
||||
|
||||
bool MatrixGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize &viewport)
|
||||
bool MatrixGenerator::GizmoPress(NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize &viewport)
|
||||
{
|
||||
GizmoSharedData gizmo_data(viewport, scale);
|
||||
|
||||
@@ -167,7 +167,7 @@ bool MatrixGenerator::HasGizmos() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void MatrixGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize& viewport) const
|
||||
void MatrixGenerator::DrawGizmos(NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize& viewport) const
|
||||
{
|
||||
p->setPen(Qt::white);
|
||||
|
||||
@@ -219,7 +219,7 @@ QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value) const
|
||||
value[anchor_input_].Take(NodeParam::kVec2).value<QVector2D>());
|
||||
}
|
||||
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueDatabase &value, bool ignore_anchor) const
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value, bool ignore_anchor) const
|
||||
{
|
||||
QVector2D anchor;
|
||||
|
||||
@@ -262,7 +262,7 @@ QMatrix4x4 MatrixGenerator::GenerateMatrix(const QVector2D& pos,
|
||||
return mat;
|
||||
}
|
||||
|
||||
QPointF MatrixGenerator::GetGizmoAnchorPoint(const NodeValueDatabase &db,
|
||||
QPointF MatrixGenerator::GetGizmoAnchorPoint(NodeValueDatabase &db,
|
||||
const GizmoSharedData& gizmo_data) const
|
||||
{
|
||||
QMatrix4x4 matrix;
|
||||
|
||||
@@ -47,9 +47,9 @@ public:
|
||||
virtual NodeValueTable Value(NodeValueDatabase& value) const override;
|
||||
|
||||
virtual bool HasGizmos() const override;
|
||||
virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override;
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override;
|
||||
|
||||
virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override;
|
||||
virtual bool GizmoPress(NodeValueDatabase& db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override;
|
||||
virtual void GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) override;
|
||||
virtual void GizmoRelease() override;
|
||||
|
||||
@@ -63,14 +63,14 @@ private:
|
||||
};
|
||||
|
||||
QMatrix4x4 GenerateMatrix(NodeValueDatabase& value) const;
|
||||
QMatrix4x4 GenerateMatrix(const NodeValueDatabase& value, bool ignore_anchor) const;
|
||||
QMatrix4x4 GenerateMatrix(NodeValueDatabase &value, bool ignore_anchor) const;
|
||||
static QMatrix4x4 GenerateMatrix(const QVector2D &pos,
|
||||
const float &rot,
|
||||
const QVector2D &scale,
|
||||
bool uniform_scale,
|
||||
const QVector2D &anchor);
|
||||
|
||||
QPointF GetGizmoAnchorPoint(const NodeValueDatabase &db, const GizmoSharedData &gizmo_data) const;
|
||||
QPointF GetGizmoAnchorPoint(NodeValueDatabase &db, const GizmoSharedData &gizmo_data) const;
|
||||
static int GetGizmoAnchorPointRadius();
|
||||
NodeInput* gizmo_drag_;
|
||||
|
||||
|
||||
@@ -85,14 +85,23 @@ void PolygonGenerator::Retranslate()
|
||||
color_input_->set_name(tr("Color"));
|
||||
}
|
||||
|
||||
Node::Capabilities PolygonGenerator::GetCapabilities(const NodeValueDatabase &) const
|
||||
ShaderCode PolygonGenerator::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return kShader;
|
||||
Q_UNUSED(shader_id)
|
||||
|
||||
return ShaderCode(Node::ReadFileAsString(":/shaders/polygon.frag"), QString());
|
||||
}
|
||||
|
||||
QString PolygonGenerator::ShaderFragmentCode(const NodeValueDatabase &) const
|
||||
NodeValueTable PolygonGenerator::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return Node::ReadFileAsString(":/shaders/polygon.frag");
|
||||
ShaderJob job;
|
||||
|
||||
job.InsertValue(points_input_, value);
|
||||
job.InsertValue(color_input_, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
table.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
return table;
|
||||
}
|
||||
|
||||
bool PolygonGenerator::HasGizmos() const
|
||||
@@ -100,8 +109,10 @@ bool PolygonGenerator::HasGizmos() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolygonGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize &viewport) const
|
||||
void PolygonGenerator::DrawGizmos(NodeValueDatabase &db, QPainter *p, const QVector2D &scale, const QSize &viewport) const
|
||||
{
|
||||
Q_UNUSED(viewport)
|
||||
|
||||
if (!points_input_->GetSize()) {
|
||||
return;
|
||||
}
|
||||
@@ -118,8 +129,10 @@ void PolygonGenerator::DrawGizmos(const NodeValueDatabase &db, QPainter *p, cons
|
||||
p->drawRects(rects);
|
||||
}
|
||||
|
||||
bool PolygonGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize& viewport)
|
||||
bool PolygonGenerator::GizmoPress(NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize& viewport)
|
||||
{
|
||||
Q_UNUSED(viewport)
|
||||
|
||||
QVector<QPointF> points = GetGizmoCoordinates(db, scale);
|
||||
QVector<QRectF> rects = GetGizmoRects(points);
|
||||
|
||||
@@ -158,7 +171,7 @@ void PolygonGenerator::GizmoRelease()
|
||||
gizmo_y_dragger_.End();
|
||||
}
|
||||
|
||||
QVector<QPointF> PolygonGenerator::GetGizmoCoordinates(const NodeValueDatabase &db, const QVector2D& scale) const
|
||||
QVector<QPointF> PolygonGenerator::GetGizmoCoordinates(NodeValueDatabase &db, const QVector2D& scale) const
|
||||
{
|
||||
QVector<QPointF> points(points_input_->GetSize());
|
||||
|
||||
|
||||
@@ -40,18 +40,18 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray& shader_id) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
virtual bool HasGizmos() const override;
|
||||
virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override;
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p, const QVector2D &scale, const QSize& viewport) const override;
|
||||
|
||||
virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override;
|
||||
virtual bool GizmoPress(NodeValueDatabase &db, const QPointF &p, const QVector2D &scale, const QSize& viewport) override;
|
||||
virtual void GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) override;
|
||||
virtual void GizmoRelease() override;
|
||||
|
||||
private:
|
||||
QVector<QPointF> GetGizmoCoordinates(const NodeValueDatabase &db, const QVector2D &scale) const;
|
||||
QVector<QPointF> GetGizmoCoordinates(NodeValueDatabase &db, const QVector2D &scale) const;
|
||||
|
||||
QVector<QRectF> GetGizmoRects(const QVector<QPointF>& points) const;
|
||||
|
||||
|
||||
@@ -63,14 +63,21 @@ void SolidGenerator::Retranslate()
|
||||
color_input_->set_name(tr("Color"));
|
||||
}
|
||||
|
||||
Node::Capabilities SolidGenerator::GetCapabilities(const NodeValueDatabase &) const
|
||||
NodeValueTable SolidGenerator::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return kShader;
|
||||
ShaderJob job;
|
||||
job.InsertValue(color_input_, value);
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
table.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
return table;
|
||||
}
|
||||
|
||||
QString SolidGenerator::ShaderFragmentCode(const NodeValueDatabase &) const
|
||||
ShaderCode SolidGenerator::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/solid.frag");
|
||||
Q_UNUSED(shader_id)
|
||||
|
||||
return ShaderCode(ReadFileAsString(":/shaders/solid.frag"), QString());
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray &shader_id) const override;
|
||||
|
||||
private:
|
||||
NodeInput* color_input_;
|
||||
|
||||
@@ -57,7 +57,7 @@ void MediaInput::Retranslate()
|
||||
|
||||
NodeValueTable MediaInput::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
NodeValueTable table;
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (connected_footage_) {
|
||||
rational media_duration = Timecode::timestamp_to_time(connected_footage_->duration(),
|
||||
@@ -66,12 +66,6 @@ NodeValueTable MediaInput::Value(NodeValueDatabase &value) const
|
||||
table.Push(NodeInput::kRational, QVariant::fromValue(media_duration), this, "length");
|
||||
}
|
||||
|
||||
// Push buffer to the top of the stack
|
||||
NodeValue buffer = value[footage_input_].GetWithMeta(NodeParam::kBuffer);
|
||||
if (buffer.type() != NodeParam::kNone) {
|
||||
table.Push(buffer);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
+103
-99
@@ -89,45 +89,21 @@ void MathNode::Retranslate()
|
||||
method_in_->set_combobox_strings(operations);
|
||||
}
|
||||
|
||||
Node::Capabilities MathNode::GetCapabilities(const NodeValueDatabase &input) const
|
||||
ShaderCode MathNode::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
|
||||
QDataStream data(shader_id);
|
||||
|
||||
switch (calc.GetMostLikelyPairing()) {
|
||||
case kPairTextureColor:
|
||||
case kPairTextureNumber:
|
||||
case kPairTextureTexture:
|
||||
case kPairTextureMatrix:
|
||||
return kShader;
|
||||
case kPairSampleNumber:
|
||||
return kSampleProcessor;
|
||||
default:
|
||||
return kNormal;
|
||||
}
|
||||
}
|
||||
Pairing pairing;
|
||||
NodeParam::DataType type_a;
|
||||
NodeParam::DataType type_b;
|
||||
|
||||
QString MathNode::ShaderID(const NodeValueDatabase &input) const
|
||||
{
|
||||
QString method = QString::number(GetOperation());
|
||||
data >> pairing;
|
||||
data >> type_a;
|
||||
data >> type_b;
|
||||
|
||||
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
|
||||
QString operation, frag, vert;
|
||||
|
||||
QString type_a = QString::number(calc.GetMostLikelyValueA().type());
|
||||
QString type_b = QString::number(calc.GetMostLikelyValueB().type());
|
||||
|
||||
return id().append(method).append(type_a).append(type_b);
|
||||
}
|
||||
|
||||
QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
{
|
||||
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
|
||||
|
||||
NodeParam::DataType type_a = calc.GetMostLikelyValueA().type();
|
||||
NodeParam::DataType type_b = calc.GetMostLikelyValueB().type();
|
||||
|
||||
QString operation;
|
||||
|
||||
if (calc.GetMostLikelyPairing() == kPairTextureMatrix && GetOperation() == kOpMultiply) {
|
||||
if (pairing == kPairTextureMatrix && GetOperation() == kOpMultiply) {
|
||||
|
||||
// Override the operation for this operation since we multiply texture COORDS by the matrix rather than
|
||||
NodeParam* tex_in = (type_a == NodeParam::kTexture) ? param_a_in_ : param_b_in_;
|
||||
@@ -135,6 +111,11 @@ QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
// No-op frag shader (can we return QString() instead?)
|
||||
operation = QStringLiteral("texture(%1, ove_texcoord)").arg(tex_in->id());
|
||||
|
||||
// Override the operation for this operation since we multiply texture COORDS by the matrix rather than
|
||||
NodeParam* mat_in = (type_a == NodeParam::kTexture) ? param_b_in_ : param_a_in_;
|
||||
|
||||
vert = ReadFileAsString(":/shaders/matrix.vert").arg(mat_in->id(), tex_in->id());
|
||||
|
||||
} else {
|
||||
switch (GetOperation()) {
|
||||
case kOpAdd:
|
||||
@@ -158,7 +139,7 @@ QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
GetShaderVariableCall(param_b_in_->id(), type_b));
|
||||
}
|
||||
|
||||
return QStringLiteral("#version 150\n"
|
||||
frag = QStringLiteral("#version 150\n"
|
||||
"\n"
|
||||
"uniform %1 %3;\n"
|
||||
"uniform %2 %4;\n"
|
||||
@@ -174,44 +155,8 @@ QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
param_a_in_->id(),
|
||||
param_b_in_->id(),
|
||||
operation);
|
||||
}
|
||||
|
||||
QString MathNode::ShaderVertexCode(const NodeValueDatabase &input) const
|
||||
{
|
||||
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
|
||||
|
||||
if (calc.GetMostLikelyPairing() == kPairTextureMatrix && GetOperation() == kOpMultiply) {
|
||||
|
||||
NodeParam::DataType type_a = calc.GetMostLikelyValueA().type();
|
||||
|
||||
// Override the operation for this operation since we multiply texture COORDS by the matrix rather than
|
||||
NodeParam* tex_in = (type_a == NodeParam::kTexture) ? param_a_in_ : param_b_in_;
|
||||
NodeParam* mat_in = (type_a == NodeParam::kTexture) ? param_b_in_ : param_a_in_;
|
||||
|
||||
return ReadFileAsString(":/shaders/matrix.vert").arg(mat_in->id(), tex_in->id());
|
||||
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
NodeValue MathNode::InputValueFromTable(NodeInput *input, NodeValueDatabase &db, bool take) const
|
||||
{
|
||||
if (input == param_a_in_ || input == param_b_in_) {
|
||||
PairingCalculator calc(db[param_a_in_], db[param_b_in_]);
|
||||
|
||||
NodeValue v = (input == param_a_in_)
|
||||
? calc.GetMostLikelyValueA()
|
||||
: calc.GetMostLikelyValueB();
|
||||
|
||||
if (take) {
|
||||
db[input].Remove(v);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
return Node::InputValueFromTable(input, db, take);
|
||||
return ShaderCode(frag, vert);
|
||||
}
|
||||
|
||||
NodeValueTable MathNode::Value(NodeValueDatabase &value) const
|
||||
@@ -220,12 +165,8 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const
|
||||
// FIXME: Add manual override for this
|
||||
PairingCalculator calc(value[param_a_in_], value[param_b_in_]);
|
||||
|
||||
if (!calc.FoundMostLikelyPairing()
|
||||
|| calc.GetMostLikelyPairing() == kPairSampleNumber
|
||||
|| calc.GetMostLikelyPairing() == kPairTextureTexture
|
||||
|| calc.GetMostLikelyPairing() == kPairTextureNumber
|
||||
|| calc.GetMostLikelyPairing() == kPairTextureColor
|
||||
|| calc.GetMostLikelyPairing() == kPairTextureMatrix) {
|
||||
// Do nothing if no pairing was found
|
||||
if (!calc.FoundMostLikelyPairing()) {
|
||||
return value.Merge();
|
||||
}
|
||||
|
||||
@@ -347,40 +288,82 @@ NodeValueTable MathNode::Value(NodeValueDatabase &value) const
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairNone:
|
||||
case kPairCount:
|
||||
case kPairTextureColor:
|
||||
case kPairTextureNumber:
|
||||
case kPairTextureTexture:
|
||||
case kPairTextureMatrix:
|
||||
{
|
||||
ShaderJob job;
|
||||
|
||||
QByteArray shader_id;
|
||||
QDataStream shader_id_stream(&shader_id, QIODevice::WriteOnly);
|
||||
shader_id_stream << calc.GetMostLikelyPairing();
|
||||
shader_id_stream << val_a.type();
|
||||
shader_id_stream << val_b.type();
|
||||
|
||||
job.SetShaderID(shader_id);
|
||||
|
||||
job.InsertValue(param_a_in_, val_a);
|
||||
job.InsertValue(param_b_in_, val_b);
|
||||
|
||||
bool operation_is_noop = false;
|
||||
|
||||
if (calc.GetMostLikelyPairing() == kPairTextureNumber) {
|
||||
NodeValue& number_val = val_a.type() == NodeParam::kTexture ? val_b : val_a;
|
||||
|
||||
if (NumberIsNoOp(GetOperation(), RetrieveNumber(number_val))) {
|
||||
operation_is_noop = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!operation_is_noop) {
|
||||
output.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
output.Push(val_a.type() == NodeParam::kTexture ? val_a : val_b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairSampleNumber:
|
||||
// Do nothing
|
||||
{
|
||||
// Queue a sample job
|
||||
SampleJob job(val_a.type() == NodeParam::kSamples ? param_a_in_ : param_b_in_);
|
||||
|
||||
NodeValue& number_val = val_a.type() == NodeParam::kSamples ? val_b : val_a;
|
||||
NodeInput* number_param = val_a.type() == NodeParam::kSamples ? param_b_in_ : param_a_in_;
|
||||
|
||||
float number = RetrieveNumber(number_val);
|
||||
|
||||
if (!NumberIsNoOp(GetOperation(), number)) {
|
||||
job.InsertValue(number_param, NodeValue(NodeParam::kFloat, number, this));
|
||||
output.Push(NodeParam::kSampleJob, QVariant::fromValue(job), this);
|
||||
} else {
|
||||
output.Push(val_a.type() == NodeParam::kSamples ? val_a : val_b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairNone:
|
||||
case kPairCount:
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
NodeInput *MathNode::ProcessesSamplesFrom(const NodeValueDatabase &value) const
|
||||
void MathNode::ProcessSamples(NodeValueDatabase &values, const AudioParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
PairingCalculator calc(value[param_a_in_], value[param_b_in_]);
|
||||
// This function is only used for sample+number pairing
|
||||
NodeValue number_val = values[param_a_in_].GetWithMeta(NodeParam::kNumber);
|
||||
|
||||
if (calc.GetMostLikelyPairing() == kPairSampleNumber) {
|
||||
if (calc.GetMostLikelyValueA().type() == NodeParam::kSamples) {
|
||||
return param_a_in_;
|
||||
} else {
|
||||
return param_b_in_;
|
||||
if (number_val.type() == NodeParam::kNone) {
|
||||
number_val = values[param_b_in_].GetWithMeta(NodeParam::kNumber);
|
||||
|
||||
if (number_val.type() == NodeParam::kNone) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MathNode::ProcessSamples(const NodeValueDatabase &values, const AudioParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
// This function is only used for sample+number pairing
|
||||
NodeInput* number_input = (ProcessesSamplesFrom(values) == param_a_in_) ? param_b_in_ : param_a_in_;
|
||||
NodeValue number_val = values[number_input].GetWithMeta(NodeParam::kNumber);
|
||||
float number_flt = RetrieveNumber(number_val);
|
||||
|
||||
for (int i=0;i<params.channel_count();i++) {
|
||||
@@ -471,6 +454,27 @@ float MathNode::RetrieveNumber(const NodeValue &val)
|
||||
}
|
||||
}
|
||||
|
||||
bool MathNode::NumberIsNoOp(const MathNode::Operation &op, const float &number)
|
||||
{
|
||||
switch (op) {
|
||||
case kOpAdd:
|
||||
case kOpSubtract:
|
||||
if (qIsNull(number)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case kOpMultiply:
|
||||
case kOpDivide:
|
||||
case kOpPower:
|
||||
if (qFuzzyCompare(number, 1.0f)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MathNode::PairingCalculator::PairingCalculator(const NodeValueTable &table_a, const NodeValueTable &table_b)
|
||||
{
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(table_a);
|
||||
@@ -501,8 +505,8 @@ MathNode::PairingCalculator::PairingCalculator(const NodeValueTable &table_a, co
|
||||
}
|
||||
|
||||
if (most_likely_pairing_ != kPairNone) {
|
||||
most_likely_value_a_ = table_a.At(pair_likelihood_a.at(most_likely_pairing_));
|
||||
most_likely_value_b_ = table_b.At(pair_likelihood_b.at(most_likely_pairing_));
|
||||
most_likely_value_a_ = table_a.at(pair_likelihood_a.at(most_likely_pairing_));
|
||||
most_likely_value_b_ = table_b.at(pair_likelihood_b.at(most_likely_pairing_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,7 +517,7 @@ QVector<int> MathNode::PairingCalculator::GetPairLikelihood(const NodeValueTable
|
||||
QVector<int> likelihood(kPairCount, -1);
|
||||
|
||||
for (int i=0;i<table.Count();i++) {
|
||||
NodeParam::DataType type = table.At(i).type();
|
||||
NodeParam::DataType type = table.at(i).type();
|
||||
|
||||
int weight = i;
|
||||
|
||||
|
||||
@@ -39,17 +39,10 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderID(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderVertexCode(const NodeValueDatabase&input) const override;
|
||||
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, NodeValueDatabase &db, bool take) const override;
|
||||
|
||||
virtual ShaderCode GetShaderCode(const QByteArray &shader_id) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
NodeInput* param_a_in() const;
|
||||
NodeInput* param_b_in() const;
|
||||
@@ -134,6 +127,8 @@ private:
|
||||
|
||||
static float RetrieveNumber(const NodeValue& val);
|
||||
|
||||
static bool NumberIsNoOp(const Operation& op, const float& number);
|
||||
|
||||
void PushVector(NodeValueTable* output, NodeParam::DataType type, const QVector4D& vec) const;
|
||||
|
||||
NodeInput* method_in_;
|
||||
|
||||
@@ -62,14 +62,37 @@ void MergeNode::Retranslate()
|
||||
blend_in_->set_name(tr("Blend"));
|
||||
}
|
||||
|
||||
Node::Capabilities MergeNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
ShaderCode MergeNode::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return kShader;
|
||||
Q_UNUSED(shader_id)
|
||||
|
||||
return ShaderCode(ReadFileAsString(":/shaders/alphaover.frag"), QString());
|
||||
}
|
||||
|
||||
QString MergeNode::ShaderFragmentCode(const NodeValueDatabase &) const
|
||||
NodeValueTable MergeNode::Value(NodeValueDatabase &value) const
|
||||
{
|
||||
return ReadFileAsString(":/shaders/alphaover.frag");
|
||||
ShaderJob job;
|
||||
job.InsertValue(base_in_, value);
|
||||
job.InsertValue(blend_in_, value);
|
||||
|
||||
// FIXME: Check if "blend" is RGB-only, in which case it's a no-op
|
||||
|
||||
NodeValueTable table = value.Merge();
|
||||
|
||||
if (!job.GetValue(base_in_).data().isNull() || !job.GetValue(blend_in_).data().isNull()) {
|
||||
if (job.GetValue(base_in_).data().isNull()) {
|
||||
// We only have a blend texture, no need to alpha over
|
||||
table.Push(job.GetValue(blend_in_));
|
||||
} else if (job.GetValue(blend_in_).data().isNull()) {
|
||||
// We only have a base texture, no need to alpha over
|
||||
table.Push(job.GetValue(base_in_));
|
||||
} else {
|
||||
// We have both textures, push the job
|
||||
table.Push(NodeParam::kShaderJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
NodeInput *MergeNode::base_in() const
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray &shader_id) const override;
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
NodeInput* base_in() const;
|
||||
NodeInput* blend_in() const;
|
||||
|
||||
+7
-52
@@ -276,11 +276,11 @@ bool Node::HasGizmos() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void Node::DrawGizmos(const NodeValueDatabase &, QPainter *, const QVector2D &, const QSize &) const
|
||||
void Node::DrawGizmos(NodeValueDatabase &, QPainter *, const QVector2D &, const QSize &) const
|
||||
{
|
||||
}
|
||||
|
||||
bool Node::GizmoPress(const NodeValueDatabase &, const QPointF &, const QVector2D &, const QSize &viewport)
|
||||
bool Node::GizmoPress(NodeValueDatabase &, const QPointF &, const QVector2D &, const QSize &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -457,42 +457,14 @@ QList<Node *> Node::GetImmediateDependencies() const
|
||||
return GetDependenciesInternal(false, false);
|
||||
}
|
||||
|
||||
Node::Capabilities Node::GetCapabilities(const NodeValueDatabase &) const
|
||||
ShaderCode Node::GetShaderCode(const QByteArray &shader_id) const
|
||||
{
|
||||
return kNormal;
|
||||
Q_UNUSED(shader_id)
|
||||
|
||||
return ShaderCode(QString(), QString());
|
||||
}
|
||||
|
||||
QString Node::ShaderID(const NodeValueDatabase &) const
|
||||
{
|
||||
return id();
|
||||
}
|
||||
|
||||
QString Node::ShaderVertexCode(const NodeValueDatabase &) const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Node::ShaderFragmentCode(const NodeValueDatabase&) const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
int Node::ShaderIterations() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
NodeInput *Node::ShaderIterativeInput() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeInput* Node::ProcessesSamplesFrom(const NodeValueDatabase &) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Node::ProcessSamples(const NodeValueDatabase &, const AudioParams&, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
void Node::ProcessSamples(NodeValueDatabase &, const AudioParams&, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
{
|
||||
}
|
||||
|
||||
@@ -752,23 +724,6 @@ NodeOutput *Node::output() const
|
||||
return output_;
|
||||
}
|
||||
|
||||
NodeValue Node::InputValueFromTable(NodeInput *input, NodeValueDatabase &db, bool take) const
|
||||
{
|
||||
NodeParam::DataType find_data_type = input->data_type();
|
||||
|
||||
// Exception for Footage types (try to get a Texture instead)
|
||||
if (find_data_type == NodeParam::kFootage) {
|
||||
find_data_type = NodeParam::kTexture;
|
||||
}
|
||||
|
||||
// Try to get a value from it
|
||||
if (take) {
|
||||
return db[input].TakeWithMeta(find_data_type);
|
||||
} else {
|
||||
return db[input].GetWithMeta(find_data_type);
|
||||
}
|
||||
}
|
||||
|
||||
const QPointF &Node::GetPosition() const
|
||||
{
|
||||
return position_;
|
||||
|
||||
+5
-44
@@ -35,6 +35,7 @@
|
||||
#include "node/output.h"
|
||||
#include "node/value.h"
|
||||
#include "render/audioparams.h"
|
||||
#include "render/shaderinfo.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
@@ -56,12 +57,6 @@ class Node : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Capabilities {
|
||||
kNormal = 0x0,
|
||||
kShader = 0x1,
|
||||
kSampleProcessor = 0x2
|
||||
};
|
||||
|
||||
enum CategoryID {
|
||||
kCategoryUnknown = -1,
|
||||
|
||||
@@ -176,47 +171,15 @@ public:
|
||||
*/
|
||||
QList<Node*> GetImmediateDependencies() const;
|
||||
|
||||
/**
|
||||
* @brief Return accelerated capabilities of this node (if any)
|
||||
*/
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const;
|
||||
|
||||
/**
|
||||
* @brief Generate a unique identifier for the shader code (if a node can produce multiple)
|
||||
*/
|
||||
virtual QString ShaderID(const NodeValueDatabase&) const;
|
||||
|
||||
/**
|
||||
* @brief Generate hardware accelerated code for this Node
|
||||
*/
|
||||
virtual QString ShaderVertexCode(const NodeValueDatabase&) const;
|
||||
|
||||
/**
|
||||
* @brief Generate hardware accelerated code for this Node
|
||||
*/
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const;
|
||||
|
||||
/**
|
||||
* @brief Number of iterations to run the accelerated code
|
||||
*
|
||||
* Some code is faster if it's merely repeated on a resulting texture rather than run once on the same buffer.
|
||||
*/
|
||||
virtual int ShaderIterations() const;
|
||||
|
||||
/**
|
||||
* @brief Parameter that should receive the buffer on an iteration past the first
|
||||
*/
|
||||
virtual NodeInput* ShaderIterativeInput() const;
|
||||
|
||||
/**
|
||||
* @brief Return whether this node processes samples or not
|
||||
*/
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const;
|
||||
virtual ShaderCode GetShaderCode(const QByteArray& shader_id) const;
|
||||
|
||||
/**
|
||||
* @brief If ProcessesSamples() is true, this is the function that will process them.
|
||||
*/
|
||||
virtual void ProcessSamples(const NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
virtual void ProcessSamples(NodeValueDatabase &values, const AudioParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the input with the specified ID (or nullptr if it doesn't exist)
|
||||
@@ -393,8 +356,6 @@ public:
|
||||
|
||||
NodeOutput* output() const;
|
||||
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, NodeValueDatabase &db, bool take) const;
|
||||
|
||||
const QPointF& GetPosition() const;
|
||||
|
||||
void SetPosition(const QPointF& pos);
|
||||
@@ -407,9 +368,9 @@ public:
|
||||
|
||||
virtual bool HasGizmos() const;
|
||||
|
||||
virtual void DrawGizmos(const NodeValueDatabase& db, QPainter* p, const QVector2D &scale, const QSize& viewport) const;
|
||||
virtual void DrawGizmos(NodeValueDatabase& db, QPainter* p, const QVector2D &scale, const QSize& viewport) const;
|
||||
|
||||
virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF& p, const QVector2D &scale, const QSize& viewport);
|
||||
virtual bool GizmoPress(NodeValueDatabase& db, const QPointF& p, const QVector2D &scale, const QSize& viewport);
|
||||
virtual void GizmoMove(const QPointF& p, const QVector2D &scale, const rational &time);
|
||||
virtual void GizmoRelease();
|
||||
|
||||
|
||||
@@ -212,6 +212,8 @@ QByteArray NodeParam::ValueToBytes(const NodeParam::DataType &type, const QVaria
|
||||
case kString:
|
||||
case kBuffer:
|
||||
case kVector:
|
||||
case kShaderJob:
|
||||
case kSampleJob:
|
||||
case kAny:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -178,6 +178,24 @@ public:
|
||||
*/
|
||||
kCombo = 0x8000,
|
||||
|
||||
/**
|
||||
* Job type
|
||||
*
|
||||
* An internal type used to indicate to the renderer that an accelerated shader job needs to
|
||||
* run. This value will usually be taken from a table and a kTexture value will be pushed to
|
||||
* take its place.
|
||||
*/
|
||||
kShaderJob = 0x10000,
|
||||
|
||||
/**
|
||||
* Job type
|
||||
*
|
||||
* An internal type used to indicate to the renderer that an accelerated sample job needs to
|
||||
* take place. This value will usually be taken from a table and a kSamples value will be
|
||||
* pushed to take its place.
|
||||
*/
|
||||
kSampleJob = 0x20000,
|
||||
|
||||
/**
|
||||
****************************** BROAD IDENTIFIERS ******************************
|
||||
*/
|
||||
|
||||
+125
-6
@@ -38,9 +38,7 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa
|
||||
|
||||
TimeRange input_time = node->InputTimeAdjustment(input, range);
|
||||
|
||||
NodeValueTable table = ProcessInput(input, input_time);
|
||||
|
||||
database.Insert(input, table);
|
||||
database.Insert(input, ProcessInput(input, input_time));
|
||||
}
|
||||
|
||||
// Insert global variables
|
||||
@@ -84,7 +82,7 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const TimeRange& rang
|
||||
// By this point, the node should have all the inputs it needs to render correctly
|
||||
NodeValueTable table = n->Value(database);
|
||||
|
||||
ProcessNodeEvent(n, range, database, table);
|
||||
PostProcessTable(n, range, table);
|
||||
|
||||
return table;
|
||||
}
|
||||
@@ -108,9 +106,130 @@ NodeValueTable NodeTraverser::GenerateBlockTable(const TrackOutput *track, const
|
||||
return table;
|
||||
}
|
||||
|
||||
StreamPtr NodeTraverser::ResolveStreamFromInput(NodeInput *input)
|
||||
QVariant NodeTraverser::ProcessVideoFootage(StreamPtr stream, const rational &input_time)
|
||||
{
|
||||
return input->get_standard_value().value<StreamPtr>();
|
||||
Q_UNUSED(stream)
|
||||
Q_UNUSED(input_time)
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant NodeTraverser::ProcessAudioFootage(StreamPtr stream, const TimeRange &input_time)
|
||||
{
|
||||
Q_UNUSED(stream)
|
||||
Q_UNUSED(input_time)
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant NodeTraverser::ProcessShader(const Node *node, const TimeRange &range, const ShaderJob &job)
|
||||
{
|
||||
Q_UNUSED(node)
|
||||
Q_UNUSED(range)
|
||||
Q_UNUSED(job)
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant NodeTraverser::ProcessSamples(const Node *node, const TimeRange &range, const SampleJob &job)
|
||||
{
|
||||
Q_UNUSED(node)
|
||||
Q_UNUSED(range)
|
||||
Q_UNUSED(job)
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant NodeTraverser::GetCachedFrame(const Node *node, const rational &time)
|
||||
{
|
||||
Q_UNUSED(node)
|
||||
Q_UNUSED(time)
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void NodeTraverser::PostProcessTable(const Node *node, const TimeRange &range, NodeValueTable &output_params)
|
||||
{
|
||||
bool got_cached_frame = false;
|
||||
|
||||
// Convert footage to image/sample buffers
|
||||
QVariant cached_frame = GetCachedFrame(node, range.in());
|
||||
if (!cached_frame.isNull()) {
|
||||
output_params.Push(NodeParam::kTexture, cached_frame, node);
|
||||
|
||||
// No more to do here
|
||||
got_cached_frame = true;
|
||||
}
|
||||
|
||||
// Strip out any jobs or footage
|
||||
QList<NodeValue> video_footage_to_retrieve;
|
||||
QList<NodeValue> audio_footage_to_retrieve;
|
||||
QList<NodeValue> shader_jobs_to_run;
|
||||
QList<NodeValue> sample_jobs_to_run;
|
||||
|
||||
for (int i=output_params.Count()-1; i>=0; i--) {
|
||||
const NodeValue& v = output_params.at(i);
|
||||
QList<NodeValue>* take_this_value_list = nullptr;
|
||||
|
||||
if (v.type() == NodeParam::kFootage) {
|
||||
StreamPtr s = v.data().value<StreamPtr>();
|
||||
|
||||
if (s) {
|
||||
if (s->type() == Stream::kVideo
|
||||
|| s->type() == Stream::kImage) {
|
||||
take_this_value_list = &video_footage_to_retrieve;
|
||||
} else if (s->type() == Stream::kAudio) {
|
||||
take_this_value_list = &audio_footage_to_retrieve;
|
||||
}
|
||||
}
|
||||
} else if (v.type() == NodeParam::kShaderJob) {
|
||||
take_this_value_list = &shader_jobs_to_run;
|
||||
} else if (v.type() == NodeParam::kSampleJob) {
|
||||
take_this_value_list = &sample_jobs_to_run;
|
||||
}
|
||||
|
||||
if (take_this_value_list) {
|
||||
take_this_value_list->append(output_params.TakeAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_cached_frame) {
|
||||
// Retrieve video frames
|
||||
foreach (const NodeValue& v, video_footage_to_retrieve) {
|
||||
QVariant value = ProcessVideoFootage(v.data().value<StreamPtr>(), range.in());
|
||||
|
||||
if (!value.isNull()) {
|
||||
output_params.Push(NodeParam::kTexture, value, node);
|
||||
}
|
||||
}
|
||||
|
||||
// Run shaders
|
||||
foreach (const NodeValue& v, shader_jobs_to_run) {
|
||||
QVariant value = ProcessShader(node, range, v.data().value<ShaderJob>());
|
||||
|
||||
if (!value.isNull()) {
|
||||
output_params.Push(NodeParam::kTexture, value, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve audio samples
|
||||
foreach (const NodeValue& v, audio_footage_to_retrieve) {
|
||||
QVariant value = ProcessAudioFootage(v.data().value<StreamPtr>(), range);
|
||||
|
||||
if (!value.isNull()) {
|
||||
output_params.Push(NodeParam::kSamples, value, node);
|
||||
}
|
||||
}
|
||||
|
||||
// Run any accelerated shader jobs
|
||||
foreach (const NodeValue& v, sample_jobs_to_run) {
|
||||
QVariant value = ProcessSamples(node, range, v.data().value<SampleJob>());
|
||||
|
||||
if (!value.isNull()) {
|
||||
output_params.Push(NodeParam::kSamples, value, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
+12
-6
@@ -39,17 +39,23 @@ public:
|
||||
|
||||
NodeValueDatabase GenerateDatabase(const Node *node, const TimeRange &range);
|
||||
|
||||
static StreamPtr ResolveStreamFromInput(NodeInput* input);
|
||||
|
||||
protected:
|
||||
NodeValueTable ProcessInput(NodeInput *input, const TimeRange &range);
|
||||
|
||||
virtual NodeValueTable GenerateBlockTable(const TrackOutput *track, const TimeRange& range);
|
||||
|
||||
virtual void ProcessNodeEvent(const Node*,
|
||||
const TimeRange&,
|
||||
NodeValueDatabase&,
|
||||
NodeValueTable&) {}
|
||||
virtual QVariant ProcessVideoFootage(StreamPtr stream, const rational &input_time);
|
||||
|
||||
virtual QVariant ProcessAudioFootage(StreamPtr stream, const TimeRange &input_time);
|
||||
|
||||
virtual QVariant ProcessShader(const Node *node, const TimeRange &range, const ShaderJob& job);
|
||||
|
||||
virtual QVariant ProcessSamples(const Node *node, const TimeRange &range, const SampleJob &job);
|
||||
|
||||
virtual QVariant GetCachedFrame(const Node *node, const rational &time);
|
||||
|
||||
private:
|
||||
void PostProcessTable(const Node *node, const TimeRange &range, NodeValueTable &output_params);
|
||||
|
||||
};
|
||||
|
||||
|
||||
+2
-12
@@ -32,16 +32,6 @@ NodeValueTable& NodeValueDatabase::operator[](const NodeInput *input)
|
||||
return tables_[input->id()];
|
||||
}
|
||||
|
||||
const NodeValueTable NodeValueDatabase::operator[](const QString &input_id) const
|
||||
{
|
||||
return tables_[input_id];
|
||||
}
|
||||
|
||||
const NodeValueTable NodeValueDatabase::operator[](const NodeInput *input) const
|
||||
{
|
||||
return tables_[input->id()];
|
||||
}
|
||||
|
||||
void NodeValueDatabase::Insert(const QString &key, const NodeValueTable &value)
|
||||
{
|
||||
tables_.insert(key, value);
|
||||
@@ -143,7 +133,7 @@ void NodeValueTable::Prepend(const NodeParam::DataType &type, const QVariant &da
|
||||
Prepend(NodeValue(type, data, from, tag));
|
||||
}
|
||||
|
||||
const NodeValue &NodeValueTable::At(int index) const
|
||||
const NodeValue &NodeValueTable::at(int index) const
|
||||
{
|
||||
return values_.at(index);
|
||||
}
|
||||
@@ -209,7 +199,7 @@ NodeValueTable NodeValueTable::Merge(QList<NodeValueTable> tables)
|
||||
|
||||
int row_index = t.Count() - 1 - row;
|
||||
|
||||
merged_table.Prepend(t.At(row_index));
|
||||
merged_table.Prepend(t.at(row_index));
|
||||
}
|
||||
|
||||
return merged_table;
|
||||
|
||||
+2
-4
@@ -60,7 +60,7 @@ public:
|
||||
void Push(const NodeParam::DataType& type, const QVariant& data, const Node *from, const QString& tag = QString());
|
||||
void Prepend(const NodeValue& value);
|
||||
void Prepend(const NodeParam::DataType& type, const QVariant& data, const Node *from, const QString& tag = QString());
|
||||
const NodeValue& At(int index) const;
|
||||
const NodeValue& at(int index) const;
|
||||
NodeValue TakeAt(int index);
|
||||
int Count() const;
|
||||
bool Has(const NodeParam::DataType& type) const;
|
||||
@@ -85,9 +85,6 @@ public:
|
||||
NodeValueTable& operator[](const QString& input_id);
|
||||
NodeValueTable& operator[](const NodeInput* input);
|
||||
|
||||
const NodeValueTable operator[](const QString& input_id) const;
|
||||
const NodeValueTable operator[](const NodeInput* input) const;
|
||||
|
||||
void Insert(const QString& key, const NodeValueTable &value);
|
||||
void Insert(const NodeInput* key, const NodeValueTable& value);
|
||||
|
||||
@@ -100,6 +97,7 @@ private:
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::NodeValue)
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::NodeValueTable)
|
||||
Q_DECLARE_METATYPE(OLIVE_NAMESPACE::NodeValueDatabase)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user