VSE: Add frame selected operator for preview
This operator moves the view to show the selected visible strips. Reviewed By: ISS Differential Revision: https://developer.blender.org/D14222
This commit is contained in:
parent
2bd9cbe405
commit
e16ff4132e
Notes:
blender-bot
2023-10-04 09:42:55 +02:00
Referenced by pull request #111987, Fix memory leak in the VSE "Frame Selected" operator
|
@ -2960,6 +2960,7 @@ def km_sequencerpreview(params):
|
|||
("sequencer.select_box", {"type": 'B', "value": 'PRESS'}, None),
|
||||
|
||||
# View.
|
||||
("sequencer.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
|
||||
("sequencer.view_all_preview", {"type": 'HOME', "value": 'PRESS'}, None),
|
||||
("sequencer.view_all_preview", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
|
||||
("sequencer.view_ghost_border", {"type": 'O', "value": 'PRESS'}, None),
|
||||
|
|
|
@ -1866,6 +1866,7 @@ def km_sequencerpreview(params):
|
|||
("wm.search_menu", {"type": 'TAB', "value": 'PRESS'}, None),
|
||||
("sequencer.view_all_preview", {"type": 'A', "value": 'PRESS'}, None),
|
||||
("sequencer.view_all_preview", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'}, None),
|
||||
("sequencer.view_selected", {"type": 'F', "value": 'PRESS'}, None),
|
||||
("sequencer.view_ghost_border", {"type": 'O', "value": 'PRESS'}, None),
|
||||
("sequencer.view_zoom_ratio", {"type": 'NUMPAD_1', "value": 'PRESS'},
|
||||
{"properties": [("ratio", 1.0)]}),
|
||||
|
|
|
@ -429,9 +429,14 @@ class SEQUENCER_MT_view(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
if st.view_type == 'PREVIEW':
|
||||
# See above (T32595)
|
||||
layout.operator_context = 'INVOKE_REGION_PREVIEW'
|
||||
layout.operator("sequencer.view_selected", text="Frame Selected")
|
||||
|
||||
if is_sequencer_view:
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("sequencer.view_selected", text="Frame Selected")
|
||||
layout.operator("sequencer.view_all")
|
||||
layout.operator("view2d.zoom_border", text="Zoom")
|
||||
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "SEQ_iterator.h"
|
||||
#include "SEQ_select.h"
|
||||
#include "SEQ_sequencer.h"
|
||||
#include "SEQ_time.h"
|
||||
#include "SEQ_transform.h"
|
||||
|
||||
/* For menu, popup, icons, etc. */
|
||||
#include "ED_anim_api.h"
|
||||
|
@ -260,14 +262,30 @@ void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot)
|
|||
/** \name Frame Selected Operator
|
||||
* \{ */
|
||||
|
||||
static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
|
||||
static void seq_view_collection_rect_preview(Scene *scene, SeqCollection *strips, rctf *rect)
|
||||
{
|
||||
float min[2], max[2];
|
||||
SEQ_image_transform_bounding_box_from_collection(scene, strips, true, min, max);
|
||||
|
||||
rect->xmin = min[0];
|
||||
rect->xmax = max[0];
|
||||
rect->ymin = min[1];
|
||||
rect->ymax = max[1];
|
||||
|
||||
float minsize = min_ff(BLI_rctf_size_x(rect), BLI_rctf_size_y(rect));
|
||||
|
||||
/* If the size of the strip is smaller than a pixel, add padding to prevent division by zero. */
|
||||
if (minsize < 1.0f) {
|
||||
BLI_rctf_pad(rect, 20.0f, 20.0f);
|
||||
}
|
||||
|
||||
/* Add padding. */
|
||||
BLI_rctf_scale(rect, 1.1f);
|
||||
}
|
||||
|
||||
static void seq_view_collection_rect_timeline(Scene *scene, SeqCollection *strips, rctf *rect)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
Sequence *seq;
|
||||
rctf cur_new = v2d->cur;
|
||||
|
||||
int xmin = MAXFRAME * 2;
|
||||
int xmax = -MAXFRAME * 2;
|
||||
|
@ -278,49 +296,63 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
|
|||
int ymargin = 1;
|
||||
int xmargin = FPS;
|
||||
|
||||
if (ed == NULL) {
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
xmin = min_ii(xmin, seq->startdisp);
|
||||
xmax = max_ii(xmax, seq->enddisp);
|
||||
|
||||
ymin = min_ii(ymin, seq->machine);
|
||||
ymax = max_ii(ymax, seq->machine);
|
||||
}
|
||||
|
||||
xmax += xmargin;
|
||||
xmin -= xmargin;
|
||||
ymax += ymargin;
|
||||
ymin -= ymargin;
|
||||
|
||||
orig_height = BLI_rctf_size_y(rect);
|
||||
|
||||
rect->xmin = xmin;
|
||||
rect->xmax = xmax;
|
||||
|
||||
rect->ymin = ymin;
|
||||
rect->ymax = ymax;
|
||||
|
||||
/* Only zoom out vertically. */
|
||||
if (orig_height > BLI_rctf_size_y(rect)) {
|
||||
ymid = BLI_rctf_cent_y(rect);
|
||||
|
||||
rect->ymin = ymid - (orig_height / 2);
|
||||
rect->ymax = ymid + (orig_height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
SeqCollection *strips = selected_strips_from_context(C);
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
rctf cur_new = v2d->cur;
|
||||
|
||||
if (SEQ_collection_len(strips) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
|
||||
if (seq->flag & SELECT) {
|
||||
xmin = min_ii(xmin, seq->startdisp);
|
||||
xmax = max_ii(xmax, seq->enddisp);
|
||||
|
||||
ymin = min_ii(ymin, seq->machine);
|
||||
ymax = max_ii(ymax, seq->machine);
|
||||
}
|
||||
if (sequencer_view_has_preview_poll(C) && !sequencer_view_preview_only_poll(C)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (ymax != 0) {
|
||||
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
||||
|
||||
xmax += xmargin;
|
||||
xmin -= xmargin;
|
||||
ymax += ymargin;
|
||||
ymin -= ymargin;
|
||||
|
||||
orig_height = BLI_rctf_size_y(&cur_new);
|
||||
|
||||
cur_new.xmin = xmin;
|
||||
cur_new.xmax = xmax;
|
||||
|
||||
cur_new.ymin = ymin;
|
||||
cur_new.ymax = ymax;
|
||||
|
||||
/* Only zoom out vertically. */
|
||||
if (orig_height > BLI_rctf_size_y(&cur_new)) {
|
||||
ymid = BLI_rctf_cent_y(&cur_new);
|
||||
|
||||
cur_new.ymin = ymid - (orig_height / 2);
|
||||
cur_new.ymax = ymid + (orig_height / 2);
|
||||
}
|
||||
|
||||
UI_view2d_smooth_view(C, region, &cur_new, smooth_viewtx);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
if (region && region->regiontype == RGN_TYPE_PREVIEW) {
|
||||
seq_view_collection_rect_preview(scene, strips, &cur_new);
|
||||
}
|
||||
return OPERATOR_CANCELLED;
|
||||
else {
|
||||
seq_view_collection_rect_timeline(scene, strips, &cur_new);
|
||||
}
|
||||
|
||||
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
||||
UI_view2d_smooth_view(C, region, &cur_new, smooth_viewtx);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SEQUENCER_OT_view_selected(wmOperatorType *ot)
|
||||
|
|
|
@ -251,17 +251,9 @@ static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
|
|||
SEQ_filter_selected_strips(strips);
|
||||
int selected_strips = SEQ_collection_len(strips);
|
||||
if (selected_strips > 0) {
|
||||
INIT_MINMAX2(r_min, r_max);
|
||||
has_select = true;
|
||||
|
||||
Sequence *seq;
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
float quad[4][2];
|
||||
SEQ_image_transform_quad_get(scene, seq, selected_strips != 1, quad);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
minmax_v2v2_v2(r_min, r_max, quad[i]);
|
||||
}
|
||||
}
|
||||
SEQ_image_transform_bounding_box_from_collection(
|
||||
scene, strips, selected_strips != 1, r_min, r_max);
|
||||
}
|
||||
SEQ_collection_free(strips);
|
||||
if (selected_strips > 1) {
|
||||
|
|
|
@ -119,6 +119,22 @@ void SEQ_image_preview_unit_from_px(const struct Scene *scene,
|
|||
const float co_src[2],
|
||||
float co_dst[2]);
|
||||
|
||||
/**
|
||||
* Get viewport axis aligned bounding box from a collection of sequences.
|
||||
* The collection must have one or more strips
|
||||
*
|
||||
* \param scene: Scene in which strips are located
|
||||
* \param strips: Collection of strips to get the bounding box from
|
||||
* \param apply_rotation: Include sequence rotation transform in the bounding box calculation
|
||||
* \param r_min: Minimum x and y values
|
||||
* \param r_max: Maximum x and y values
|
||||
*/
|
||||
void SEQ_image_transform_bounding_box_from_collection(struct Scene *scene,
|
||||
struct SeqCollection *strips,
|
||||
bool apply_rotation,
|
||||
float r_min[2],
|
||||
float r_max[2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -517,3 +517,18 @@ void SEQ_image_preview_unit_from_px(const Scene *scene, const float co_src[2], f
|
|||
co_dst[0] = co_src[0] / scene->r.xsch;
|
||||
co_dst[1] = co_src[1] / scene->r.ysch;
|
||||
}
|
||||
|
||||
void SEQ_image_transform_bounding_box_from_collection(
|
||||
Scene *scene, SeqCollection *strips, bool apply_rotation, float r_min[2], float r_max[2])
|
||||
{
|
||||
Sequence *seq;
|
||||
|
||||
INIT_MINMAX2(r_min, r_max);
|
||||
SEQ_ITERATOR_FOREACH (seq, strips) {
|
||||
float quad[4][2];
|
||||
SEQ_image_transform_quad_get(scene, seq, apply_rotation, quad);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
minmax_v2v2_v2(r_min, r_max, quad[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue