implemented gizmo transforming through the node graph
This commit is contained in:
@@ -79,10 +79,12 @@ void CropDistortNode::Value(const NodeValueRow &value, const NodeGlobals &global
|
||||
{
|
||||
ShaderJob job;
|
||||
job.Insert(value);
|
||||
job.Insert(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this));
|
||||
job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
|
||||
job.SetWillChangeImageSize(false);
|
||||
|
||||
if (TexturePtr texture = job.Get(kTextureInput).toTexture()) {
|
||||
job.Insert(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, QVector2D(texture->params().width(), texture->params().height()), this));
|
||||
|
||||
if (job.Get(kTextureInput).toTexture()) {
|
||||
if (!qIsNull(job.Get(kLeftInput).toDouble())
|
||||
|| !qIsNull(job.Get(kRightInput).toDouble())
|
||||
|| !qIsNull(job.Get(kTopInput).toDouble())
|
||||
|
||||
@@ -84,7 +84,7 @@ void TransformDistortNode::Retranslate()
|
||||
void TransformDistortNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
// Generate matrix
|
||||
QMatrix4x4 generated_matrix = GenerateMatrix(value, true, false, false, false);
|
||||
QMatrix4x4 generated_matrix = GenerateMatrix(value, false, false, false);
|
||||
|
||||
// Pop texture
|
||||
NodeValue texture_meta = value[kTextureInput];
|
||||
@@ -143,7 +143,7 @@ void TransformDistortNode::Hash(QCryptographicHash &hash, const NodeGlobals &glo
|
||||
TexturePtr tex = db[kTextureInput].toTexture();
|
||||
if (tex) {
|
||||
VideoParams tex_params = tex->params();
|
||||
QMatrix4x4 matrix = GenerateMatrix(db, true, false, false, false);
|
||||
QMatrix4x4 matrix = GenerateMatrix(db, false, false, false);
|
||||
matrix = GenerateAutoScaledMatrix(matrix, db, globals, tex_params);
|
||||
|
||||
if (!matrix.isIdentity()) {
|
||||
@@ -162,7 +162,7 @@ void TransformDistortNode::GizmoDragStart(const NodeValueRow &row, double x, dou
|
||||
|
||||
if (gizmo == anchor_gizmo_) {
|
||||
|
||||
gizmo_inverted_transform_ = GenerateMatrix(row, false, true, true, false).toTransform().inverted();
|
||||
gizmo_inverted_transform_ = GenerateMatrix(row, true, true, false).toTransform().inverted();
|
||||
|
||||
} else if (IsAScaleGizmo(gizmo)) {
|
||||
|
||||
@@ -204,7 +204,7 @@ void TransformDistortNode::GizmoDragStart(const NodeValueRow &row, double x, dou
|
||||
}
|
||||
|
||||
// Store current matrix
|
||||
gizmo_inverted_transform_ = GenerateMatrix(row, false, true, true, true).toTransform().inverted();
|
||||
gizmo_inverted_transform_ = GenerateMatrix(row, true, true, true).toTransform().inverted();
|
||||
|
||||
} else if (gizmo == rotation_gizmo_) {
|
||||
|
||||
@@ -389,7 +389,7 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N
|
||||
// Fold values into a matrix for the rectangle
|
||||
QMatrix4x4 rectangle_matrix;
|
||||
rectangle_matrix.scale(sequence_half_res);
|
||||
rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false, false),
|
||||
rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false),
|
||||
sequence_res,
|
||||
tex_sz,
|
||||
tex_offset,
|
||||
@@ -409,7 +409,7 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N
|
||||
// Draw anchor point
|
||||
QMatrix4x4 anchor_matrix;
|
||||
anchor_matrix.scale(sequence_half_res);
|
||||
anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, true, false, false),
|
||||
anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, true, false, false),
|
||||
sequence_res,
|
||||
tex_sz,
|
||||
tex_offset,
|
||||
@@ -432,6 +432,15 @@ void TransformDistortNode::UpdateGizmoPositions(const NodeValueRow &row, const N
|
||||
SetInputProperty(kAnchorInput, QStringLiteral("offset"), tex_sz * 0.5);
|
||||
}
|
||||
|
||||
QTransform TransformDistortNode::GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const
|
||||
{
|
||||
if (TexturePtr texture = row[kTextureInput].toTexture()) {
|
||||
auto m = GenerateMatrix(row, false, false, false);
|
||||
return GenerateAutoScaledMatrix(m, row, globals, texture->params()).toTransform();
|
||||
}
|
||||
return super::GizmoTransformation(row, globals);
|
||||
}
|
||||
|
||||
QPointF TransformDistortNode::CreateScalePoint(double x, double y, const QPointF &half_res, const QMatrix4x4 &mat)
|
||||
{
|
||||
return mat.map(QPointF(x, y)) + half_res;
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
AutoScaleType autoscale_type = kAutoScaleNone);
|
||||
|
||||
virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals) override;
|
||||
virtual QTransform GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const override;
|
||||
|
||||
static const QString kTextureInput;
|
||||
static const QString kAutoscaleInput;
|
||||
|
||||
@@ -90,63 +90,33 @@ void MatrixGenerator::Retranslate()
|
||||
void MatrixGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const
|
||||
{
|
||||
// Push matrix output
|
||||
QMatrix4x4 mat = GenerateMatrix(value, true, false, false, false);
|
||||
QMatrix4x4 mat = GenerateMatrix(value, false, false, false);
|
||||
table->Push(NodeValue::kMatrix, mat, this);
|
||||
}
|
||||
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool ignore_anchor, bool ignore_position, bool ignore_scale) const
|
||||
{
|
||||
QVector2D anchor;
|
||||
QVector2D position;
|
||||
QVector2D scale;
|
||||
|
||||
if (!ignore_anchor) {
|
||||
if (take) {
|
||||
// Take and store
|
||||
anchor = value[kAnchorInput].toVec2();
|
||||
} else {
|
||||
// Get and store
|
||||
anchor = value[kAnchorInput].toVec2();
|
||||
}
|
||||
} else if (take) {
|
||||
// Just take
|
||||
value[kAnchorInput].toVec2();
|
||||
anchor = value[kAnchorInput].toVec2();
|
||||
}
|
||||
|
||||
if (!ignore_scale) {
|
||||
if (take) {
|
||||
scale = value[kScaleInput].toVec2();
|
||||
} else {
|
||||
scale = value[kScaleInput].toVec2();
|
||||
}
|
||||
} else if (take) {
|
||||
value[kScaleInput].toVec2();
|
||||
scale = value[kScaleInput].toVec2();
|
||||
}
|
||||
|
||||
if (!ignore_position) {
|
||||
if (take) {
|
||||
position = value[kPositionInput].toVec2();
|
||||
} else {
|
||||
position = value[kPositionInput].toVec2();
|
||||
}
|
||||
} else if (take) {
|
||||
value[kPositionInput].toVec2();
|
||||
position = value[kPositionInput].toVec2();
|
||||
}
|
||||
|
||||
if (take) {
|
||||
return GenerateMatrix(position,
|
||||
value[kRotationInput].toDouble(),
|
||||
scale,
|
||||
value[kUniformScaleInput].toBool(),
|
||||
anchor);
|
||||
} else {
|
||||
return GenerateMatrix(position,
|
||||
value[kRotationInput].toDouble(),
|
||||
scale,
|
||||
value[kUniformScaleInput].toBool(),
|
||||
anchor);
|
||||
|
||||
}
|
||||
return GenerateMatrix(position,
|
||||
value[kRotationInput].toDouble(),
|
||||
scale,
|
||||
value[kUniformScaleInput].toBool(),
|
||||
anchor);
|
||||
}
|
||||
|
||||
QMatrix4x4 MatrixGenerator::GenerateMatrix(const QVector2D& pos,
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
static const QString kAnchorInput;
|
||||
|
||||
protected:
|
||||
QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const;
|
||||
QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool ignore_anchor, bool ignore_position, bool ignore_scale) const;
|
||||
static QMatrix4x4 GenerateMatrix(const QVector2D &pos,
|
||||
const float &rot,
|
||||
const QVector2D &scale,
|
||||
|
||||
@@ -50,7 +50,7 @@ QByteArray HashTraverser::GetHash(const Node *node, const Node::ValueHint &hint,
|
||||
//Hash(reference);
|
||||
|
||||
// Our overrides will generate a hash from this
|
||||
NodeValueTable table = GenerateTable(node, hint, range);
|
||||
NodeValueTable table = GenerateTable(node, range);
|
||||
NodeValue final_value = GenerateRowValueElement(hint, NodeValue::kTexture, &table);
|
||||
HashNodeValue(final_value);
|
||||
|
||||
|
||||
@@ -889,6 +889,8 @@ public:
|
||||
return gizmos_;
|
||||
}
|
||||
|
||||
virtual QTransform GizmoTransformation(const NodeValueRow &row, const NodeGlobals &globals) const { return QTransform(); }
|
||||
|
||||
virtual void UpdateGizmoPositions(const NodeValueRow &row, const NodeGlobals &globals){}
|
||||
|
||||
const QString& GetLabel() const;
|
||||
|
||||
@@ -381,7 +381,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const
|
||||
switch (type) {
|
||||
case Track::kVideo:
|
||||
if (IsInputConnected(kTextureInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), GetValueHintForInput(kTextureInput), TimeRange(0, 0));
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), TimeRange(0, 0));
|
||||
rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();
|
||||
if (!r.isNaN()) {
|
||||
return r;
|
||||
@@ -390,7 +390,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const
|
||||
break;
|
||||
case Track::kAudio:
|
||||
if (IsInputConnected(kSamplesInput)) {
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), GetValueHintForInput(kSamplesInput), TimeRange(0, 0));
|
||||
NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), TimeRange(0, 0));
|
||||
rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value<rational>();;
|
||||
if (!r.isNaN()) {
|
||||
return r;
|
||||
|
||||
+58
-7
@@ -141,6 +141,16 @@ int NodeTraverser::GenerateRowValueElementIndex(const Node *node, const QString
|
||||
return GenerateRowValueElementIndex(node->GetValueHintForInput(input, element), node->GetInputDataType(input), table);
|
||||
}
|
||||
|
||||
void NodeTraverser::Transform(QTransform *transform, const Node *start, const Node *end, const TimeRange &range)
|
||||
{
|
||||
transform_ = transform;
|
||||
transform_start_ = start;
|
||||
|
||||
GenerateTable(end, range);
|
||||
|
||||
transform_ = nullptr;
|
||||
}
|
||||
|
||||
NodeGlobals NodeTraverser::GenerateGlobals(const VideoParams ¶ms, const TimeRange &time)
|
||||
{
|
||||
return NodeGlobals(QVector2D(params.width(), params.height()), params.pixel_aspect_ratio(), time);
|
||||
@@ -179,6 +189,20 @@ int NodeTraverser::GetChannelCountFromJob(const GenerateJob &job)
|
||||
return VideoParams::kRGBAChannelCount;
|
||||
}
|
||||
|
||||
TexturePtr NodeTraverser::GetMainTextureFromJob(const GenerateJob &job)
|
||||
{
|
||||
// FIXME: Should probably take Node::GetEffectInput into account here
|
||||
for (auto it=job.GetValues().cbegin(); it!=job.GetValues().cend(); it++) {
|
||||
if (it.value().type() == NodeValue::kTexture) {
|
||||
if (TexturePtr t = it.value().toTexture()) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& input, const TimeRange& range)
|
||||
{
|
||||
// If input is connected, retrieve value directly
|
||||
@@ -187,7 +211,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu
|
||||
TimeRange adjusted_range = node->InputTimeAdjustment(input, -1, range);
|
||||
|
||||
// Value will equal something from the connected node, follow it
|
||||
return GenerateTable(node->GetConnectedOutput(input), node->GetValueHintForInput(input), adjusted_range);
|
||||
return GenerateTable(node->GetConnectedOutput(input), adjusted_range);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -205,7 +229,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu
|
||||
TimeRange adjusted_range = node->InputTimeAdjustment(input, i, range);
|
||||
|
||||
if (node->IsInputConnected(input, i)) {
|
||||
sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), node->GetValueHintForInput(input, i), adjusted_range);
|
||||
sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), adjusted_range);
|
||||
} else {
|
||||
QVariant input_value = node->GetValueAtTime(input, adjusted_range.in(), i);
|
||||
sub_tbl.Push(node->GetInputDataType(input), input_value, node);
|
||||
@@ -231,11 +255,12 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu
|
||||
}
|
||||
|
||||
NodeTraverser::NodeTraverser() :
|
||||
cancel_(nullptr)
|
||||
cancel_(nullptr),
|
||||
transform_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NodeValueTable NodeTraverser::GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange& range)
|
||||
NodeValueTable NodeTraverser::GenerateTable(const Node *n, const TimeRange& range)
|
||||
{
|
||||
const Track* track = dynamic_cast<const Track*>(n);
|
||||
if (track) {
|
||||
@@ -264,7 +289,24 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const Node::ValueHint
|
||||
NodeValueTable table = database.Merge();
|
||||
|
||||
// By this point, the node should have all the inputs it needs to render correctly
|
||||
n->Value(row, GenerateGlobals(video_params_, range), &table);
|
||||
NodeGlobals globals = GenerateGlobals(video_params_, range);
|
||||
n->Value(row, globals, &table);
|
||||
|
||||
if (transform_) {
|
||||
if (!transform_start_) {
|
||||
if (!transform_ignore_.contains(n)) {
|
||||
QTransform t = n->GizmoTransformation(row, globals);
|
||||
if (!t.isIdentity()) {
|
||||
qDebug() << "transforming" << n;
|
||||
(*transform_) *= t;
|
||||
}
|
||||
|
||||
transform_ignore_.append(n);
|
||||
}
|
||||
} else if (transform_start_ == n) {
|
||||
transform_start_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return table;
|
||||
} else {
|
||||
@@ -288,7 +330,7 @@ NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeR
|
||||
NodeValueTable table;
|
||||
|
||||
if (active_block) {
|
||||
table = GenerateTable(active_block, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(active_block)), Track::TransformRangeForBlock(active_block, range));
|
||||
table = GenerateTable(active_block, Track::TransformRangeForBlock(active_block, range));
|
||||
}
|
||||
|
||||
return table;
|
||||
@@ -307,12 +349,21 @@ void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
|
||||
|
||||
ShaderJob job = val.value<ShaderJob>();
|
||||
|
||||
PreProcessRow(range, job.GetValues());
|
||||
|
||||
VideoParams tex_params = GetCacheVideoParams();
|
||||
tex_params.set_channel_count(GetChannelCountFromJob(job));
|
||||
|
||||
if (!job.GetWillChangeImageSize()) {
|
||||
if (TexturePtr texture = GetMainTextureFromJob(job)) {
|
||||
tex_params.set_width(texture->params().width());
|
||||
tex_params.set_height(texture->params().height());
|
||||
tex_params.set_divider(texture->params().divider());
|
||||
}
|
||||
}
|
||||
|
||||
TexturePtr tex = CreateTexture(tex_params);
|
||||
|
||||
PreProcessRow(range, job.GetValues());
|
||||
ProcessShader(tex, val.source(), range, job);
|
||||
|
||||
val.set_value(tex);
|
||||
|
||||
@@ -37,7 +37,7 @@ class NodeTraverser
|
||||
public:
|
||||
NodeTraverser();
|
||||
|
||||
NodeValueTable GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange &range);
|
||||
NodeValueTable GenerateTable(const Node *n, const TimeRange &range);
|
||||
|
||||
NodeValueDatabase GenerateDatabase(const Node *node, const TimeRange &range);
|
||||
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
int GenerateRowValueElementIndex(const Node::ValueHint &hint, NodeValue::Type preferred_type, const NodeValueTable *table);
|
||||
int GenerateRowValueElementIndex(const Node *node, const QString &input, int element, const NodeValueTable *table);
|
||||
|
||||
void Transform(QTransform *transform, const Node *start, const Node *end, const TimeRange &range);
|
||||
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time);
|
||||
static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time)
|
||||
{
|
||||
@@ -78,6 +80,8 @@ public:
|
||||
|
||||
static int GetChannelCountFromJob(const GenerateJob& job);
|
||||
|
||||
static TexturePtr GetMainTextureFromJob(const GenerateJob& job);
|
||||
|
||||
protected:
|
||||
NodeValueTable ProcessInput(const Node *node, const QString &input, const TimeRange &range);
|
||||
|
||||
@@ -152,6 +156,10 @@ private:
|
||||
|
||||
const QAtomicInt *cancel_;
|
||||
|
||||
const Node *transform_start_;
|
||||
QTransform *transform_;
|
||||
QVector<const Node*> transform_ignore_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user