Skip to content

Commit

Permalink
Merge pull request OpenShot#2938 from ferdnyc/playhead-zoom
Browse files Browse the repository at this point in the history
Zoom centered on the playhead, if visible
  • Loading branch information
jonoomph authored Nov 18, 2019
2 parents 9b07bf1 + e74eb12 commit b0fe642
Showing 1 changed file with 67 additions and 60 deletions.
127 changes: 67 additions & 60 deletions src/timeline/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ App.controller('TimelineCtrl',function($scope) {
// version : "2"
// }
};

// Additional variables used to control the rendering of HTML
$scope.pixelsPerSecond = parseFloat($scope.project.tick_pixels) / parseFloat($scope.project.scale);
$scope.playheadOffset = 0;
Expand Down Expand Up @@ -266,14 +266,14 @@ App.controller('TimelineCtrl',function($scope) {
$(".playhead-line").css("left", (($scope.project.playhead_position * $scope.pixelsPerSecond) + $scope.playheadOffset) + "px");
$("#ruler_time").text($scope.playheadTime.hour + ":" + $scope.playheadTime.min + ":" + $scope.playheadTime.sec + ":" + $scope.playheadTime.frame);
};

// Move the playhead to a specific frame
$scope.MovePlayheadToFrame = function(position_frames) {
// Don't move the playhead if it's currently animating
if ($scope.playhead_animating) {
return;
}

// Determine seconds
var frames_per_second = $scope.project.fps.num / $scope.project.fps.den;
var position_seconds = ((position_frames - 1) / frames_per_second);
Expand Down Expand Up @@ -420,25 +420,32 @@ App.controller('TimelineCtrl',function($scope) {

// ############# QT FUNCTIONS #################### //

// Change the scale and apply to scope
$scope.setScale = function(scaleVal, cursor_x) {
// Get scrollbar positions
var horz_scroll_offset = $("#scrolling_tracks").scrollLeft();
var track_labels_width = $("#track_controls").width();

// Determine actual x coordinate (over timeline)
var center_x = Math.max(cursor_x - track_labels_width, 0);
if (cursor_x === 0) {
center_x = 0;
}

// Determine time of cursor position
var cursor_time = parseFloat(center_x + horz_scroll_offset) / $scope.pixelsPerSecond;
// Change the scale and apply to scope
$scope.setScale = function(scaleVal, cursor_x) {
// Get scrollbar positions
var horz_scroll_offset = $("#scrolling_tracks").scrollLeft();
var track_labels_width = $("#track_controls").width();
var center_x = 0;
var cursor_time = 0;

// Determine actual x coordinate (over timeline)
if (cursor_x > 0) {
center_x = Math.max(cursor_x - track_labels_width, 0);
// Determine time of cursor position
cursor_time = parseFloat(center_x + horz_scroll_offset) / $scope.pixelsPerSecond;
} else if ($scope.isPlayheadVisible()) {
// Zoom on playhead if visible
cursor_time = $scope.project.playhead_position;
center_x = (cursor_time * $scope.pixelsPerSecond) - horz_scroll_offset;
} else {
// Fall back to centering on left edge of canvas
cursor_time = parseFloat(horz_scroll_offset) / $scope.pixelsPerSecond;
}

$scope.$apply(function() {
$scope.project.scale = parseFloat(scaleVal);
$scope.pixelsPerSecond = parseFloat($scope.project.tick_pixels) / parseFloat($scope.project.scale);
});
$scope.$apply(function() {
$scope.project.scale = parseFloat(scaleVal);
$scope.pixelsPerSecond = parseFloat($scope.project.tick_pixels) / parseFloat($scope.project.scale);
});

// Scroll back to correct cursor time (minus the difference of the cursor location)
var new_cursor_x = Math.round((cursor_time * $scope.pixelsPerSecond) - center_x);
Expand Down Expand Up @@ -590,17 +597,17 @@ App.controller('TimelineCtrl',function($scope) {

clip_json.position = clip_position;
clip_json.layer = $scope.GetTrackAtY(y).number;

// Push new clip onto stack
$scope.project.clips.push(clip_json);
});
};

// Update cache json
$scope.RenderCache = function(cache_json) {
// Push new clip onto stack
$scope.project.progress = cache_json;

//clear the canvas first
var ruler = $("#progress");
var ctx = ruler[0].getContext('2d');
Expand Down Expand Up @@ -645,7 +652,7 @@ App.controller('TimelineCtrl',function($scope) {
}
});
};

// Select all clips and transitions
$scope.SelectAll = function() {
$scope.$apply(function() {
Expand All @@ -661,7 +668,7 @@ App.controller('TimelineCtrl',function($scope) {
}
});
};

// Select clip in scope
$scope.SelectClip = function(clip_id, clear_selections, event) {
// Trim clip_id
Expand All @@ -686,7 +693,7 @@ App.controller('TimelineCtrl',function($scope) {
if (event && event.ctrlKey) {
is_ctrl = true;
}

// Unselect all clips
for (var clip_index = 0; clip_index < $scope.project.clips.length; clip_index++) {
if ($scope.project.clips[clip_index].id == id) {
Expand All @@ -703,7 +710,7 @@ App.controller('TimelineCtrl',function($scope) {
}
}
};

// Select transition in scope
$scope.SelectTransition = function(tran_id, clear_selections, event) {
// Trim tran_id
Expand Down Expand Up @@ -776,7 +783,7 @@ App.controller('TimelineCtrl',function($scope) {
}
}
};

// Show clip context menu
$scope.ShowClipMenu = function(clip_id, event) {
if ($scope.Qt && !$scope.enable_razor) {
Expand Down Expand Up @@ -855,7 +862,7 @@ $scope.SetTrackLabel = function (label) {
return Math.max(min_value, $scope.project.duration * $scope.pixelsPerSecond);
};


// Get Position of item (used by Qt)
$scope.GetJavaScriptPosition = function(x) {
// Adjust for scrollbar position
Expand All @@ -868,11 +875,11 @@ $scope.SetTrackLabel = function (label) {
if (clip_position < 0) {
clip_position = 0;
}

// Return position in seconds
return clip_position;
};

// Get Track number of item (used by Qt)
$scope.GetJavaScriptTrack = function(y) {
// Adjust for scrollbar position
Expand All @@ -884,7 +891,7 @@ $scope.SetTrackLabel = function (label) {
var track_number = parseInt($scope.GetTrackAtY(y - scrolling_tracks_offset_top).number);
return track_number;
};

// Get JSON of most recent item (used by Qt)
$scope.UpdateRecentItemJSON = function(item_type, item_id) {

Expand Down Expand Up @@ -937,7 +944,7 @@ $scope.SetTrackLabel = function (label) {
// Remove CSS class (after the drag)
bounding_box = {};
};

// Init bounding boxes for manual move
$scope.StartManualMove = function(item_type, item_id) {
// Select the item
Expand Down Expand Up @@ -990,7 +997,7 @@ $scope.SetTrackLabel = function (label) {
bounding_box.element.addClass("manual-move");
}
};

// Move a new clip to the timeline
$scope.MoveItem = function(x, y, item_type) {

Expand Down Expand Up @@ -1039,7 +1046,7 @@ $scope.SetTrackLabel = function (label) {
bounding_box.element.css('left', results.position.left);
bounding_box.element.css('top', bounding_box.track_position - scrolling_tracks_offset_top);
};

// Update X,Y indexes of tracks / layers (anytime the project.layers scope changes)
$scope.UpdateLayerIndex = function(){

Expand All @@ -1058,7 +1065,7 @@ $scope.SetTrackLabel = function (label) {
// Loop through each layer
for (var layer_index = 0; layer_index < $scope.project.layers.length; layer_index++) {
var layer = $scope.project.layers[layer_index];

// Find element on screen (bound to this layer)
var layer_elem = $("#track_" + layer.number);
if (layer_elem) {
Expand Down Expand Up @@ -1116,16 +1123,16 @@ $scope.SetTrackLabel = function (label) {
});
}
};

// Find overlapping clips
$scope.GetMissingTransitions = function(original_clip) {

var transition_size = null;

// Get clip that matches this id
var original_left = original_clip.position;
var original_right = original_clip.position + (original_clip.end - original_clip.start);

// Search through all other clips on this track, and look for overlapping ones
for (var index = 0; index < $scope.project.clips.length; index++) {
var clip = $scope.project.clips[index];
Expand All @@ -1134,11 +1141,11 @@ $scope.SetTrackLabel = function (label) {
if (original_clip.layer != clip.layer) {
continue;
}

// is clip overlapping
var clip_left = clip.position;
var clip_right = clip.position + (clip.end - clip.start);

if (original_left < clip_right && original_left > clip_left) {
transition_size = { "position" : original_left, "layer" : clip.layer, "start" : 0, "end" : (clip_right - original_left) };
}
Expand Down Expand Up @@ -1182,7 +1189,7 @@ $scope.SetTrackLabel = function (label) {

return transition_size;
};

// Search through clips and transitions to find the closest element within a given threshold
$scope.GetNearbyPosition = function(pixel_positions, threshold, ignore_ids) {
// init some vars
Expand All @@ -1205,11 +1212,11 @@ $scope.SetTrackLabel = function (label) {
if (ignore_ids.hasOwnProperty(clip.id)) {
continue;
}

diffs.push({'diff' : position - clip_left_position, 'position' : clip_left_position}, // left side of clip
{'diff' : position - clip_right_position, 'position' : clip_right_position}); // right side of clip
}

// Add transition positions to array
for (var index = 0; index < $scope.project.effects.length; index++) {
var transition = $scope.project.effects[index];
Expand All @@ -1221,7 +1228,7 @@ $scope.SetTrackLabel = function (label) {
if (ignore_ids.hasOwnProperty(transition.id)) {
continue;
}

diffs.push({'diff' : position - tran_left_position, 'position' : tran_left_position}, // left side of transition
{'diff' : position - tran_right_position, 'position' : tran_right_position}); // right side of transition
}
Expand All @@ -1239,13 +1246,13 @@ $scope.SetTrackLabel = function (label) {
var playhead_pixel_position = $scope.project.playhead_position * $scope.pixelsPerSecond;
var playhead_diff = position - playhead_pixel_position;
diffs.push({'diff' : playhead_diff, 'position' : playhead_pixel_position });

// Loop through diffs (and find the smallest one)
for (var diff_index = 0; diff_index < diffs.length; diff_index++) {
var diff = diffs[diff_index].diff;
var position = diffs[diff_index].position;
var abs_diff = Math.abs(diff);

// Check if this clip is nearby
if (abs_diff < smallest_abs_diff && abs_diff <= threshold) {
// This one is smaller
Expand All @@ -1255,16 +1262,16 @@ $scope.SetTrackLabel = function (label) {
}
}
}

// no nearby found?
if (smallest_diff === 900.0) {
smallest_diff = 0.0;
}

// Return closest nearby position
return [smallest_diff, snapping_position];
};

// Show the nearby snapping line
$scope.ShowSnapline = function(position) {
if (position != $scope.snapline_position || !$scope.snapline) {
Expand All @@ -1275,7 +1282,7 @@ $scope.SetTrackLabel = function (label) {
});
}
};

// Hide the nearby snapping line
$scope.HideSnapline = function() {
if ($scope.snapline) {
Expand All @@ -1285,7 +1292,7 @@ $scope.SetTrackLabel = function (label) {
});
}
};

// Find a track JSON object at a given y coordinate (if any)
$scope.GetTrackAtY = function(y) {
// Loop through each layer (looking for the closest track based on Y coordinate)
Expand Down Expand Up @@ -1348,7 +1355,7 @@ $scope.SetTrackLabel = function (label) {
// Loop through each UpdateAction
for (var action_index = 0; action_index < jsonDiff.length; action_index++) {
var action = jsonDiff[action_index];

// Iterate through the key levels (looking for a matching element in the $scope.project)
var previous_object = null;
var current_object = $scope.project;
Expand All @@ -1367,7 +1374,7 @@ $scope.SetTrackLabel = function (label) {
previous_object = current_object;
current_object = current_object[key_value];
current_key = key_value;

}
else if (key_value.constructor == Object) {
// Get the id from the object (if any)
Expand All @@ -1381,7 +1388,7 @@ $scope.SetTrackLabel = function (label) {
current_position = 0;
for (var child_index = 0; child_index < current_object.length; child_index++) {
var child_object = current_object[child_index];

// Find matching child
if (child_object.hasOwnProperty("id") && child_object.id == id) {
// set current level and previous level
Expand Down Expand Up @@ -1458,10 +1465,10 @@ $scope.SetTrackLabel = function (label) {
// return true
return true;
};

// Load entire project data JSON from UpdateManager (i.e. user opened an existing project)
$scope.LoadJson = function(EntireProjectJson) {

$scope.$apply(function() {
// Update the entire JSON object for the entire timeline
$scope.project = EntireProjectJson.value;
Expand All @@ -1481,8 +1488,8 @@ $scope.SetTrackLabel = function (label) {
scrollLeft: 0
}, 'slow');

// Update playhead position and time readout
$scope.MovePlayhead($scope.project.playhead_position)
// Update playhead position and time readout
$scope.MovePlayhead($scope.project.playhead_position)

// return true
return true;
Expand Down

0 comments on commit b0fe642

Please sign in to comment.