nodefactory: added time remap node
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
#include "project/folder/folder.h"
|
||||
#include "project/footage/footage.h"
|
||||
#include "project/sequence/sequence.h"
|
||||
#include "node/input/value/valuenode.h"
|
||||
#include "time/timeremap/timeremap.h"
|
||||
|
||||
namespace olive {
|
||||
QList<Node*> NodeFactory::library_;
|
||||
@@ -237,6 +237,8 @@ Node *NodeFactory::CreateFromFactoryIndex(const NodeFactory::InternalID &id)
|
||||
return new Sequence();
|
||||
case kValueNode:
|
||||
return new ValueNode();
|
||||
case kTimeRemapNode:
|
||||
return new TimeRemapNode();
|
||||
|
||||
case kInternalNodeCount:
|
||||
break;
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
kProjectFolder,
|
||||
kProjectSequence,
|
||||
kValueNode,
|
||||
kTimeRemapNode,
|
||||
|
||||
// Count value
|
||||
kInternalNodeCount
|
||||
|
||||
+28
-11
@@ -602,13 +602,15 @@ QVariant Node::GetSplitValueAtTimeOnTrack(const QString &input, const rational &
|
||||
return key_track.last()->value();
|
||||
}
|
||||
|
||||
NodeValue::Type type = GetInputDataType(input);
|
||||
|
||||
// If we're here, the time must be somewhere in between the keyframes
|
||||
for (int i=0;i<key_track.size()-1;i++) {
|
||||
NodeKeyframe* before = key_track.at(i);
|
||||
NodeKeyframe* after = key_track.at(i+1);
|
||||
|
||||
if (before->time() == time
|
||||
|| !NodeValue::type_can_be_interpolated(GetInputDataType(input))
|
||||
|| !NodeValue::type_can_be_interpolated(type)
|
||||
|| (before->type() == NodeKeyframe::kHold && after->time() > time)) {
|
||||
|
||||
// Time == keyframe time, so value is precise
|
||||
@@ -622,6 +624,15 @@ QVariant Node::GetSplitValueAtTimeOnTrack(const QString &input, const rational &
|
||||
} else if (before->time() < time && after->time() > time) {
|
||||
// We must interpolate between these keyframes
|
||||
|
||||
double before_val, after_val, interpolated;
|
||||
if (type == NodeValue::kRational) {
|
||||
before_val = before->value().value<rational>().toDouble();
|
||||
after_val = after->value().value<rational>().toDouble();
|
||||
} else {
|
||||
before_val = before->value().toDouble();
|
||||
after_val = after->value().toDouble();
|
||||
}
|
||||
|
||||
if (before->type() == NodeKeyframe::kBezier && after->type() == NodeKeyframe::kBezier) {
|
||||
// Perform a cubic bezier with two control points
|
||||
|
||||
@@ -631,13 +642,13 @@ QVariant Node::GetSplitValueAtTimeOnTrack(const QString &input, const rational &
|
||||
after->time().toDouble() + after->valid_bezier_control_in().x(),
|
||||
after->time().toDouble());
|
||||
|
||||
double y = Bezier::CubicTtoY(before->value().toDouble(),
|
||||
before->value().toDouble() + before->valid_bezier_control_out().y(),
|
||||
after->value().toDouble() + after->valid_bezier_control_in().y(),
|
||||
after->value().toDouble(),
|
||||
double y = Bezier::CubicTtoY(before_val,
|
||||
before_val + before->valid_bezier_control_out().y(),
|
||||
after_val + after->valid_bezier_control_in().y(),
|
||||
after_val,
|
||||
t);
|
||||
|
||||
return y;
|
||||
interpolated = y;
|
||||
|
||||
} else if (before->type() == NodeKeyframe::kBezier || after->type() == NodeKeyframe::kBezier) {
|
||||
// Perform a quadratic bezier with only one control point
|
||||
@@ -649,26 +660,32 @@ QVariant Node::GetSplitValueAtTimeOnTrack(const QString &input, const rational &
|
||||
if (before->type() == NodeKeyframe::kBezier) {
|
||||
control_point = before->valid_bezier_control_out();
|
||||
control_point_time = before->time().toDouble() + control_point.x();
|
||||
control_point_value = before->value().toDouble() + control_point.y();
|
||||
control_point_value = before_val + control_point.y();
|
||||
} else {
|
||||
control_point = after->valid_bezier_control_in();
|
||||
control_point_time = after->time().toDouble() + control_point.x();
|
||||
control_point_value = after->value().toDouble() + control_point.y();
|
||||
control_point_value = after_val + control_point.y();
|
||||
}
|
||||
|
||||
// Generate T from time values - used to determine bezier progress
|
||||
double t = Bezier::QuadraticXtoT(time.toDouble(), before->time().toDouble(), control_point_time, after->time().toDouble());
|
||||
|
||||
// Generate value using T
|
||||
double y = Bezier::QuadraticTtoY(before->value().toDouble(), control_point_value, after->value().toDouble(), t);
|
||||
double y = Bezier::QuadraticTtoY(before_val, control_point_value, after_val, t);
|
||||
|
||||
return y;
|
||||
interpolated = y;
|
||||
|
||||
} else {
|
||||
// To have arrived here, the keyframes must both be linear
|
||||
qreal period_progress = (time.toDouble() - before->time().toDouble()) / (after->time().toDouble() - before->time().toDouble());
|
||||
|
||||
return lerp(before->value().toDouble(), after->value().toDouble(), period_progress);
|
||||
interpolated = lerp(before_val, after_val, period_progress);
|
||||
}
|
||||
|
||||
if (type == NodeValue::kRational) {
|
||||
return QVariant::fromValue(rational::fromDouble(interpolated));
|
||||
} else {
|
||||
return interpolated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -274,7 +274,8 @@ public:
|
||||
|| type == kVec2
|
||||
|| type == kVec3
|
||||
|| type == kVec4
|
||||
|| type == kColor;
|
||||
|| type == kColor
|
||||
|| type == kRational;
|
||||
}
|
||||
|
||||
static bool type_is_numeric(NodeValue::Type type)
|
||||
|
||||
Reference in New Issue
Block a user