implemented "value hints" for choosing output values to use

This commit is contained in:
itsmattkc
2021-09-17 20:56:53 -07:00
parent a5e7859e1f
commit 67c7c71ca2
30 changed files with 439 additions and 85 deletions
+1 -1
View File
@@ -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());
+1 -1
View File
@@ -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_;
+1 -1
View File
@@ -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);
}
}
+3 -3
View File
@@ -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));
}
}
+2
View File
@@ -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);
+2
View File
@@ -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);
+2
View File
@@ -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;
}
+1 -1
View File
@@ -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) {
+94
View File
@@ -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
View File
@@ -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
+1
View File
@@ -221,6 +221,7 @@ uint qHash(const NodeKeyframeTrackReference& i);
}
Q_DECLARE_METATYPE(olive::NodeInput)
Q_DECLARE_METATYPE(olive::NodeKeyframeTrackReference)
#endif // NODEPARAM_H
+19 -7
View File
@@ -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)
+1
View File
@@ -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 &params, const TimeRange &time);
static NodeGlobals GenerateGlobals(const VideoParams &params, const rational &time)
+3 -3
View File
@@ -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
View File
@@ -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_;
};