From 3f11361f09b964b193c3f8f06adab22a837ae6a2 Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 27 Jan 2021 17:41:39 -0300 Subject: [PATCH] Added support to attach a clip to another clip --- src/Clip.cpp | 49 +++++++++++++++++++++++++++++++--------- src/Clip.h | 7 +++++- tests/KeyFrame_Tests.cpp | 2 +- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index b1ea5c315..af09db1ea 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -100,6 +100,10 @@ void Clip::init_settings() has_audio = Keyframe(-1.0); has_video = Keyframe(-1.0); + // Initialize the attached object and attached clip as null pointers + attachedObject = nullptr; + attachedClip = NULL; + // Init reader info struct and cache size init_reader_settings(); } @@ -245,22 +249,23 @@ Clip::~Clip() } // Attach clip to bounding box -void Clip::AttachToTracker(std::string tracked_id) +void Clip::AttachToObject(std::string object_id) { // Search for the tracked object on the timeline Timeline* parentTimeline = (Timeline *) ParentTimeline(); - - // Check if the clip has a parent timeline - if (parentTimeline){ + if (parentTimeline) { // Create a smart pointer to the tracked object from the timeline - std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); - + std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(object_id); + Clip* clipObject = parentTimeline->GetClip(object_id); + // Check for valid tracked object if (trackedObject){ SetAttachedObject(trackedObject); } - + else if (clipObject) { + SetAttachedClip(clipObject); + } } return; } @@ -271,6 +276,12 @@ void Clip::SetAttachedObject(std::shared_ptr tracke return; } +// Set the pointer to the clip this clip is attached to +void Clip::SetAttachedClip(Clip* clipObject){ + attachedClip = clipObject; + return; +} + /// Set the current reader void Clip::Reader(ReaderBase* new_reader) { @@ -979,13 +990,15 @@ void Clip::SetJsonValue(const Json::Value root) { cache.Clear(); // Set data from Json (if key is found) - if (!root["attached_id"].isNull()) + if (!root["attached_id"].isNull()){ attached_id = root["attached_id"].asString(); if (attached_id.size() > 0 && attached_id != "None"){ - AttachToTracker(attached_id); + AttachToObject(attached_id); } else{ attachedObject = nullptr; + attachedClip = NULL; } + } if (!root["gravity"].isNull()) gravity = (GravityType) root["gravity"].asInt(); if (!root["scale"].isNull()) @@ -1315,7 +1328,7 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) break; } } - + // Initialize attached object's properties values float attached_location_x = 0.0; float attached_location_y = 0.0; @@ -1323,6 +1336,20 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float attached_scale_y = 1.0; float attached_rotation = 0.0; + if (attachedClip){ + + // Convert Clip's frame position to Timeline's frame position + long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; + long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; + double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; + + attached_location_x = attachedClip->location_x.GetValue(timeline_frame_number); + attached_location_y = attachedClip->location_y.GetValue(timeline_frame_number); + attached_scale_x = attachedClip->scale_x.GetValue(timeline_frame_number); + attached_scale_y = attachedClip->scale_y.GetValue(timeline_frame_number); + attached_rotation = attachedClip->rotation.GetValue(timeline_frame_number); + } + /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ @@ -1371,7 +1398,7 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float sy = scale_y.GetValue(frame->number); // percentage Y scale // Compose clip's scale to attachedObject's scale - if(attached_scale_x > 0.0 && attached_scale_y > 0.0){ + if(attached_scale_x != 0.0 && attached_scale_y != 0.0){ sx*= attached_scale_x; sy*= attached_scale_y; } diff --git a/src/Clip.h b/src/Clip.h index 8b31405af..87673ece2 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -126,6 +126,7 @@ namespace openshot { bool is_open; ///> Is Reader opened std::string attached_id; ///< Id of the bounding box that this clip is attached to std::shared_ptr attachedObject; + Clip* attachedClip; ///< Clip object this clip is attached to // Audio resampler (if time mapping) openshot::AudioResampler *resampler; @@ -203,12 +204,16 @@ namespace openshot { void SetAttachedId(std::string value) { attached_id = value; }; /// Attach clip to bounding box - void AttachToTracker(std::string tracked_id); + void AttachToObject(std::string object_id); /// Set the pointer to the trackedObject this clip is attached to void SetAttachedObject(std::shared_ptr trackedObject); + /// Set the pointer to the clip this clip is attached to + void SetAttachedClip(Clip* clipObject); /// Return a pointer to the trackedObject this clip is attached to std::shared_ptr GetAttachedObject() const { return attachedObject; }; + /// Return a pointer to the clip this clip is attached to + Clip* GetAttachedClip() const { return attachedClip; }; /// Return the type name of the class std::string Name() override { return "Clip"; }; diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 31d93c3fb..4444a9c99 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -666,7 +666,7 @@ TEST(Attach_test){ // Attach childClip to tracked object std::string tracked_id = trackedData->Id(); childClip.Open(); - childClip.AttachToTracker(tracked_id); + childClip.AttachToObject(tracked_id); std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject());