Skip to content

Commit

Permalink
Adding keyframable origin point (for shear and rotation)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonoomph committed Apr 13, 2020
1 parent 166f693 commit 2bea436
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 29 deletions.
24 changes: 13 additions & 11 deletions include/Clip.h
Expand Up @@ -140,11 +140,11 @@ namespace openshot {
void reverse_buffer(juce::AudioSampleBuffer* buffer);

public:
openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent
openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent
openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to
openshot::FrameDisplayType display; ///< The format to display the frame number (if any)
openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips
openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent
openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent
openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to
openshot::FrameDisplayType display; ///< The format to display the frame number (if any)
openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips

/// Default Constructor
Clip();
Expand Down Expand Up @@ -208,15 +208,19 @@ namespace openshot {
bool Waveform() { return waveform; } ///< Get the waveform property of this clip
void Waveform(bool value) { waveform = value; } ///< Set the waveform property of this clip

// Scale and Location curves
// Scale, Location, and Alpha curves
openshot::Keyframe scale_x; ///< Curve representing the horizontal scaling in percent (0 to 1)
openshot::Keyframe scale_y; ///< Curve representing the vertical scaling in percent (0 to 1)
openshot::Keyframe location_x; ///< Curve representing the relative X position in percent based on the gravity (-1 to 1)
openshot::Keyframe location_y; ///< Curve representing the relative Y position in percent based on the gravity (-1 to 1)

// Alpha and Rotation curves
openshot::Keyframe alpha; ///< Curve representing the alpha (1 to 0)

// Rotation and Shear curves (origin point (x,y) is adjustable for both rotation and shear)
openshot::Keyframe rotation; ///< Curve representing the rotation (0 to 360)
openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right)
openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up)
openshot::Keyframe origin_x; ///< Curve representing X origin point (0.0=0% (left), 1.0=100% (right))
openshot::Keyframe origin_y; ///< Curve representing Y origin point (0.0=0% (top), 1.0=100% (bottom))

// Time and Volume curves
openshot::Keyframe time; ///< Curve representing the frames over time to play (used for speed and direction of video)
Expand All @@ -232,9 +236,7 @@ namespace openshot {
openshot::Keyframe crop_x; ///< Curve representing X offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)
openshot::Keyframe crop_y; ///< Curve representing Y offset in percent (-1.0=-100%, 0.0=0%, 1.0=100%)

// Shear and perspective curves
openshot::Keyframe shear_x; ///< Curve representing X shear angle in degrees (-45.0=left, 45.0=right)
openshot::Keyframe shear_y; ///< Curve representing Y shear angle in degrees (-45.0=down, 45.0=up)
// Perspective curves
openshot::Keyframe perspective_c1_x; ///< Curves representing X for coordinate 1
openshot::Keyframe perspective_c1_y; ///< Curves representing Y for coordinate 1
openshot::Keyframe perspective_c2_x; ///< Curves representing X for coordinate 2
Expand Down
10 changes: 10 additions & 0 deletions src/Clip.cpp
Expand Up @@ -89,6 +89,8 @@ void Clip::init_settings()
// Init shear and perspective curves
shear_x = Keyframe(0.0);
shear_y = Keyframe(0.0);
origin_x = Keyframe(0.5);
origin_y = Keyframe(0.5);
perspective_c1_x = Keyframe(-1.0);
perspective_c1_y = Keyframe(-1.0);
perspective_c2_x = Keyframe(-1.0);
Expand Down Expand Up @@ -718,6 +720,8 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const {
root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame);
root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame);
root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, -360, 360, false, requested_frame);
root["origin_x"] = add_property_json("Origin X", origin_x.GetValue(requested_frame), "float", "", &origin_x, 0.0, 1.0, false, requested_frame);
root["origin_y"] = add_property_json("Origin Y", origin_y.GetValue(requested_frame), "float", "", &origin_y, 0.0, 1.0, false, requested_frame);
root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame);
root["time"] = add_property_json("Time", time.GetValue(requested_frame), "float", "", &time, 0.0, 30 * 60 * 60 * 48, false, requested_frame);
root["channel_filter"] = add_property_json("Channel Filter", channel_filter.GetValue(requested_frame), "int", "", &channel_filter, -1, 10, false, requested_frame);
Expand Down Expand Up @@ -774,6 +778,8 @@ Json::Value Clip::JsonValue() const {
root["crop_y"] = crop_y.JsonValue();
root["shear_x"] = shear_x.JsonValue();
root["shear_y"] = shear_y.JsonValue();
root["origin_x"] = origin_x.JsonValue();
root["origin_y"] = origin_y.JsonValue();
root["channel_filter"] = channel_filter.JsonValue();
root["channel_mapping"] = channel_mapping.JsonValue();
root["has_audio"] = has_audio.JsonValue();
Expand Down Expand Up @@ -871,6 +877,10 @@ void Clip::SetJsonValue(const Json::Value root) {
shear_x.SetJsonValue(root["shear_x"]);
if (!root["shear_y"].isNull())
shear_y.SetJsonValue(root["shear_y"]);
if (!root["origin_x"].isNull())
origin_x.SetJsonValue(root["origin_x"]);
if (!root["origin_y"].isNull())
origin_y.SetJsonValue(root["origin_y"]);
if (!root["channel_filter"].isNull())
channel_filter.SetJsonValue(root["channel_filter"]);
if (!root["channel_mapping"].isNull())
Expand Down
33 changes: 15 additions & 18 deletions src/Timeline.cpp
Expand Up @@ -677,28 +677,31 @@ void Timeline::add_layer(std::shared_ptr<Frame> new_frame, Clip* source_clip, in
y += (Settings::Instance()->MAX_HEIGHT * source_clip->location_y.GetValue(clip_frame_number)); // move in percentage of final height
float shear_x = source_clip->shear_x.GetValue(clip_frame_number);
float shear_y = source_clip->shear_y.GetValue(clip_frame_number);
float origin_x = source_clip->origin_x.GetValue(clip_frame_number);
float origin_y = source_clip->origin_y.GetValue(clip_frame_number);

bool transformed = false;
QTransform transform;

// Transform source image (if needed)
ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Build QTransform - if needed)", "source_frame->number", source_frame->number, "x", x, "y", y, "r", r, "sx", sx, "sy", sy);

if (!isEqual(r, 0)) {
// ROTATE CLIP
float origin_x = x + (scaled_source_width / 2.0);
float origin_y = y + (scaled_source_height / 2.0);
transform.translate(origin_x, origin_y);
transform.rotate(r);
transform.translate(-origin_x,-origin_y);
if (!isEqual(x, 0) || !isEqual(y, 0)) {
// TRANSLATE/MOVE CLIP
transform.translate(x, y);
transformed = true;
}

if (!isEqual(x, 0) || !isEqual(y, 0)) {
// TRANSLATE/MOVE CLIP
transform.translate(x, y);
transformed = true;
}
if (!isEqual(r, 0) || !isEqual(shear_x, 0) || !isEqual(shear_y, 0)) {
// ROTATE CLIP (around origin_x, origin_y)
float origin_x_value = (scaled_source_width * origin_x);
float origin_y_value = (scaled_source_height * origin_y);
transform.translate(origin_x_value, origin_y_value);
transform.rotate(r);
transform.shear(shear_x, shear_y);
transform.translate(-origin_x_value,-origin_y_value);
transformed = true;
}

// SCALE CLIP (if needed)
float source_width_scale = (float(source_size.width()) / float(source_image->width())) * sx;
Expand All @@ -709,12 +712,6 @@ void Timeline::add_layer(std::shared_ptr<Frame> new_frame, Clip* source_clip, in
transformed = true;
}

if (!isEqual(shear_x, 0) || !isEqual(shear_y, 0)) {
// SHEAR HEIGHT/WIDTH
transform.shear(shear_x, shear_y);
transformed = true;
}

// Debug output
ZmqLogger::Instance()->AppendDebugMethod("Timeline::add_layer (Transform: Composite Image Layer: Prepare)", "source_frame->number", source_frame->number, "new_frame->GetImage()->width()", new_frame->GetImage()->width(), "transformed", transformed);

Expand Down

0 comments on commit 2bea436

Please sign in to comment.