diff --git a/include/KeyFrame.h b/include/KeyFrame.h index abca5d92..8bb1d31b 100644 --- a/include/KeyFrame.h +++ b/include/KeyFrame.h @@ -137,6 +137,9 @@ namespace openshot { // Get the number of values (i.e. coordinates on the X axis) int GetLength(); + /// Get the number of points (i.e. # of points) + int GetCount(); + /// Get the direction of the curve at a specific index (increasing or decreasing) bool IsIncreasing(int index); diff --git a/src/Clip.cpp b/src/Clip.cpp index 8c588df1..cff6ce7c 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -544,21 +544,21 @@ string Clip::PropertiesJSON(int requested_frame) { root["waveform"] = add_property_json("Waveform", waveform, "int", "", false, 0, -1, -1, CONSTANT, -1, false); // Keyframes - root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", location_x.Contains(requested_point), location_x.GetLength(), -10000, 10000, location_x.GetClosestPoint(requested_point).interpolation, location_x.GetClosestPoint(requested_point).co.X, false); - root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", location_y.Contains(requested_point), location_y.GetLength(), -10000, 10000, location_y.GetClosestPoint(requested_point).interpolation, location_y.GetClosestPoint(requested_point).co.X, false); - root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", scale_x.Contains(requested_point), scale_x.GetLength(), 0.0, 100.0, scale_x.GetClosestPoint(requested_point).interpolation, scale_x.GetClosestPoint(requested_point).co.X, false); - root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", scale_y.Contains(requested_point), scale_y.GetLength(), 0.0, 100.0, scale_y.GetClosestPoint(requested_point).interpolation, scale_y.GetClosestPoint(requested_point).co.X, false); - root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", alpha.Contains(requested_point), alpha.GetLength(), 0.0, 1.0, alpha.GetClosestPoint(requested_point).interpolation, alpha.GetClosestPoint(requested_point).co.X, false); - root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", rotation.Contains(requested_point), rotation.GetLength(), -10000, 10000, rotation.GetClosestPoint(requested_point).interpolation, rotation.GetClosestPoint(requested_point).co.X, false); - root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", volume.Contains(requested_point), volume.GetLength(), 0.0, 1.0, volume.GetClosestPoint(requested_point).interpolation, volume.GetClosestPoint(requested_point).co.X, false); - root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", time.Contains(requested_point), time.GetLength(), 0.0, 1000 * 60 * 30, time.GetClosestPoint(requested_point).interpolation, time.GetClosestPoint(requested_point).co.X, false); + root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", location_x.Contains(requested_point), location_x.GetCount(), -10000, 10000, location_x.GetClosestPoint(requested_point).interpolation, location_x.GetClosestPoint(requested_point).co.X, false); + root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", location_y.Contains(requested_point), location_y.GetCount(), -10000, 10000, location_y.GetClosestPoint(requested_point).interpolation, location_y.GetClosestPoint(requested_point).co.X, false); + root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", scale_x.Contains(requested_point), scale_x.GetCount(), 0.0, 100.0, scale_x.GetClosestPoint(requested_point).interpolation, scale_x.GetClosestPoint(requested_point).co.X, false); + root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", scale_y.Contains(requested_point), scale_y.GetCount(), 0.0, 100.0, scale_y.GetClosestPoint(requested_point).interpolation, scale_y.GetClosestPoint(requested_point).co.X, false); + root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", alpha.Contains(requested_point), alpha.GetCount(), 0.0, 1.0, alpha.GetClosestPoint(requested_point).interpolation, alpha.GetClosestPoint(requested_point).co.X, false); + root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", rotation.Contains(requested_point), rotation.GetCount(), -10000, 10000, rotation.GetClosestPoint(requested_point).interpolation, rotation.GetClosestPoint(requested_point).co.X, false); + root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", volume.Contains(requested_point), volume.GetCount(), 0.0, 1.0, volume.GetClosestPoint(requested_point).interpolation, volume.GetClosestPoint(requested_point).co.X, false); + root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", time.Contains(requested_point), time.GetCount(), 0.0, 1000 * 60 * 30, time.GetClosestPoint(requested_point).interpolation, time.GetClosestPoint(requested_point).co.X, false); // Keep track of settings string stringstream properties; properties << 0.0f << Position() << Layer() << Start() << End() << Duration() << gravity << scale << anchor << waveform << location_x.GetValue(requested_frame) << location_y.GetValue(requested_frame) << scale_x.GetValue(requested_frame) << scale_y.GetValue(requested_frame) << alpha.GetValue(requested_frame) << rotation.GetValue(requested_frame) << - volume.GetValue(requested_frame) << time.GetValue(requested_frame); + volume.GetValue(requested_frame) << time.GetValue(requested_frame) << alpha.GetCount() << alpha.GetClosestPoint(requested_point).interpolation << alpha.GetClosestPoint(requested_point).co.X; // Have they changed since the previous call? bool changed = false; diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index e5c5c2f7..5d8d4b41 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -197,12 +197,23 @@ Point Keyframe::GetClosestPoint(Point p) { Point existing_point = Points[x]; // find a match - if ((p.co.X <= existing_point.co.X && p.co.X >= closest.co.X) || (closest.co.X == -1)) { + if (existing_point.co.X >= p.co.X) { // New closest point found closest = existing_point; + break; } } + // Handle edge cases (if no point was found) + if (closest.co.X == -1) { + if (p.co.X < 1) + // Assign 1st point + closest = Points[0]; + else + // Assign last point + closest = Points[Points.size() - 1]; + } + // no matching point found return closest; } @@ -416,6 +427,13 @@ int Keyframe::GetLength() { return Values.size(); } +// Get the number of points (i.e. # of points) +int Keyframe::GetCount() { + + // return the size of the Values vector + return Points.size(); +} + // Remove a point by matching a coordinate void Keyframe::RemovePoint(Point p) throw(OutOfBoundsPoint) { // mark as dirty diff --git a/tests/Clip_Tests.cpp b/tests/Clip_Tests.cpp index e7d38163..8689fc1e 100644 --- a/tests/Clip_Tests.cpp +++ b/tests/Clip_Tests.cpp @@ -116,7 +116,7 @@ TEST(Clip_Properties) try { // Check for specific things - CHECK_CLOSE(1.0f, root["alpha"]["value"].asDouble(), 0.00001); + CHECK_CLOSE(1.0f, root["alpha"]["value"].asDouble(), 0.01); CHECK_EQUAL(true, root["alpha"]["keyframe"].asBool()); CHECK_EQUAL(true, root["changed"]["value"].asBool()); @@ -141,7 +141,7 @@ TEST(Clip_Properties) try { // Check for specific things - CHECK_CLOSE(0.5f, root["alpha"]["value"].asDouble(), 0.001); + CHECK_CLOSE(0.5f, root["alpha"]["value"].asDouble(), 0.01); CHECK_EQUAL(false, root["alpha"]["keyframe"].asBool()); CHECK_EQUAL(true, root["changed"]["value"].asBool()); diff --git a/tests/Color_Tests.cpp b/tests/Color_Tests.cpp index 31ae59ff..1ab710a1 100644 --- a/tests/Color_Tests.cpp +++ b/tests/Color_Tests.cpp @@ -74,7 +74,7 @@ TEST(Color_HEX_Value) c.blue.AddPoint(100, 255); CHECK_EQUAL("#000000", c.GetColorHex(1)); - CHECK_EQUAL("#818181", c.GetColorHex(50)); + CHECK_EQUAL("#7f7f7f", c.GetColorHex(50)); CHECK_EQUAL("#ffffff", c.GetColorHex(100)); } diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 3f793745..fb358697 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -223,3 +223,23 @@ TEST(Keyframe_Check_Direction_and_Repeat_Fractions) CHECK_EQUAL(kf.GetRepeatFraction(391).den, 12); CHECK_EQUAL(kf.GetDelta(391), -1); } + + +TEST(Keyframe_Get_Closest_Point) +{ + // Create a keyframe curve with 2 points + Keyframe kf; + kf.AddPoint(1, 0.0); + kf.AddPoint(1000, 1.0); + kf.AddPoint(2500, 0.0); + + // Spot check values from the curve + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(900, 900)).co.X, 1000); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1, 1)).co.X, 1); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(5, 5)).co.X, 1000); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1000, 1000)).co.X, 1000); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(1001, 1001)).co.X, 2500); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(2500, 2500)).co.X, 2500); + CHECK_EQUAL(kf.GetClosestPoint(openshot::Point(3000, 3000)).co.X, 2500); + +}