diff --git a/app/node/factory.cpp b/app/node/factory.cpp index 33c5a8996..9df4b11cd 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -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 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; diff --git a/app/node/factory.h b/app/node/factory.h index 7d19977ce..5a43d56d5 100644 --- a/app/node/factory.h +++ b/app/node/factory.h @@ -57,6 +57,7 @@ public: kProjectFolder, kProjectSequence, kValueNode, + kTimeRemapNode, // Count value kInternalNodeCount diff --git a/app/node/node.cpp b/app/node/node.cpp index d52d8893e..8f37040e2 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -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;itime() == 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().toDouble(); + after_val = after->value().value().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; } } } diff --git a/app/node/value.h b/app/node/value.h index 723e84b2d..ba5651aae 100644 --- a/app/node/value.h +++ b/app/node/value.h @@ -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)