implemented "value hints" for choosing output values to use
This commit is contained in:
@@ -100,7 +100,7 @@ void Block::InputValueChangedEvent(const QString &input, int element)
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::HashPassthrough(const QString &input, const Node::ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
bool Block::HashPassthrough(const QString &input, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
if (IsInputConnected(input)) {
|
||||
TimeRange t = InputTimeAdjustment(input, -1, globals.time());
|
||||
|
||||
@@ -134,7 +134,7 @@ signals:
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString& input, int element) override;
|
||||
|
||||
bool HashPassthrough(const QString &input, const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const;
|
||||
bool HashPassthrough(const QString &input, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const;
|
||||
|
||||
Block* previous_;
|
||||
Block* next_;
|
||||
|
||||
@@ -266,7 +266,7 @@ void ClipBlock::Retranslate()
|
||||
|
||||
void ClipBlock::Hash(const ValueHint &out, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
HashPassthrough(kBufferIn, GetValueHintForInput(kBufferIn, -1), hash, globals, video_params);
|
||||
HashPassthrough(kBufferIn, hash, globals, video_params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -139,9 +139,9 @@ double TransitionBlock::GetInProgress(const double &time) const
|
||||
|
||||
void TransitionBlock::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const
|
||||
{
|
||||
if (HashPassthrough(kInBlockInput, GetValueHintForInput(kInBlockInput, -1), hash, globals, video_params)
|
||||
|| HashPassthrough(kOutBlockInput, GetValueHintForInput(kOutBlockInput, -1), hash, globals, video_params)) {
|
||||
HashAddNodeSignature(hash, output);
|
||||
if (HashPassthrough(kInBlockInput, hash, globals, video_params)
|
||||
|| HashPassthrough(kOutBlockInput, hash, globals, video_params)) {
|
||||
HashAddNodeSignature(hash);
|
||||
|
||||
double time_dbl = globals.time().in().toDouble();
|
||||
double all_prog = GetTotalProgress(time_dbl);
|
||||
|
||||
@@ -61,17 +61,15 @@ void TransformDistortNode::Value(const NodeValueRow &value, const NodeGlobals &g
|
||||
|
||||
// Pop texture
|
||||
NodeValue texture_meta = value[kTextureInput];
|
||||
TexturePtr texture = texture_meta.data().value<TexturePtr>();
|
||||
|
||||
bool pushed_job = false;
|
||||
|
||||
// If we have a texture, generate a matrix and make it happen
|
||||
if (texture) {
|
||||
if (TexturePtr texture = texture_meta.data().value<TexturePtr>()) {
|
||||
// Adjust our matrix by the resolutions involved
|
||||
QMatrix4x4 real_matrix = GenerateAutoScaledMatrix(generated_matrix, value, globals, texture->params());
|
||||
|
||||
if (real_matrix.isIdentity()) {
|
||||
// We don't expect any changes, just push as normal
|
||||
table->Push(texture_meta);
|
||||
} else {
|
||||
if (!real_matrix.isIdentity()) {
|
||||
// The matrix will transform things
|
||||
ShaderJob job;
|
||||
job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture), this));
|
||||
@@ -83,8 +81,15 @@ void TransformDistortNode::Value(const NodeValueRow &value, const NodeGlobals &g
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
|
||||
table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
|
||||
|
||||
pushed_job = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pushed_job) {
|
||||
// Re-push whatever value we received
|
||||
table->Push(texture_meta);
|
||||
}
|
||||
}
|
||||
|
||||
ShaderCode TransformDistortNode::GetShaderCode(const QString &shader_id) const
|
||||
@@ -328,7 +333,7 @@ void TransformDistortNode::Hash(const ValueHint &output, QCryptographicHash &has
|
||||
|
||||
if (!matrix.isIdentity()) {
|
||||
// Add fingerprint
|
||||
HashAddNodeSignature(hash, output);
|
||||
HashAddNodeSignature(hash);
|
||||
hash.addData(reinterpret_cast<const char*>(&matrix), sizeof(matrix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ void NodeGraph::childEvent(QChildEvent *event)
|
||||
connect(node, &Node::InputConnected, this, &NodeGraph::InputConnected);
|
||||
connect(node, &Node::InputDisconnected, this, &NodeGraph::InputDisconnected);
|
||||
connect(node, &Node::ValueChanged, this, &NodeGraph::ValueChanged);
|
||||
connect(node, &Node::InputValueHintChanged, this, &NodeGraph::InputValueHintChanged);
|
||||
|
||||
emit NodeAdded(node);
|
||||
emit node->AddedToGraph(this);
|
||||
@@ -110,6 +111,7 @@ void NodeGraph::childEvent(QChildEvent *event)
|
||||
disconnect(node, &Node::InputConnected, this, &NodeGraph::InputConnected);
|
||||
disconnect(node, &Node::InputDisconnected, this, &NodeGraph::InputDisconnected);
|
||||
disconnect(node, &Node::ValueChanged, this, &NodeGraph::ValueChanged);
|
||||
disconnect(node, &Node::InputValueHintChanged, this, &NodeGraph::InputValueHintChanged);
|
||||
|
||||
emit NodeRemoved(node);
|
||||
emit node->RemovedFromGraph(this);
|
||||
|
||||
@@ -129,6 +129,8 @@ signals:
|
||||
|
||||
void ValueChanged(const NodeInput& input);
|
||||
|
||||
void InputValueHintChanged(const NodeInput& input);
|
||||
|
||||
void NodePositionAdded(Node *node, Node *relative, const QPointF &position);
|
||||
|
||||
void NodePositionRemoved(Node *node, Node *relative);
|
||||
|
||||
@@ -359,6 +359,8 @@ void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QSt
|
||||
} else {
|
||||
output->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
} else {
|
||||
output->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void MergeNode::Hash(const ValueHint &output, QCryptographicHash &hash, const No
|
||||
|
||||
if (!passthrough_base && !passthrough_blend) {
|
||||
// This merge will actually do something so we add a fingerprint
|
||||
HashAddNodeSignature(hash, output);
|
||||
HashAddNodeSignature(hash);
|
||||
}
|
||||
|
||||
if (!passthrough_base) {
|
||||
|
||||
@@ -139,6 +139,28 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, uint versi
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("hints")) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("hint")) {
|
||||
QString input;
|
||||
int element;
|
||||
|
||||
XMLAttributeLoop(reader, attr) {
|
||||
if (attr.name() == QStringLiteral("input")) {
|
||||
input = attr.value().toString();
|
||||
} else if (attr.name() == QStringLiteral("element")) {
|
||||
element = attr.value().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
ValueHint vh;
|
||||
vh.Load(reader);
|
||||
|
||||
value_hints_.insert({input, element}, vh);
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
@@ -179,6 +201,19 @@ void Node::Save(QXmlStreamWriter *writer) const
|
||||
}
|
||||
writer->writeEndElement(); // connections
|
||||
|
||||
writer->writeStartElement(QStringLiteral("hints"));
|
||||
for (auto it=value_hints_.cbegin(); it!=value_hints_.cend(); it++) {
|
||||
writer->writeStartElement(QStringLiteral("hint"));
|
||||
|
||||
writer->writeAttribute(QStringLiteral("input"), it.key().input);
|
||||
writer->writeAttribute(QStringLiteral("element"), QString::number(it.key().element));
|
||||
|
||||
it.value().Save(writer);
|
||||
|
||||
writer->writeEndElement(); // hint
|
||||
}
|
||||
writer->writeEndElement();
|
||||
|
||||
writer->writeStartElement(QStringLiteral("custom"));
|
||||
SaveCustom(writer);
|
||||
writer->writeEndElement(); // custom
|
||||
@@ -980,6 +1015,15 @@ int Node::InputArraySize(const QString &id) const
|
||||
}
|
||||
}
|
||||
|
||||
void Node::SetValueHintForInput(const QString &input, int element, const ValueHint &hint)
|
||||
{
|
||||
value_hints_.insert({input, element}, hint);
|
||||
|
||||
emit InputValueHintChanged(NodeInput(this, input, element));
|
||||
|
||||
InvalidateAll(input, element);
|
||||
}
|
||||
|
||||
const NodeKeyframeTrack &Node::GetTrackFromKeyframe(NodeKeyframe *key) const
|
||||
{
|
||||
return GetImmediate(key->input(), key->element())->keyframe_tracks().at(key->track());
|
||||
@@ -1256,6 +1300,7 @@ bool Node::AreLinked(Node *a, Node *b)
|
||||
|
||||
void Node::HashAddNodeSignature(QCryptographicHash &hash) const
|
||||
{
|
||||
// Add node ID
|
||||
hash.addData(id().toUtf8());
|
||||
}
|
||||
|
||||
@@ -1529,6 +1574,9 @@ void Node::CopyValuesOfElement(const Node *src, Node *dst, const QString &input,
|
||||
if (src_element == -1 && dst_element == -1) {
|
||||
dst->ArrayResizeInternal(input, src->InputArraySize(input));
|
||||
}
|
||||
|
||||
// Copy value hint
|
||||
dst->SetValueHintForInput(input, dst_element, src->GetValueHintForInput(input, src_element));
|
||||
}
|
||||
|
||||
bool Node::CanBeDeleted() const
|
||||
@@ -2408,4 +2456,50 @@ void NodeRemovePositionFromAllContextsCommand::undo()
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ValueHint::Hash(QCryptographicHash &hash) const
|
||||
{
|
||||
// Add value hint
|
||||
foreach (NodeValue::Type t, type) {
|
||||
hash.addData(reinterpret_cast<const char*>(&t), sizeof(t));
|
||||
}
|
||||
hash.addData(reinterpret_cast<const char *>(&index), sizeof(index));
|
||||
hash.addData(tag.toUtf8());
|
||||
}
|
||||
|
||||
void Node::ValueHint::Load(QXmlStreamReader *reader)
|
||||
{
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("types")) {
|
||||
while (XMLReadNextStartElement(reader)) {
|
||||
if (reader->name() == QStringLiteral("type")) {
|
||||
type.append(static_cast<NodeValue::Type>(reader->readElementText().toInt()));
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else if (reader->name() == QStringLiteral("index")) {
|
||||
index = reader->readElementText().toInt();
|
||||
} else if (reader->name() == QStringLiteral("tag")) {
|
||||
tag = reader->readElementText();
|
||||
} else {
|
||||
reader->skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ValueHint::Save(QXmlStreamWriter *writer) const
|
||||
{
|
||||
writer->writeStartElement(QStringLiteral("types"));
|
||||
|
||||
for (auto it=type.cbegin(); it!=type.cend(); it++) {
|
||||
writer->writeTextElement(QStringLiteral("type"), QString::number(*it));
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // types
|
||||
|
||||
writer->writeTextElement(QStringLiteral("index"), QString::number(index));
|
||||
|
||||
writer->writeTextElement(QStringLiteral("tag"), tag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-4
@@ -466,6 +466,11 @@ public:
|
||||
QVector<NodeValue::Type> type;
|
||||
int index = -1;
|
||||
QString tag;
|
||||
|
||||
void Hash(QCryptographicHash &hash) const;
|
||||
|
||||
void Load(QXmlStreamReader *reader);
|
||||
void Save(QXmlStreamWriter *writer) const;
|
||||
};
|
||||
|
||||
ValueHint GetValueHintForInput(const QString &input, int element) const
|
||||
@@ -473,10 +478,7 @@ public:
|
||||
return value_hints_.value({input, element});
|
||||
}
|
||||
|
||||
void SetValueHintForInput(const QString &input, int element, const ValueHint &hint)
|
||||
{
|
||||
value_hints_.insert({input, element}, hint);
|
||||
}
|
||||
void SetValueHintForInput(const QString &input, int element, const ValueHint &hint);
|
||||
|
||||
const NodeKeyframeTrack& GetTrackFromKeyframe(NodeKeyframe* key) const;
|
||||
|
||||
@@ -965,6 +967,8 @@ signals:
|
||||
|
||||
void OutputDisconnected(Node *output, const NodeInput& input);
|
||||
|
||||
void InputValueHintChanged(const NodeInput& input);
|
||||
|
||||
void InputPropertyChanged(const QString& input, const QString& key, const QVariant& value);
|
||||
|
||||
void LinksChanged();
|
||||
@@ -1519,4 +1523,6 @@ private:
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::Node::ValueHint);
|
||||
|
||||
#endif // NODE_H
|
||||
|
||||
@@ -221,6 +221,7 @@ uint qHash(const NodeKeyframeTrackReference& i);
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::NodeInput)
|
||||
Q_DECLARE_METATYPE(olive::NodeKeyframeTrackReference)
|
||||
|
||||
#endif // NODEPARAM_H
|
||||
|
||||
+19
-7
@@ -48,7 +48,8 @@ NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node
|
||||
NodeValueRow row;
|
||||
for (auto it=database->begin(); it!=database->end(); it++) {
|
||||
// Get hint for which value should be pulled
|
||||
row.insert(it.key(), GenerateRowValue(node, it.key(), &it.value()));
|
||||
NodeValue value = GenerateRowValue(node, it.key(), &it.value());
|
||||
row.insert(it.key(), value);
|
||||
}
|
||||
|
||||
return row;
|
||||
@@ -82,6 +83,17 @@ NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input
|
||||
}
|
||||
|
||||
NodeValue NodeTraverser::GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table)
|
||||
{
|
||||
int value_index = GenerateRowValueElementIndex(node, input, element, table);
|
||||
|
||||
if (value_index == -1) {
|
||||
return NodeValue();
|
||||
} else {
|
||||
return table->TakeAt(value_index);
|
||||
}
|
||||
}
|
||||
|
||||
int NodeTraverser::GenerateRowValueElementIndex(const Node *node, const QString &input, int element, const NodeValueTable *table)
|
||||
{
|
||||
Node::ValueHint hint = node->GetValueHintForInput(input, element);
|
||||
QVector<NodeValue::Type> types = hint.type;
|
||||
@@ -92,23 +104,23 @@ NodeValue NodeTraverser::GenerateRowValueElement(const Node *node, const QString
|
||||
|
||||
if (hint.index == -1) {
|
||||
// Get most recent value with this type and tag
|
||||
return table->TakeWithMeta(types, hint.tag);
|
||||
return table->GetValueIndex(types, hint.tag);
|
||||
} else {
|
||||
// Try to find value at this index
|
||||
int index = table->Count() - hint.index;
|
||||
int index = table->Count() - 1 - hint.index;
|
||||
int diff = 0;
|
||||
|
||||
while (index + diff < table->Count() && index - diff >= 0) {
|
||||
if (index + diff < table->Count() && types.contains(table->at(index + diff).type())) {
|
||||
return table->TakeAt(index + diff);
|
||||
return index + diff;
|
||||
}
|
||||
if (index - diff >= 0 && types.contains(table->at(index - diff).type())) {
|
||||
return table->TakeAt(index - diff);
|
||||
return index - diff;
|
||||
}
|
||||
diff++;
|
||||
}
|
||||
|
||||
return NodeValue();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +282,7 @@ QVariant NodeTraverser::ProcessSamples(const Node *node, const TimeRange &range,
|
||||
Q_UNUSED(range)
|
||||
Q_UNUSED(job)
|
||||
|
||||
return QVariant();
|
||||
return QVariant::fromValue(SampleBuffer::Create());
|
||||
}
|
||||
|
||||
QVariant NodeTraverser::ProcessFrameGeneration(const Node *node, const GenerateJob &job)
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
|
||||
NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table);
|
||||
NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table);
|
||||
int GenerateRowValueElementIndex(const Node *node, const QString &input, int element, const NodeValueTable *table);
|
||||
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time);
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time)
|
||||
|
||||
+3
-3
@@ -326,7 +326,7 @@ QString NodeValue::GetPrettyDataTypeName(Type type)
|
||||
|
||||
NodeValue NodeValueTable::GetWithMeta(const QVector<NodeValue::Type> &type, const QString &tag) const
|
||||
{
|
||||
int value_index = GetInternal(type, tag);
|
||||
int value_index = GetValueIndex(type, tag);
|
||||
|
||||
if (value_index >= 0) {
|
||||
return values_.at(value_index);
|
||||
@@ -337,7 +337,7 @@ NodeValue NodeValueTable::GetWithMeta(const QVector<NodeValue::Type> &type, cons
|
||||
|
||||
NodeValue NodeValueTable::TakeWithMeta(const QVector<NodeValue::Type> &type, const QString &tag)
|
||||
{
|
||||
int value_index = GetInternal(type, tag);
|
||||
int value_index = GetValueIndex(type, tag);
|
||||
|
||||
if (value_index >= 0) {
|
||||
return values_.takeAt(value_index);
|
||||
@@ -407,7 +407,7 @@ NodeValueTable NodeValueTable::Merge(QList<NodeValueTable> tables)
|
||||
return merged_table;
|
||||
}
|
||||
|
||||
int NodeValueTable::GetInternal(const QVector<NodeValue::Type>& types, const QString &tag) const
|
||||
int NodeValueTable::GetValueIndex(const QVector<NodeValue::Type>& types, const QString &tag) const
|
||||
{
|
||||
int index = -1;
|
||||
|
||||
|
||||
+2
-2
@@ -391,11 +391,11 @@ public:
|
||||
return values_.isEmpty();
|
||||
}
|
||||
|
||||
int GetValueIndex(const QVector<NodeValue::Type> &type, const QString& tag) const;
|
||||
|
||||
static NodeValueTable Merge(QList<NodeValueTable> tables);
|
||||
|
||||
private:
|
||||
int GetInternal(const QVector<NodeValue::Type> &type, const QString& tag) const;
|
||||
|
||||
QVector<NodeValue> values_;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user