forked from bartvdbraak/blender
Zoom to frame options, requested by the Hwoozeberry (dutch translation)
team. There are 3 options here: 1) Keep range (previous behaviour) 2) Seconds - allows a specified offset in seconds around current frame 3) keyframes - zoom to include a number of keyframes around the cursor Options 2 and 3 have their own properties to tweak the behaviour and all options can be found in User Preferences->Interface under the 2D viewports section. Number 3 will probably need some refinement so commiting here for the hwoozeberry team to test first.
This commit is contained in:
parent
c86a6f3efb
commit
e4c93dc7db
@ -200,6 +200,11 @@ class USERPREF_PT_interface(Panel):
|
|||||||
col.label(text="2D Viewports:")
|
col.label(text="2D Viewports:")
|
||||||
col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
|
col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
|
||||||
col.prop(view, "timecode_style")
|
col.prop(view, "timecode_style")
|
||||||
|
col.prop(view, "view_frame_type")
|
||||||
|
if (view.view_frame_type == 'SECONDS'):
|
||||||
|
col.prop(view, "view_frame_seconds")
|
||||||
|
elif (view.view_frame_type == 'KEYFRAMES'):
|
||||||
|
col.prop(view, "view_frame_keyframes")
|
||||||
|
|
||||||
row.separator()
|
row.separator()
|
||||||
row.separator()
|
row.separator()
|
||||||
|
@ -34,17 +34,25 @@
|
|||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
#include "DNA_userdef_types.h"
|
#include "DNA_userdef_types.h"
|
||||||
|
#include "DNA_screen_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_gpencil_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "BLI_timecode.h"
|
#include "BLI_timecode.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
#include "BLI_rect.h"
|
||||||
|
#include "BLI_dlrbTree.h"
|
||||||
|
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_nla.h"
|
#include "BKE_nla.h"
|
||||||
|
#include "BKE_mask.h"
|
||||||
|
|
||||||
#include "ED_anim_api.h"
|
#include "ED_anim_api.h"
|
||||||
#include "ED_keyframes_edit.h"
|
#include "ED_keyframes_edit.h"
|
||||||
|
#include "ED_keyframes_draw.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
@ -381,4 +389,136 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag
|
|||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) {
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
Object *ob = CTX_data_active_object(C);
|
||||||
|
bGPdata *gpd = CTX_data_gpencil_data(C);
|
||||||
|
Mask *mask = CTX_data_edit_mask(C);
|
||||||
|
bDopeSheet ads = {NULL};
|
||||||
|
DLRBT_Tree keys;
|
||||||
|
ActKeyColumn *aknext, *akprev;
|
||||||
|
float cfranext, cfraprev;
|
||||||
|
bool donenext = false, doneprev = false;
|
||||||
|
int nextcount = 0, prevcount = 0;
|
||||||
|
|
||||||
|
cfranext = cfraprev = (float)(CFRA);
|
||||||
|
|
||||||
|
/* init binarytree-list for getting keyframes */
|
||||||
|
BLI_dlrbTree_init(&keys);
|
||||||
|
|
||||||
|
/* seed up dummy dopesheet context with flags to perform necessary filtering */
|
||||||
|
if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
|
||||||
|
/* only selected channels are included */
|
||||||
|
ads.filterflag |= ADS_FILTER_ONLYSEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* populate tree with keyframe nodes */
|
||||||
|
scene_to_keylist(&ads, scene, &keys, NULL);
|
||||||
|
|
||||||
|
if (ob)
|
||||||
|
ob_to_keylist(&ads, ob, &keys, NULL);
|
||||||
|
|
||||||
|
gpencil_to_keylist(&ads, gpd, &keys);
|
||||||
|
|
||||||
|
if (mask) {
|
||||||
|
MaskLayer *masklay = BKE_mask_layer_active(mask);
|
||||||
|
mask_to_keylist(&ads, masklay, &keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build linked-list for searching */
|
||||||
|
BLI_dlrbTree_linkedlist_sync(&keys);
|
||||||
|
|
||||||
|
/* find matching keyframe in the right direction */
|
||||||
|
do {
|
||||||
|
aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);
|
||||||
|
|
||||||
|
if (aknext) {
|
||||||
|
if (CFRA == (int)aknext->cfra) {
|
||||||
|
/* make this the new starting point for the search and ignore */
|
||||||
|
cfranext = aknext->cfra;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* this changes the frame, so set the frame and we're done */
|
||||||
|
if (++nextcount == U.view_frame_keyframes)
|
||||||
|
donenext = true;
|
||||||
|
}
|
||||||
|
cfranext = aknext->cfra;
|
||||||
|
}
|
||||||
|
} while ((aknext != NULL) && (donenext == false));
|
||||||
|
|
||||||
|
do {
|
||||||
|
akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);
|
||||||
|
|
||||||
|
if (akprev) {
|
||||||
|
if (CFRA == (int)akprev->cfra) {
|
||||||
|
/* make this the new starting point for the search */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* this changes the frame, so set the frame and we're done */
|
||||||
|
if (++prevcount == U.view_frame_keyframes)
|
||||||
|
doneprev = true;
|
||||||
|
}
|
||||||
|
cfraprev = akprev->cfra;
|
||||||
|
}
|
||||||
|
} while ((akprev != NULL) && (doneprev == false));
|
||||||
|
|
||||||
|
/* free temp stuff */
|
||||||
|
BLI_dlrbTree_free(&keys);
|
||||||
|
|
||||||
|
/* any success? */
|
||||||
|
if (doneprev || donenext) {
|
||||||
|
if (doneprev)
|
||||||
|
*prevfra = cfraprev;
|
||||||
|
else
|
||||||
|
*prevfra = CFRA - (cfranext - CFRA);
|
||||||
|
|
||||||
|
if (donenext)
|
||||||
|
*nextfra = cfranext;
|
||||||
|
else
|
||||||
|
*nextfra = CFRA + (CFRA - cfraprev);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
|
||||||
|
{
|
||||||
|
ARegion *ar = CTX_wm_region(C);
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
float w = BLI_rctf_size_x(&ar->v2d.cur);
|
||||||
|
rctf newrct;
|
||||||
|
int nextfra, prevfra;
|
||||||
|
|
||||||
|
switch (U.view_frame_type) {
|
||||||
|
case ZOOM_FRAME_MODE_SECONDS:
|
||||||
|
newrct.xmax = scene->r.cfra + U.view_frame_seconds * FPS + 1;
|
||||||
|
newrct.xmin = scene->r.cfra - U.view_frame_seconds * FPS - 1;
|
||||||
|
newrct.ymax = ar->v2d.cur.ymax;
|
||||||
|
newrct.ymin = ar->v2d.cur.ymin;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* hardest case of all, look for all keyframes around frame and display those */
|
||||||
|
case ZOOM_FRAME_MODE_KEYFRAMES:
|
||||||
|
if (find_prev_next_keyframes(C, &nextfra, &prevfra)) {
|
||||||
|
newrct.xmax = nextfra;
|
||||||
|
newrct.xmin = prevfra;
|
||||||
|
newrct.ymax = ar->v2d.cur.ymax;
|
||||||
|
newrct.ymin = ar->v2d.cur.ymin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* else drop through, keep range instead */
|
||||||
|
|
||||||
|
case ZOOM_FRAME_MODE_KEEP_RANGE:
|
||||||
|
default:
|
||||||
|
newrct.xmax = scene->r.cfra + (w / 2);
|
||||||
|
newrct.xmin = scene->r.cfra - (w / 2);
|
||||||
|
newrct.ymax = ar->v2d.cur.ymax;
|
||||||
|
newrct.ymin = ar->v2d.cur.ymin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
|
||||||
|
}
|
||||||
/* *************************************************** */
|
/* *************************************************** */
|
||||||
|
@ -659,6 +659,7 @@ void ANIM_list_elem_update(struct Scene *scene, bAnimListElem *ale);
|
|||||||
/* data -> channels syncing */
|
/* data -> channels syncing */
|
||||||
void ANIM_sync_animchannels_to_data(const struct bContext *C);
|
void ANIM_sync_animchannels_to_data(const struct bContext *C);
|
||||||
|
|
||||||
|
void ANIM_center_frame(struct bContext *C, int smooth_viewtx);
|
||||||
/* ************************************************* */
|
/* ************************************************* */
|
||||||
/* OPERATORS */
|
/* OPERATORS */
|
||||||
|
|
||||||
|
@ -233,7 +233,6 @@ void ED_keymap_view2d(struct wmKeyConfig *keyconf);
|
|||||||
|
|
||||||
void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar,
|
void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar,
|
||||||
const struct rctf *cur, const int smooth_viewtx);
|
const struct rctf *cur, const int smooth_viewtx);
|
||||||
void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx);
|
|
||||||
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
|
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
|
||||||
|
|
||||||
#endif /* __UI_VIEW2D_H__ */
|
#endif /* __UI_VIEW2D_H__ */
|
||||||
|
@ -1468,21 +1468,6 @@ void UI_view2d_smooth_view(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_view2d_center_frame(struct bContext *C, int smooth_viewtx)
|
|
||||||
{
|
|
||||||
ARegion *ar = CTX_wm_region(C);
|
|
||||||
Scene *scene = CTX_data_scene(C);
|
|
||||||
float w = BLI_rctf_size_x(&ar->v2d.cur);
|
|
||||||
rctf newrct;
|
|
||||||
|
|
||||||
newrct.xmax = scene->r.cfra + (w / 2);
|
|
||||||
newrct.xmin = scene->r.cfra - (w / 2);
|
|
||||||
newrct.ymax = ar->v2d.cur.ymax;
|
|
||||||
newrct.ymin = ar->v2d.cur.ymin;
|
|
||||||
|
|
||||||
UI_view2d_smooth_view(C, ar, &newrct, smooth_viewtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only meant for timer usage */
|
/* only meant for timer usage */
|
||||||
static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
|
static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -429,7 +429,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
static int actkeys_view_frame_exec(bContext *C, wmOperator *op)
|
static int actkeys_view_frame_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
||||||
UI_view2d_center_frame(C, smooth_viewtx);
|
ANIM_center_frame(C, smooth_viewtx);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op)
|
|||||||
static int graphkeys_view_frame_exec(bContext *C, wmOperator *op)
|
static int graphkeys_view_frame_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
||||||
UI_view2d_center_frame(C, smooth_viewtx);
|
ANIM_center_frame(C, smooth_viewtx);
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +503,10 @@ typedef struct UserDef {
|
|||||||
char ipo_new; /* interpolation mode for newly added F-Curves */
|
char ipo_new; /* interpolation mode for newly added F-Curves */
|
||||||
char keyhandles_new; /* handle types for newly added keyframes */
|
char keyhandles_new; /* handle types for newly added keyframes */
|
||||||
char gpu_select_method;
|
char gpu_select_method;
|
||||||
char pad1;
|
char view_frame_type;
|
||||||
|
|
||||||
|
int view_frame_keyframes; /* number of keyframes to zoom around current frame */
|
||||||
|
float view_frame_seconds; /* seconds to zoom around current frame */
|
||||||
|
|
||||||
short scrcastfps; /* frame rate for screencast to be played back */
|
short scrcastfps; /* frame rate for screencast to be played back */
|
||||||
short scrcastwait; /* milliseconds between screencast snapshots */
|
short scrcastwait; /* milliseconds between screencast snapshots */
|
||||||
@ -686,6 +689,13 @@ typedef enum eAutokey_Mode {
|
|||||||
AUTOKEY_MODE_EDITKEYS = 5
|
AUTOKEY_MODE_EDITKEYS = 5
|
||||||
} eAutokey_Mode;
|
} eAutokey_Mode;
|
||||||
|
|
||||||
|
/* Zoom to frame mode */
|
||||||
|
typedef enum eZoomFrame_Mode {
|
||||||
|
ZOOM_FRAME_MODE_KEEP_RANGE = 0,
|
||||||
|
ZOOM_FRAME_MODE_SECONDS = 1,
|
||||||
|
ZOOM_FRAME_MODE_KEYFRAMES = 2
|
||||||
|
} eZoomFrame_Mode;
|
||||||
|
|
||||||
/* Auto-Keying flag
|
/* Auto-Keying flag
|
||||||
* U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days)
|
* U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days)
|
||||||
* note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL)
|
* note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL)
|
||||||
|
@ -3264,6 +3264,13 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
|||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static EnumPropertyItem zoom_frame_modes[] = {
|
||||||
|
{ZOOM_FRAME_MODE_KEEP_RANGE, "KEEP_RANGE", 0, "Keep Range", ""},
|
||||||
|
{ZOOM_FRAME_MODE_SECONDS, "SECONDS", 0, "Seconds", ""},
|
||||||
|
{ZOOM_FRAME_MODE_KEYFRAMES, "KEYFRAMES", 0, "Keyframes", ""},
|
||||||
|
{0, NULL, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
PropertyRNA *prop;
|
PropertyRNA *prop;
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
|
|
||||||
@ -3505,6 +3512,22 @@ static void rna_def_userdef_view(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "TimeCode Style",
|
RNA_def_property_ui_text(prop, "TimeCode Style",
|
||||||
"Format of Time Codes displayed when not displaying timing in terms of frames");
|
"Format of Time Codes displayed when not displaying timing in terms of frames");
|
||||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "view_frame_type", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, zoom_frame_modes);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "view_frame_type");
|
||||||
|
RNA_def_property_ui_text(prop, "Zoom To Frame Type", "How zooming to frame focuses around current frame");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "view_frame_keyframes", PROP_INT, PROP_NONE);
|
||||||
|
RNA_def_property_range(prop, 1, 500);
|
||||||
|
RNA_def_property_ui_text(prop, "Zoom Keyframes",
|
||||||
|
"Keyframes around cursor that we zoom around");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "view_frame_seconds", PROP_FLOAT, PROP_TIME);
|
||||||
|
RNA_def_property_range(prop, 0.0, 10000.0);
|
||||||
|
RNA_def_property_ui_text(prop, "Zoom Seconds",
|
||||||
|
"Seconds around cursor that we zoom around");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_userdef_edit(BlenderRNA *brna)
|
static void rna_def_userdef_edit(BlenderRNA *brna)
|
||||||
|
Loading…
Reference in New Issue
Block a user