mathnode: implemented add/subtract/multiply/divide/power functions

Includes implementing combobox UI for the NodeParamViewWidgetBridge.
This commit is contained in:
itsmattkc
2020-04-15 01:52:24 +10:00
parent fd1ecfae6f
commit a0a7d106dc
15 changed files with 451 additions and 88 deletions
-5
View File
@@ -22,11 +22,6 @@
OLIVE_NAMESPACE_ENTER
NodeGraph::NodeGraph()
{
}
void NodeGraph::Clear()
{
foreach (Node* node, node_children_) {
+1 -1
View File
@@ -37,7 +37,7 @@ public:
/**
* @brief NodeGraph Constructor
*/
NodeGraph();
NodeGraph() = default;
/**
* @brief Destructively destroys all nodes in the graph
+10
View File
@@ -1046,4 +1046,14 @@ QVariant NodeInput::combine_track_values_into_normal_value(const QVector<QVarian
}
}
QStringList NodeInput::get_combobox_strings() const
{
return get_property(QStringLiteral("combo_str")).toStringList();
}
void NodeInput::set_combobox_strings(const QStringList &strings)
{
set_property(QStringLiteral("combo_str"), strings);
}
OLIVE_NAMESPACE_EXIT
+4
View File
@@ -260,6 +260,10 @@ public:
QVariant combine_track_values_into_normal_value(const QVector<QVariant>& split) const;
QStringList get_combobox_strings() const;
void set_combobox_strings(const QStringList& strings);
static QString ValueToString(const DataType& data_type, const QVariant& value);
static QVariant StringToValue(const DataType &data_type, const QString &string);
+231 -58
View File
@@ -23,12 +23,13 @@
#include <QMatrix4x4>
#include <QVector2D>
#include "render/color.h"
OLIVE_NAMESPACE_ENTER
MathNode::MathNode()
{
// FIXME: Make this a combobox
method_in_ = new NodeInput(QStringLiteral("method_in"), NodeParam::kText);
method_in_ = new NodeInput(QStringLiteral("method_in"), NodeParam::kCombo);
method_in_->SetConnectable(false);
method_in_->set_is_keyframable(false);
AddInput(method_in_);
@@ -72,15 +73,16 @@ void MathNode::Retranslate()
method_in_->set_name(tr("Method"));
param_a_in_->set_name(tr("Value"));
param_b_in_->set_name(tr("Value"));
QStringList operations = {tr("Add"), tr("Subtract"), tr("Multiply"), tr("Divide")};
method_in_->set_combobox_strings(operations);
}
Node::Capabilities MathNode::GetCapabilities(const NodeValueDatabase &input) const
{
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);
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
switch (most_likely_pairing) {
switch (calc.GetMostLikelyPairing()) {
case kPairTextureColor:
case kPairTextureNumber:
case kPairTextureTexture:
@@ -97,24 +99,43 @@ QString MathNode::ShaderID(const NodeValueDatabase &input) const
{
QString method = QString::number(GetOperation());
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);
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
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());
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
{
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);
PairingCalculator calc(input[param_a_in_], input[param_b_in_]);
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();
NodeParam::DataType type_a = calc.GetMostLikelyValueA().type();
NodeParam::DataType type_b = calc.GetMostLikelyValueB().type();
QString operation;
switch (GetOperation()) {
case kOpAdd:
operation = QStringLiteral("%1 + %2");
break;
case kOpSubtract:
operation = QStringLiteral("%1 - %2");
break;
case kOpMultiply:
operation = QStringLiteral("%1 * %2");
break;
case kOpDivide:
operation = QStringLiteral("%1 / %2");
break;
case kOpPower:
operation = QStringLiteral("pow(%1, %2)");
break;
}
operation = operation.arg(GetShaderVariableCall(param_a_in_->id(), type_a),
GetShaderVariableCall(param_b_in_->id(), type_b));
return QStringLiteral("#version 110\n"
"\n"
@@ -124,26 +145,23 @@ QString MathNode::ShaderFragmentCode(const NodeValueDatabase &input) const
"uniform %2 %4;\n"
"\n"
"void main(void) {\n"
" gl_FragColor = %5 + %6;\n"
" gl_FragColor = %5;\n"
"}\n").arg(GetShaderUniformType(type_a),
GetShaderUniformType(type_b),
param_a_in_->id(),
param_b_in_->id(),
GetShaderVariableCall(param_a_in_->id(), type_a),
GetShaderVariableCall(param_b_in_->id(), type_b));
operation);
}
NodeValue MathNode::InputValueFromTable(NodeInput *input, const NodeValueDatabase &db) const
{
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);
PairingCalculator calc(db[param_a_in_], db[param_b_in_]);
if (input == param_a_in_) {
return db[input].At(pair_likelihood_a.at(most_likely_pairing));
return calc.GetMostLikelyValueA();
} else {
return db[input].At(pair_likelihood_b.at(most_likely_pairing));
return calc.GetMostLikelyValueB();
}
}
@@ -156,28 +174,26 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
// 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);
PairingCalculator calc(value[param_a_in_], value[param_b_in_]);
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 (!calc.FoundMostLikelyPairing()) {
return output;
}
switch (most_likely_pairing) {
NodeValue val_a = calc.GetMostLikelyValueA();
NodeValue val_b = calc.GetMostLikelyValueB();
switch (calc.GetMostLikelyPairing()) {
case kPairNumberNumber:
{
if (val_a.type() == NodeParam::kRational && val_b.type() == NodeParam::kRational) {
if (val_a.type() == NodeParam::kRational && val_b.type() == NodeParam::kRational && GetOperation() != kOpPower) {
// Preserve rationals
output.Push(NodeParam::kRational, QVariant::fromValue(val_a.data().value<rational>() + val_b.data().value<rational>()));
output.Push(NodeParam::kRational,
QVariant::fromValue(PerformAddSubMultDiv<rational, rational>(val_a.data().value<rational>(), val_b.data().value<rational>())));
} else {
float flt_a = RetrieveNumber(val_a);
float flt_b = RetrieveNumber(val_b);
output.Push(NodeParam::kFloat, flt_a + flt_b);
output.Push(NodeParam::kFloat,
PerformAll<float, float>(RetrieveNumber(val_a), RetrieveNumber(val_b)));
}
break;
}
@@ -186,7 +202,9 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
{
// 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));
PushVector(&output,
qMax(val_a.type(), val_b.type()),
PerformAddSubMultDiv<QVector4D, QVector4D>(RetrieveVector(val_a), RetrieveVector(val_b)));
break;
}
@@ -195,7 +213,10 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
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);
// Only valid operation is multiply
PushVector(&output,
qMax(val_a.type(), val_b.type()),
PerformMult<QVector4D, QMatrix4x4>(vec, matrix));
break;
}
@@ -204,29 +225,44 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
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);
// Only multiply and divide are valid operations
PushVector(&output, val_a.type(), PerformMultDiv<QVector4D, float>(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);
QMatrix4x4 mat_a = val_a.data().value<QMatrix4x4>();
QMatrix4x4 mat_b = val_b.data().value<QMatrix4x4>();
output.Push(NodeParam::kMatrix, PerformAddSubMult<QMatrix4x4, QMatrix4x4>(mat_a, mat_b));
break;
}
case kPairColorColor:
{
Color col_a = val_a.data().value<Color>();
Color col_b = val_b.data().value<Color>();
// Only add and subtract are valid operations
output.Push(NodeParam::kColor, QVariant::fromValue(PerformAddSub<Color, Color>(col_a, col_b)));
break;
}
case kPairNumberColor:
{
// FIXME: Still undecided on the true representation of color
Color col = (val_a.type() == NodeParam::kColor) ? val_a.data().value<Color>() : val_b.data().value<Color>();
float num = (val_a.type() == NodeParam::kColor) ? val_b.data().toFloat() : val_a.data().toFloat();
// Only multiply and divide are valid operations
output.Push(NodeParam::kColor, QVariant::fromValue(PerformMult<Color, float>(col, num)));
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>();
SampleBufferPtr samples_a = val_a.data().value<SampleBufferPtr>();
SampleBufferPtr samples_b = val_b.data().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());
@@ -236,7 +272,7 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
// 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];
mixed_samples->data()[i][j] = PerformAll<float, float>(samples_a->data()[i][j], samples_b->data()[i][j]);
}
}
@@ -255,7 +291,6 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
break;
}
case kPairNone:
case kPairCount:
case kPairTextureColor:
@@ -272,12 +307,10 @@ NodeValueTable MathNode::Value(const NodeValueDatabase &value) const
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);
PairingCalculator calc(value[param_a_in_], value[param_b_in_]);
if (most_likely_pairing == kPairSampleNumber) {
if (value[param_a_in_].At(pair_likelihood_a.at(most_likely_pairing)).type() == NodeParam::kSamples) {
if (calc.GetMostLikelyPairing() == kPairSampleNumber) {
if (calc.GetMostLikelyValueA().type() == NodeParam::kSamples) {
return param_a_in_;
} else {
return param_b_in_;
@@ -295,7 +328,7 @@ void MathNode::ProcessSamples(const NodeValueDatabase &values, const AudioRender
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;
output->data()[i][index] = PerformAll<float, float>(input->data()[i][index], number_flt);
}
}
@@ -311,7 +344,7 @@ NodeInput *MathNode::param_b_in() const
MathNode::Operation MathNode::GetOperation() const
{
return kOpAdd;
return static_cast<Operation>(method_in_->get_standard_value().toInt());
}
QString MathNode::GetShaderUniformType(const NodeParam::DataType &type)
@@ -337,7 +370,7 @@ QString MathNode::GetShaderVariableCall(const QString &input_id, const NodeParam
return input_id;
}
QVector<int> MathNode::GetPairLikelihood(const NodeValueTable &table)
QVector<int> MathNode::PairingCalculator::GetPairLikelihood(const NodeValueTable &table)
{
// FIXME: When we introduce a manual override, placing it here would be the least problematic
@@ -378,7 +411,7 @@ QVector<int> MathNode::GetPairLikelihood(const NodeValueTable &table)
return likelihood;
}
MathNode::Pairing MathNode::GetMostLikelyPairing(const QVector<int> &a, const QVector<int> &b)
MathNode::Pairing MathNode::PairingCalculator::GetMostLikelyPairingInternal(const QVector<int> &a, const QVector<int> &b)
{
QVector<int> likelihoods(kPairCount);
@@ -446,4 +479,144 @@ float MathNode::RetrieveNumber(const NodeValue &val)
}
}
MathNode::PairingCalculator::PairingCalculator(const NodeValueTable &table_a, const NodeValueTable &table_b)
{
table_a_ = table_a;
table_b_ = table_b;
pair_likelihood_a_ = GetPairLikelihood(table_a_);
pair_likelihood_b_ = GetPairLikelihood(table_b_);
most_likely_pairing_ = GetMostLikelyPairingInternal(pair_likelihood_a_, pair_likelihood_b_);
}
bool MathNode::PairingCalculator::FoundMostLikelyPairing() const
{
return (most_likely_pairing_ >= 0 && most_likely_pairing_ < kPairCount);
}
MathNode::Pairing MathNode::PairingCalculator::GetMostLikelyPairing() const
{
return most_likely_pairing_;
}
NodeValue MathNode::PairingCalculator::GetMostLikelyValueA() const
{
return GetMostLikelyValue(table_a_, pair_likelihood_a_);
}
NodeValue MathNode::PairingCalculator::GetMostLikelyValueB() const
{
return GetMostLikelyValue(table_b_, pair_likelihood_b_);
}
NodeValue MathNode::PairingCalculator::GetMostLikelyValue(const NodeValueTable &table, const QVector<int> &likelihood) const
{
return table.At(likelihood.at(most_likely_pairing_));
}
template<typename T, typename U>
T MathNode::PerformAll(T a, U b) const
{
switch (GetOperation()) {
case kOpAdd:
return a + b;
case kOpSubtract:
return a - b;
case kOpMultiply:
return a * b;
case kOpDivide:
return a / b;
case kOpPower:
return qPow(a, b);
}
return a;
}
template<typename T, typename U>
T MathNode::PerformMultDiv(T a, U b) const
{
switch (GetOperation()) {
case kOpMultiply:
return a * b;
case kOpDivide:
return a / b;
case kOpAdd:
case kOpSubtract:
case kOpPower:
break;
}
return a;
}
template<typename T, typename U>
T MathNode::PerformAddSub(T a, U b) const
{
switch (GetOperation()) {
case kOpAdd:
return a + b;
case kOpSubtract:
return a - b;
case kOpMultiply:
case kOpDivide:
case kOpPower:
break;
}
return a;
}
template<typename T, typename U>
T MathNode::PerformMult(T a, U b) const
{
switch (GetOperation()) {
case kOpMultiply:
return a * b;
case kOpAdd:
case kOpSubtract:
case kOpDivide:
case kOpPower:
break;
}
return a;
}
template<typename T, typename U>
T MathNode::PerformAddSubMult(T a, U b) const
{
switch (GetOperation()) {
case kOpAdd:
return a + b;
case kOpSubtract:
return a - b;
case kOpMultiply:
return a * b;
case kOpDivide:
case kOpPower:
break;
}
return a;
}
template<typename T, typename U>
T MathNode::PerformAddSubMultDiv(T a, U b) const
{
switch (GetOperation()) {
case kOpAdd:
return a + b;
case kOpSubtract:
return a - b;
case kOpMultiply:
return a * b;
case kOpDivide:
return a / b;
case kOpPower:
break;
}
return a;
}
OLIVE_NAMESPACE_EXIT
+50 -9
View File
@@ -56,9 +56,10 @@ public:
private:
enum Operation {
kOpAdd,
kOpSubtrack,
kOpSubtract,
kOpMultiply,
kOpDivide
kOpDivide,
kOpPower
};
Operation GetOperation() const;
@@ -84,23 +85,63 @@ private:
kPairCount
};
class PairingCalculator {
public:
PairingCalculator(const NodeValueTable& table_a, const NodeValueTable& table_b);
bool FoundMostLikelyPairing() const;
Pairing GetMostLikelyPairing() const;
NodeValue GetMostLikelyValueA() const;
NodeValue GetMostLikelyValueB() const;
private:
static Pairing GetMostLikelyPairingInternal(const QVector<int> &a, const QVector<int> &b);
static QVector<int> GetPairLikelihood(const NodeValueTable& table);
NodeValue GetMostLikelyValue(const NodeValueTable& table, const QVector<int>& likelihood) const;
Pairing most_likely_pairing_;
NodeValueTable table_a_;
NodeValueTable table_b_;
QVector<int> pair_likelihood_a_;
QVector<int> pair_likelihood_b_;
};
template<typename T, typename U>
static T OperationAdd(T a, U b);
T PerformAll(T a, U b) const;
template<typename T, typename U>
T PerformMultDiv(T a, U b) const;
template<typename T, typename U>
T PerformAddSub(T a, U b) const;
template<typename T, typename U>
T PerformMult(T a, U b) const;
template<typename T, typename U>
T PerformAddSubMult(T a, U b) const;
template<typename T, typename U>
T PerformAddSubMultDiv(T a, U b) const;
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);
static void PushVector(NodeValueTable* output, NodeParam::DataType type, const QVector4D& vec);
NodeInput* method_in_;
NodeInput* param_a_in_;
+14 -11
View File
@@ -201,6 +201,7 @@ QByteArray NodeParam::ValueToBytes(const NodeParam::DataType &type, const QVaria
case kVec2: return ValueToBytesInternal<QVector2D>(value);
case kVec3: return ValueToBytesInternal<QVector3D>(value);
case kVec4: return ValueToBytesInternal<QVector4D>(value);
case kCombo: return ValueToBytesInternal<int>(value);
// These types have no persistent input
case kNone:
@@ -223,28 +224,30 @@ NodeParam::DataType NodeParam::StringToDataType(const QString &s)
{
QString type_id = s.toLower();
if (type_id == "float") {
if (type_id == QStringLiteral("float")) {
return kFloat;
} else if (type_id == "int") {
} else if (type_id == QStringLiteral("int")) {
return kInt;
} else if (type_id == "rational") {
} else if (type_id == QStringLiteral("rational")) {
return kRational;
} else if (type_id == "bool") {
} else if (type_id == QStringLiteral("bool")) {
return kBoolean;
} else if (type_id == "color") {
} else if (type_id == QStringLiteral("color")) {
return kColor;
} else if (type_id == "matrix") {
} else if (type_id == QStringLiteral("matrix")) {
return kMatrix;
} else if (type_id == "text") {
} else if (type_id == QStringLiteral("text")) {
return kText;
} else if (type_id == "texture") {
} else if (type_id == QStringLiteral("texture")) {
return kTexture;
} else if (type_id == "vec2") {
} else if (type_id == QStringLiteral("vec2")) {
return kVec2;
} else if (type_id == "vec3") {
} else if (type_id == QStringLiteral("vec3")) {
return kVec3;
} else if (type_id == "vec4") {
} else if (type_id == QStringLiteral("vec4")) {
return kVec4;
} else if (type_id == QStringLiteral("combo")) {
return kCombo;
}
return kAny;
+7
View File
@@ -171,6 +171,13 @@ public:
*/
kVec4 = 0x4000,
/**
* ComboBox type
*
* Resolves to `int` - the index currently selected
*/
kCombo = 0x8000,
/**
****************************** BROAD IDENTIFIERS ******************************
*/
+4 -1
View File
@@ -67,7 +67,7 @@ bool OpenGLProxy::Init()
return true;
}
void OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, const TimeRange &range, NodeValueTable* table)
void OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, NodeValueTable* table)
{
// Ensure stream is video or image type
if (stream->type() != Stream::kVideo && stream->type() != Stream::kImage) {
@@ -289,6 +289,9 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, c
case NodeInput::kMatrix:
shader->setUniformValue(variable_location, value.value<QMatrix4x4>());
break;
case NodeInput::kCombo:
shader->setUniformValue(variable_location, value.value<int>());
break;
case NodeInput::kColor:
{
Color color = value.value<Color>();
+1 -1
View File
@@ -63,7 +63,7 @@ public:
void Close();
void FrameToValue(FramePtr frame, StreamPtr stream, const TimeRange &range, NodeValueTable* table);
void FrameToValue(FramePtr frame, StreamPtr stream, NodeValueTable* table);
void RunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase &input_params, NodeValueTable* output_params);
+1 -1
View File
@@ -41,7 +41,7 @@ void OpenGLWorker::FrameToValue(DecoderPtr decoder, StreamPtr stream, const Time
FramePtr frame = decoder->RetrieveVideo(range.in(), video_params().divider());
if (frame) {
emit RequestFrameToValue(frame, stream, range, table);
emit RequestFrameToValue(frame, stream, table);
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ public:
QObject* parent = nullptr);
signals:
void RequestFrameToValue(FramePtr frame, StreamPtr stream, const TimeRange &range, NodeValueTable* table);
void RequestFrameToValue(FramePtr frame, StreamPtr stream, NodeValueTable* table);
void RequestRunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase &input_params, NodeValueTable* output_params);
+64
View File
@@ -204,6 +204,70 @@ QColor Color::toQColor() const
return c;
}
const Color &Color::operator+=(const Color &rhs)
{
for (int i=0;i<kRGBAChannels;i++) {
data_[i] += rhs.data_[i];
}
return *this;
}
const Color &Color::operator-=(const Color &rhs)
{
for (int i=0;i<kRGBAChannels;i++) {
data_[i] -= rhs.data_[i];
}
return *this;
}
const Color &Color::operator*=(const float &rhs)
{
for (int i=0;i<kRGBAChannels;i++) {
data_[i] *= rhs;
}
return *this;
}
const Color &Color::operator/=(const float &rhs)
{
for (int i=0;i<kRGBAChannels;i++) {
data_[i] /= rhs;
}
return *this;
}
Color Color::operator+(const Color &rhs) const
{
Color c(*this);
c += rhs;
return c;
}
Color Color::operator-(const Color &rhs) const
{
Color c(*this);
c -= rhs;
return c;
}
Color Color::operator*(const float &rhs) const
{
Color c(*this);
c *= rhs;
return c;
}
Color Color::operator/(const float &rhs) const
{
Color c(*this);
c /= rhs;
return c;
}
OLIVE_NAMESPACE_EXIT
QDebug operator<<(QDebug debug, const OLIVE_NAMESPACE::Color &r)
+12
View File
@@ -86,6 +86,18 @@ public:
QColor toQColor() const;
// Assignment math operators
const Color& operator+=(const Color& rhs);
const Color& operator-=(const Color& rhs);
const Color& operator*=(const float& rhs);
const Color& operator/=(const float& rhs);
// Binary math operators
Color operator+(const Color& rhs) const;
Color operator-(const Color& rhs) const;
Color operator*(const float& rhs) const;
Color operator/(const float& rhs) const;
private:
float data_[kRGBAChannels];
@@ -111,6 +111,19 @@ void NodeParamViewWidgetBridge::CreateWidgets()
CreateSliders(4);
break;
}
case NodeParam::kCombo:
{
QComboBox* combobox = new QComboBox();
QStringList items = input_->get_combobox_strings();
foreach (const QString& s, items) {
combobox->addItem(s);
}
widgets_.append(combobox);
connect(combobox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &NodeParamViewWidgetBridge::WidgetCallback);
break;
}
case NodeParam::kFile:
// FIXME: File selector
break;
@@ -373,6 +386,12 @@ void NodeParamViewWidgetBridge::WidgetCallback()
SetInputValue(QVariant::fromValue(static_cast<FootageComboBox*>(sender())->SelectedFootage()), 0);
break;
}
case NodeParam::kCombo:
{
// Widget is a QComboBox
SetInputValue(static_cast<QComboBox*>(widgets_.first())->currentIndex(), 0);
break;
}
}
}
@@ -458,6 +477,11 @@ void NodeParamViewWidgetBridge::UpdateWidgetValues()
// FIXME: Implement this
break;
}
case NodeParam::kCombo:
{
static_cast<QComboBox*>(widgets_.first())->setCurrentIndex(input_->get_value_at_time(node_time).toInt());
break;
}
case NodeParam::kFootage:
static_cast<FootageComboBox*>(widgets_.first())->SetFootage(input_->get_value_at_time(node_time).value<StreamPtr>());
break;
@@ -592,6 +616,33 @@ void NodeParamViewWidgetBridge::PropertyChanged(const QString &key, const QVaria
}
}
}
// ComboBox strings changing
if (input_->data_type() & NodeParam::kCombo) {
QComboBox* cb = static_cast<QComboBox*>(widgets_.first());
int old_index = cb->currentIndex();
// Block the combobox changed signals since we anticipate the index will be the same and not require a re-render
cb->blockSignals(true);
cb->clear();
QStringList items = input_->get_combobox_strings();
foreach (const QString& s, items) {
cb->addItem(s);
}
cb->setCurrentIndex(old_index);
cb->blockSignals(false);
// In case the amount of items is LESS and the previous index cannot be set, NOW we trigger a re-cache since the
// value has changed
if (cb->currentIndex() != old_index) {
WidgetCallback();
}
}
}
OLIVE_NAMESPACE_EXIT