mathnode: expanded math node
Implemented handling of various different types.
This commit is contained in:
@@ -42,19 +42,19 @@ Node::Capabilities PanNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
return kSampleProcessor;
|
||||
}
|
||||
|
||||
NodeInput *PanNode::ProcessesSamplesFrom() const
|
||||
NodeInput *PanNode::ProcessesSamplesFrom(const NodeValueDatabase &value) const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
void PanNode::ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void PanNode::ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams ¶ms, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
if (params.channel_count() != 2) {
|
||||
// This node currently only works for stereo audio
|
||||
return;
|
||||
}
|
||||
|
||||
float pan_val = (*values)[panning_input_].Get(NodeParam::kFloat).toFloat();
|
||||
float pan_val = values[panning_input_].Get(NodeParam::kFloat).toFloat();
|
||||
|
||||
for (int i=0;i<params.channel_count();i++) {
|
||||
output->data()[i][index] = input->data()[i][index];
|
||||
|
||||
@@ -16,8 +16,8 @@ public:
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom() const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase* values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ Node::Capabilities VolumeNode::GetCapabilities(const NodeValueDatabase &) const
|
||||
return kSampleProcessor;
|
||||
}
|
||||
|
||||
NodeInput *VolumeNode::ProcessesSamplesFrom() const
|
||||
NodeInput *VolumeNode::ProcessesSamplesFrom(const NodeValueDatabase &value) const
|
||||
{
|
||||
return samples_input_;
|
||||
}
|
||||
|
||||
void VolumeNode::ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
void VolumeNode::ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const
|
||||
{
|
||||
float volume_val = (*values)[volume_input_].Get(NodeParam::kFloat).toFloat();
|
||||
float volume_val = values[volume_input_].Get(NodeParam::kFloat).toFloat();
|
||||
|
||||
for (int i=0;i<params.channel_count();i++) {
|
||||
output->data()[i][index] = input->data()[i][index] * volume_val;
|
||||
|
||||
@@ -16,8 +16,8 @@ public:
|
||||
virtual QString Description() const override;
|
||||
|
||||
virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom() const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase* values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase& values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
|
||||
+291
-45
@@ -1,5 +1,8 @@
|
||||
#include "math.h"
|
||||
|
||||
#include <QMatrix4x4>
|
||||
#include <QVector2D>
|
||||
|
||||
MathNode::MathNode()
|
||||
{
|
||||
// FIXME: Make this a combobox
|
||||
@@ -49,28 +52,44 @@ void MathNode::Retranslate()
|
||||
|
||||
Node::Capabilities MathNode::GetCapabilities(const NodeValueDatabase &input) const
|
||||
{
|
||||
if (input[param_a_in_].Has(NodeParam::kTexture) || input[param_b_in_].Has(NodeParam::kTexture)) {
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(input[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(input[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
switch (most_likely_pairing) {
|
||||
case kPairTextureColor:
|
||||
case kPairTextureNumber:
|
||||
case kPairTextureTexture:
|
||||
return kShader;
|
||||
} else {
|
||||
case kPairSampleNumber:
|
||||
return kSampleProcessor;
|
||||
default:
|
||||
return kNormal;
|
||||
}
|
||||
}
|
||||
|
||||
QString MathNode::ShaderID(const NodeValueDatabase &input) const
|
||||
{
|
||||
// FIXME: Hardcoded ADD operation
|
||||
QString method = QString::number(0);
|
||||
QString method = QString::number(GetOperation());
|
||||
|
||||
QString type_a = QString::number(GuessTypeFromTable(input[param_a_in_]));
|
||||
QString type_b = QString::number(GuessTypeFromTable(input[param_b_in_]));
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(input[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(input[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
QString type_a = QString::number(input[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing)).type());
|
||||
QString type_b = QString::number(input[param_b_in_].At(pair_likelihood_b.at(most_likely_pairing)).type());
|
||||
|
||||
return id().append(method).append(type_a).append(type_b);
|
||||
}
|
||||
|
||||
QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
{
|
||||
NodeParam::DataType type_a = GuessTypeFromTable(input[param_a_in_]);
|
||||
NodeParam::DataType type_b = GuessTypeFromTable(input[param_b_in_]);
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(input[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(input[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
NodeParam::DataType type_a = input[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing)).type();
|
||||
NodeParam::DataType type_b = input[param_b_in_].At(pair_likelihood_b.at(most_likely_pairing)).type();
|
||||
|
||||
return QStringLiteral("#version 110\n"
|
||||
"\n"
|
||||
@@ -81,58 +100,179 @@ QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
|
||||
"\n"
|
||||
"void main(void) {\n"
|
||||
" gl_FragColor = %5 + %6;\n"
|
||||
"}\n").arg(GetUniformTypeFromType(type_a),
|
||||
GetUniformTypeFromType(type_b),
|
||||
"}\n").arg(GetShaderUniformType(type_a),
|
||||
GetShaderUniformType(type_b),
|
||||
param_a_in_->id(),
|
||||
param_b_in_->id(),
|
||||
GetVariableCall(param_a_in_->id(), type_a),
|
||||
GetVariableCall(param_b_in_->id(), type_b));
|
||||
GetShaderVariableCall(param_a_in_->id(), type_a),
|
||||
GetShaderVariableCall(param_b_in_->id(), type_b));
|
||||
}
|
||||
|
||||
NodeValue MathNode::InputValueFromTable(NodeInput *input, const NodeValueTable &table) const
|
||||
NodeValue MathNode::InputValueFromTable(NodeInput *input, const NodeValueDatabase &db) const
|
||||
{
|
||||
if (input->IsConnected()
|
||||
&& (input == param_a_in_ || input == param_b_in_)
|
||||
&& table.Has(NodeParam::kTexture)) {
|
||||
return table.GetWithMeta(NodeParam::kTexture);
|
||||
if (input == param_a_in_ || input == param_b_in_) {
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(db[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(db[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
if (input == param_a_in_) {
|
||||
return db[input].At(pair_likelihood_a.at(most_likely_pairing));
|
||||
} else {
|
||||
return db[input].At(pair_likelihood_b.at(most_likely_pairing));
|
||||
}
|
||||
}
|
||||
|
||||
return Node::InputValueFromTable(input, table);
|
||||
return Node::InputValueFromTable(input, db);
|
||||
}
|
||||
|
||||
NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
|
||||
{
|
||||
NodeValueTable output = value.Merge();
|
||||
|
||||
if (value[param_a_in_].Has(NodeParam::kSamples) && value[param_b_in_].Has(NodeParam::kSamples)) {
|
||||
QByteArray samples_a_bytes = value[param_a_in_].Get(NodeParam::kSamples).toByteArray();
|
||||
QByteArray samples_b_bytes = value[param_b_in_].Get(NodeParam::kSamples).toByteArray();
|
||||
// Auto-detect what values to operate with
|
||||
// FIXME: Add manual override for this
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(value[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(value[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
QByteArray mixed_bytes;
|
||||
NodeValue val_a, val_b;
|
||||
if (most_likely_pairing >= 0 && most_likely_pairing < kPairCount) {
|
||||
val_a = value[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing));
|
||||
val_b = value[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing));
|
||||
}
|
||||
|
||||
if (samples_a_bytes.size() > samples_b_bytes.size()) {
|
||||
mixed_bytes = samples_a_bytes;
|
||||
switch (most_likely_pairing) {
|
||||
|
||||
case kPairNumberNumber:
|
||||
{
|
||||
if (val_a.type() == NodeParam::kRational && val_b.type() == NodeParam::kRational) {
|
||||
// Preserve rationals
|
||||
output.Push(NodeParam::kRational, QVariant::fromValue(val_a.data().value<rational>() + val_b.data().value<rational>()));
|
||||
} else {
|
||||
mixed_bytes = samples_b_bytes;
|
||||
float flt_a = RetrieveNumber(val_a);
|
||||
float flt_b = RetrieveNumber(val_b);
|
||||
|
||||
output.Push(NodeParam::kFloat, flt_a + flt_b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairVecVec:
|
||||
{
|
||||
// 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, qMax(val_a.type(), val_b.type()), RetrieveVector(val_a) + RetrieveVector(val_b));
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairMatrixVec:
|
||||
{
|
||||
QMatrix4x4 matrix = (val_a.type() == NodeParam::kMatrix) ? val_a.data().value<QMatrix4x4>() : val_b.data().value<QMatrix4x4>();
|
||||
QVector4D vec = (val_a.type() == NodeParam::kMatrix) ? RetrieveVector(val_b) : RetrieveVector(val_a);
|
||||
|
||||
PushVector(&output, qMax(val_a.type(), val_b.type()), vec * matrix);
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairVecNumber:
|
||||
{
|
||||
QVector4D vec = (val_a.type() & NodeParam::kVector) ? RetrieveVector(val_a) : RetrieveVector(val_b);
|
||||
float number = RetrieveNumber((val_a.type() & NodeParam::kMatrix) ? val_b : val_a);
|
||||
|
||||
PushVector(&output, val_a.type(), vec * number);
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairMatrixMatrix:
|
||||
{
|
||||
QMatrix4x4 mat_a = value[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing)).data().value<QMatrix4x4>();
|
||||
QMatrix4x4 mat_b = value[param_b_in_].At(pair_likelihood_b.at(most_likely_pairing)).data().value<QMatrix4x4>();
|
||||
output.Push(NodeParam::kMatrix, mat_a + mat_b);
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairColorColor:
|
||||
case kPairNumberColor:
|
||||
{
|
||||
// FIXME: Still undecided on the true representation of color
|
||||
break;
|
||||
}
|
||||
|
||||
case kPairSampleSample:
|
||||
{
|
||||
SampleBufferPtr samples_a = value[param_a_in_].Get(NodeParam::kSamples).value<SampleBufferPtr>();
|
||||
SampleBufferPtr samples_b = value[param_b_in_].Get(NodeParam::kSamples).value<SampleBufferPtr>();
|
||||
|
||||
int max_samples = qMax(samples_a->sample_count_per_channel(), samples_b->sample_count_per_channel());
|
||||
int min_samples = qMin(samples_a->sample_count_per_channel(), samples_b->sample_count_per_channel());
|
||||
|
||||
SampleBufferPtr mixed_samples = SampleBuffer::CreateAllocated(samples_a->audio_params(), max_samples);
|
||||
|
||||
// Mix samples that are in both buffers
|
||||
for (int i=0;i<mixed_samples->audio_params().channel_count();i++) {
|
||||
for (int j=0;j<min_samples;j++) {
|
||||
mixed_samples->data()[i][j] = samples_a->data()[i][j] + samples_b->data()[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Assumes float
|
||||
float* samples_a = reinterpret_cast<float*>(samples_a_bytes.data());
|
||||
float* samples_b = reinterpret_cast<float*>(samples_b_bytes.data());
|
||||
float* mixed = reinterpret_cast<float*>(mixed_bytes.data());
|
||||
if (max_samples > min_samples) {
|
||||
// Fill in remainder space with 0s
|
||||
int remainder = max_samples - min_samples;
|
||||
|
||||
int nb_samples = qMin(samples_a_bytes.size(), samples_b_bytes.size()) / sizeof(float);
|
||||
|
||||
for (int i=0;i<nb_samples;i++) {
|
||||
mixed[i] = samples_a[i] + samples_b[i];
|
||||
for (int i=0;i<mixed_samples->audio_params().channel_count();i++) {
|
||||
memset(mixed_samples->data()[i] + min_samples * sizeof(float),
|
||||
0,
|
||||
remainder * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
output.Push(NodeParam::kSamples, mixed_bytes);
|
||||
output.Push(NodeParam::kSamples, QVariant::fromValue(mixed_samples));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case kPairNone:
|
||||
case kPairCount:
|
||||
case kPairTextureColor:
|
||||
case kPairTextureNumber:
|
||||
case kPairTextureTexture:
|
||||
case kPairSampleNumber:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
NodeInput *MathNode::ProcessesSamplesFrom(const NodeValueDatabase &value) const
|
||||
{
|
||||
QVector<int> pair_likelihood_a = GetPairLikelihood(value[param_a_in_]);
|
||||
QVector<int> pair_likelihood_b = GetPairLikelihood(value[param_b_in_]);
|
||||
Pairing most_likely_pairing = GetMostLikelyPairing(pair_likelihood_a, pair_likelihood_b);
|
||||
|
||||
if (most_likely_pairing == kPairSampleNumber) {
|
||||
if (value[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing)).type() == NodeParam::kSamples) {
|
||||
return param_a_in_;
|
||||
} else {
|
||||
return param_b_in_;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MathNode::ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams ¶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++) {
|
||||
output->data()[i][index] = input->data()[i][index] + number_flt;
|
||||
}
|
||||
}
|
||||
|
||||
NodeInput *MathNode::param_a_in() const
|
||||
{
|
||||
return param_a_in_;
|
||||
@@ -143,25 +283,24 @@ NodeInput *MathNode::param_b_in() const
|
||||
return param_b_in_;
|
||||
}
|
||||
|
||||
NodeParam::DataType MathNode::GuessTypeFromTable(const NodeValueTable &table)
|
||||
MathNode::Operation MathNode::GetOperation() const
|
||||
{
|
||||
if (table.Has(NodeParam::kTexture)) {
|
||||
return NodeParam::kTexture;
|
||||
} else {
|
||||
return NodeParam::kFloat;
|
||||
}
|
||||
return kOpAdd;
|
||||
}
|
||||
|
||||
QString MathNode::GetUniformTypeFromType(const NodeParam::DataType &type)
|
||||
QString MathNode::GetShaderUniformType(const NodeParam::DataType &type)
|
||||
{
|
||||
if (type == NodeParam::kTexture) {
|
||||
switch (type) {
|
||||
case NodeParam::kTexture:
|
||||
return QStringLiteral("sampler2D");
|
||||
case NodeParam::kColor:
|
||||
return QStringLiteral("vec4");
|
||||
default:
|
||||
return QStringLiteral("float");
|
||||
}
|
||||
|
||||
return QStringLiteral("float");
|
||||
}
|
||||
|
||||
QString MathNode::GetVariableCall(const QString &input_id, const NodeParam::DataType &type)
|
||||
QString MathNode::GetShaderVariableCall(const QString &input_id, const NodeParam::DataType &type)
|
||||
{
|
||||
if (type == NodeParam::kTexture) {
|
||||
return QStringLiteral("texture2D(%1, ove_texcoord)").arg(input_id);
|
||||
@@ -169,3 +308,110 @@ QString MathNode::GetVariableCall(const QString &input_id, const NodeParam::Data
|
||||
|
||||
return input_id;
|
||||
}
|
||||
|
||||
QVector<int> MathNode::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++) {
|
||||
NodeParam::DataType type = table.At(i).type();
|
||||
|
||||
if (type & NodeParam::kVector) {
|
||||
likelihood.replace(kPairVecVec, i);
|
||||
likelihood.replace(kPairVecNumber, i);
|
||||
likelihood.replace(kPairMatrixVec, i);
|
||||
} else if (type & NodeParam::kMatrix) {
|
||||
likelihood.replace(kPairMatrixMatrix, i);
|
||||
likelihood.replace(kPairMatrixVec, i);
|
||||
} else if (type & NodeParam::kColor) {
|
||||
likelihood.replace(kPairColorColor, i);
|
||||
likelihood.replace(kPairNumberColor, i);
|
||||
likelihood.replace(kPairTextureColor, i);
|
||||
} else if (type & NodeParam::kNumber) {
|
||||
likelihood.replace(kPairNumberNumber, i);
|
||||
likelihood.replace(kPairVecNumber, i);
|
||||
likelihood.replace(kPairNumberColor, i);
|
||||
likelihood.replace(kPairTextureNumber, i);
|
||||
likelihood.replace(kPairSampleNumber, i);
|
||||
} else if (type & NodeParam::kSamples) {
|
||||
likelihood.replace(kPairSampleSample, i);
|
||||
likelihood.replace(kPairSampleNumber, i);
|
||||
} else if (type & NodeParam::kTexture) {
|
||||
likelihood.replace(kPairTextureTexture, i);
|
||||
likelihood.replace(kPairTextureNumber, i);
|
||||
likelihood.replace(kPairTextureColor, i);
|
||||
}
|
||||
}
|
||||
|
||||
return likelihood;
|
||||
}
|
||||
|
||||
MathNode::Pairing MathNode::GetMostLikelyPairing(const QVector<int> &a, const QVector<int> &b)
|
||||
{
|
||||
QVector<int> likelihoods(kPairCount);
|
||||
|
||||
for (int i=0;i<likelihoods.size();i++) {
|
||||
if (a.at(i) == -1 || b.at(i) == -1) {
|
||||
likelihoods.replace(i, -1);
|
||||
} else {
|
||||
likelihoods.replace(i, a.at(i) + b.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
Pairing pairing = kPairNone;
|
||||
|
||||
for (int i=0;i<likelihoods.size();i++) {
|
||||
//qDebug() << "Likelihood" << i << "is" << likelihoods.at(i);
|
||||
|
||||
if (likelihoods.at(i) > -1) {
|
||||
if (pairing == kPairNone
|
||||
|| likelihoods.at(i) > likelihoods.at(pairing)) {
|
||||
pairing = static_cast<Pairing>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pairing;
|
||||
}
|
||||
|
||||
QVector4D MathNode::RetrieveVector(const NodeValue &val)
|
||||
{
|
||||
// QVariant doesn't know that QVector*D can convert themselves so we do it here
|
||||
switch (val.type()) {
|
||||
case NodeParam::kVec2:
|
||||
return val.data().value<QVector2D>();
|
||||
case NodeParam::kVec3:
|
||||
return val.data().value<QVector3D>();
|
||||
case NodeParam::kVec4:
|
||||
default:
|
||||
return val.data().value<QVector4D>();
|
||||
}
|
||||
}
|
||||
|
||||
void MathNode::PushVector(NodeValueTable *output, NodeParam::DataType type, const QVector4D &vec)
|
||||
{
|
||||
switch (type) {
|
||||
case NodeParam::kVec2:
|
||||
output->Push(type, QVector2D(vec));
|
||||
break;
|
||||
case NodeParam::kVec3:
|
||||
output->Push(type, QVector3D(vec));
|
||||
break;
|
||||
case NodeParam::kVec4:
|
||||
output->Push(type, vec);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float MathNode::RetrieveNumber(const NodeValue &val)
|
||||
{
|
||||
if (val.type() == NodeParam::kRational) {
|
||||
return val.data().value<rational>().toDouble();
|
||||
} else {
|
||||
return val.data().toFloat();
|
||||
}
|
||||
}
|
||||
|
||||
+40
-4
@@ -21,10 +21,13 @@ public:
|
||||
virtual QString ShaderID(const NodeValueDatabase&) const override;
|
||||
virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
|
||||
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, const NodeValueTable& table) const override;
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, const NodeValueDatabase &db) const override;
|
||||
|
||||
virtual NodeValueTable Value(const NodeValueDatabase& value) const override;
|
||||
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const override;
|
||||
virtual void ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const override;
|
||||
|
||||
NodeInput* param_a_in() const;
|
||||
NodeInput* param_b_in() const;
|
||||
|
||||
@@ -36,11 +39,44 @@ private:
|
||||
kOpDivide
|
||||
};
|
||||
|
||||
static NodeParam::DataType GuessTypeFromTable(const NodeValueTable& table);
|
||||
Operation GetOperation() const;
|
||||
|
||||
static QString GetUniformTypeFromType(const NodeParam::DataType& type);
|
||||
enum Pairing {
|
||||
kPairNone = -1,
|
||||
|
||||
static QString GetVariableCall(const QString& input_id, const NodeParam::DataType& type);
|
||||
kPairNumberNumber,
|
||||
kPairVecVec,
|
||||
kPairMatrixMatrix,
|
||||
kPairColorColor,
|
||||
kPairTextureTexture,
|
||||
|
||||
kPairVecNumber,
|
||||
kPairMatrixVec,
|
||||
kPairNumberColor,
|
||||
kPairTextureNumber,
|
||||
kPairTextureColor,
|
||||
kPairSampleSample,
|
||||
kPairSampleNumber,
|
||||
|
||||
kPairCount
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
static T OperationAdd(T a, U b);
|
||||
|
||||
static QString GetShaderUniformType(const NodeParam::DataType& type);
|
||||
|
||||
static QString GetShaderVariableCall(const QString& input_id, const NodeParam::DataType& type);
|
||||
|
||||
static QVector<int> GetPairLikelihood(const NodeValueTable& table);
|
||||
|
||||
static Pairing GetMostLikelyPairing(const QVector<int> &a, const QVector<int> &b);
|
||||
|
||||
static QVector4D RetrieveVector(const NodeValue& val);
|
||||
|
||||
static void PushVector(NodeValueTable* output, NodeParam::DataType type, const QVector4D& vec);
|
||||
|
||||
static float RetrieveNumber(const NodeValue& val);
|
||||
|
||||
NodeInput* method_in_;
|
||||
|
||||
|
||||
+4
-4
@@ -477,12 +477,12 @@ NodeInput *Node::ShaderIterativeInput() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeInput* Node::ProcessesSamplesFrom() const
|
||||
NodeInput* Node::ProcessesSamplesFrom(const NodeValueDatabase &value) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Node::ProcessSamples(const NodeValueDatabase*, const AudioRenderingParams&, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
void Node::ProcessSamples(const NodeValueDatabase &, const AudioRenderingParams&, const SampleBufferPtr, SampleBufferPtr, int) const
|
||||
{
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ NodeOutput *Node::output() const
|
||||
return output_;
|
||||
}
|
||||
|
||||
NodeValue Node::InputValueFromTable(NodeInput *input, const NodeValueTable &table) const
|
||||
NodeValue Node::InputValueFromTable(NodeInput *input, const NodeValueDatabase &db) const
|
||||
{
|
||||
NodeParam::DataType find_data_type = input->data_type();
|
||||
|
||||
@@ -624,7 +624,7 @@ NodeValue Node::InputValueFromTable(NodeInput *input, const NodeValueTable &tabl
|
||||
}
|
||||
|
||||
// Try to get a value from it
|
||||
return table.GetWithMeta(find_data_type);
|
||||
return db[input].GetWithMeta(find_data_type);
|
||||
}
|
||||
|
||||
const QPointF &Node::GetPosition()
|
||||
|
||||
+3
-3
@@ -186,12 +186,12 @@ public:
|
||||
/**
|
||||
* @brief Return whether this node processes samples or not
|
||||
*/
|
||||
virtual NodeInput* ProcessesSamplesFrom() const;
|
||||
virtual NodeInput* ProcessesSamplesFrom(const NodeValueDatabase &value) const;
|
||||
|
||||
/**
|
||||
* @brief If ProcessesSamples() is true, this is the function that will process them.
|
||||
*/
|
||||
virtual void ProcessSamples(const NodeValueDatabase *values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
virtual void ProcessSamples(const NodeValueDatabase &values, const AudioRenderingParams& params, const SampleBufferPtr input, SampleBufferPtr output, int index) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the parameter with the specified ID (or nullptr if it doesn't exist)
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
|
||||
NodeOutput* output() const;
|
||||
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, const NodeValueTable& table) const;
|
||||
virtual NodeValue InputValueFromTable(NodeInput* input, const NodeValueDatabase& db) const;
|
||||
|
||||
const QPointF& GetPosition();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
class NodeValue
|
||||
{
|
||||
public:
|
||||
NodeValue() = default;
|
||||
NodeValue(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString());
|
||||
|
||||
const NodeParam::DataType& type() const;
|
||||
|
||||
@@ -31,9 +31,10 @@ void AudioWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
|
||||
// Copy database so we can make some temporary modifications to it
|
||||
NodeValueDatabase input_params = input_params_in;
|
||||
NodeInput* sample_input = node->ProcessesSamplesFrom(input_params);
|
||||
|
||||
// Try to find the sample buffer in the table
|
||||
QVariant samples_var = input_params[node->ProcessesSamplesFrom()].Get(NodeParam::kSamples);
|
||||
QVariant samples_var = input_params[sample_input].Get(NodeParam::kSamples);
|
||||
|
||||
// If there isn't one, there's nothing to do
|
||||
if (samples_var.isNull()) {
|
||||
@@ -41,6 +42,11 @@ void AudioWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
}
|
||||
|
||||
SampleBufferPtr input_buffer = samples_var.value<SampleBufferPtr>();
|
||||
|
||||
if (!input_buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SampleBufferPtr output_buffer = SampleBuffer::CreateAllocated(input_buffer->audio_params(), input_buffer->sample_count_per_channel());
|
||||
|
||||
int sample_count = input_buffer->sample_count_per_channel();
|
||||
@@ -56,7 +62,7 @@ void AudioWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
// Update all non-sample and non-footage inputs
|
||||
foreach (NodeParam* param, node->parameters()) {
|
||||
if (param->type() == NodeParam::kInput
|
||||
&& param != node->ProcessesSamplesFrom()) {
|
||||
&& param != sample_input) {
|
||||
NodeInput* input = static_cast<NodeInput*>(param);
|
||||
|
||||
// If the input isn't keyframing, we don't need to update it unless it's connected, in which case it may change
|
||||
@@ -66,7 +72,7 @@ void AudioWorker::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
}
|
||||
}
|
||||
|
||||
node->ProcessSamples(&input_params,
|
||||
node->ProcessSamples(input_params,
|
||||
audio_params(),
|
||||
input_buffer,
|
||||
output_buffer,
|
||||
|
||||
@@ -240,9 +240,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
NodeInput* input = static_cast<NodeInput*>(param);
|
||||
|
||||
// Get value from database at this input
|
||||
const NodeValueTable& input_data = input_params[input];
|
||||
|
||||
NodeValue meta_value = node->InputValueFromTable(input, input_data);
|
||||
NodeValue meta_value = node->InputValueFromTable(input, input_params);
|
||||
const QVariant& value = meta_value.data();
|
||||
|
||||
switch (meta_value.type()) {
|
||||
|
||||
Reference in New Issue
Block a user