23 constexpr
double kCurveDomainMax = 255.0;
25 static double clamp01(
const double value) {
26 return std::max(0.0, std::min(1.0, value));
41 interpolation(node_interpolation),
45 Point point(
static_cast<float>(clamp01(
x.
GetValue(frame_number)) * x_scale),
46 static_cast<float>(clamp01(
y.
GetValue(frame_number))),
61 Json::Value root(Json::objectValue);
77 }
catch (
const std::exception&) {
78 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
83 if (!root[
"id"].isNull())
84 id = root[
"id"].asInt();
85 if (!root[
"x"].isNull())
87 if (!root[
"y"].isNull())
89 if (!root[
"left_handle_x"].isNull())
91 if (!root[
"left_handle_y"].isNull())
93 if (!root[
"right_handle_x"].isNull())
95 if (!root[
"right_handle_y"].isNull())
97 if (!root[
"interpolation"].isNull())
99 if (!root[
"handle_type"].isNull())
105 nodes.emplace_back(0, 0.0, 0.0,
LINEAR);
106 nodes.emplace_back(1, 1.0, 1.0,
LINEAR);
111 std::vector<AnimatedCurveNode> ordered_nodes = nodes;
113 std::sort(ordered_nodes.begin(), ordered_nodes.end(),
115 const double lhs_x = lhs.x.GetValue(frame_number);
116 const double rhs_x = rhs.x.GetValue(frame_number);
118 return lhs.id < rhs.id;
119 return lhs_x < rhs_x;
122 for (
const auto& node : ordered_nodes) {
123 curve.
AddPoint(node.Evaluate(frame_number, x_scale));
130 return static_cast<float>(clamp01(input));
133 return static_cast<float>(clamp01(curve.
GetValue(std::lround(clamp01(input) * kCurveDomainMax))));
137 std::ostringstream ss;
140 ss << nodes.size() <<
" nodes";
149 Json::Value root(Json::objectValue);
151 root[
"nodes"] = Json::Value(Json::arrayValue);
152 for (
const auto& node : nodes)
153 root[
"nodes"].append(node.JsonValue());
160 }
catch (
const std::exception&) {
161 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
166 if (!root[
"enabled"].isNull())
169 if (root[
"nodes"].isArray()) {
170 std::vector<AnimatedCurveNode> parsed_nodes;
171 for (
const auto& item : root[
"nodes"]) {
174 parsed_nodes.push_back(node);
176 if (!parsed_nodes.empty())
177 nodes.swap(parsed_nodes);
Header file for AnimatedCurve classes.
Header file for all Exception classes.
void SetJsonValue(const Json::Value &root)
Json::Value JsonValue() const
Point Evaluate(int64_t frame_number, double x_scale=1.0) const
InterpolationType interpolation
void SetJson(const std::string value)
void SetJsonValue(const Json::Value &root)
void SetJson(const std::string value)
float Sample(float input, int64_t frame_number) const
std::string Summary(int64_t frame_number) const
Keyframe BuildCurve(int64_t frame_number, double x_scale=1.0) const
Json::Value JsonValue() const
A Cartesian coordinate (X, Y) used in the Keyframe animation system.
Exception for invalid JSON.
A Keyframe is a collection of Point instances, which is used to vary a number or property over time.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
void AddPoint(Point p)
Add a new point on the key-frame. Each point has a primary coordinate, a left handle,...
double GetValue(int64_t index) const
Get the value at a specific index.
Json::Value JsonValue() const
Generate Json::Value for this object.
A Point is the basic building block of a key-frame curve.
Coordinate handle_left
This is the left handle coordinate (in percentages from 0 to 1)
HandleType handle_type
This is the handle mode.
Coordinate handle_right
This is the right handle coordinate (in percentages from 0 to 1)
This namespace is the default namespace for all code in the openshot library.
HandleType
When BEZIER interpolation is used, the point's left and right handles are used to influence the direc...
@ AUTO
Automatically adjust the handles to achieve the smoothest curve.
const Json::Value stringToJson(const std::string value)
InterpolationType
This controls how a Keyframe uses this point to interpolate between two points.
@ LINEAR
Linear curves are angular, straight lines between two points.