Animation: Move Snapping to Scene #109015

Merged
Christoph Lendenfeld merged 35 commits from ChrisLend/blender:frame_snapping into main 2023-09-05 10:07:02 +02:00
12 changed files with 90 additions and 32 deletions
Showing only changes of commit f07c49be92 - Show all commits

View File

@ -277,7 +277,14 @@ class DOPESHEET_HT_editor_buttons:
# Grease Pencil mode doesn't need snapping, as it's frame-aligned only
if st.mode != 'GPENCIL':
layout.prop(st, "auto_snap", text="")
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_anim", text="")
sub = row.row(align=True)
sub.popover(
panel="DOPESHEET_PT_snapping",
icon='NONE',
text="Modes",
)
row = layout.row(align=True)
row.prop(tool_settings, "use_proportional_action", text="", icon_only=True)
@ -292,6 +299,19 @@ class DOPESHEET_HT_editor_buttons:
)
class DOPESHEET_PT_snapping(Panel):
bl_space_type = 'DOPESHEET_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Snapping"
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Snap With")
st = context.space_data
col.prop(st, "auto_snap", expand=True)
class DOPESHEET_PT_proportional_edit(Panel):
bl_space_type = 'DOPESHEET_EDITOR'
bl_region_type = 'HEADER'
@ -870,6 +890,7 @@ classes = (
DOPESHEET_PT_gpencil_layer_relations,
DOPESHEET_PT_gpencil_layer_display,
DOPESHEET_PT_custom_props_action,
DOPESHEET_PT_snapping
)
if __name__ == "__main__": # only for live edit.

View File

@ -49,7 +49,14 @@ class GRAPH_HT_header(Header):
layout.prop(st, "pivot_point", icon_only=True)
layout.prop(st, "auto_snap", text="")
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_anim", text="")
sub = row.row(align=True)
sub.popover(
panel="GRAPH_PT_snapping",
icon='NONE',
text="Modes",
)
row = layout.row(align=True)
row.prop(tool_settings, "use_proportional_fcurve", text="", icon_only=True)
@ -94,6 +101,18 @@ class GRAPH_PT_filters(DopesheetFilterPopoverBase, Panel):
layout.separator()
DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
class GRAPH_PT_snapping(Panel):
bl_space_type = 'GRAPH_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Snapping"
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Snap With")
st = context.space_data
col.prop(st, "auto_snap", expand=True)
class GRAPH_MT_editor_menus(Menu):
bl_idname = "GRAPH_MT_editor_menus"
@ -522,6 +541,7 @@ classes = (
GRAPH_MT_snap_pie,
GRAPH_MT_view_pie,
GRAPH_PT_filters,
GRAPH_PT_snapping,
)
if __name__ == "__main__": # only for live edit.

View File

@ -33,7 +33,28 @@ class NLA_HT_header(Header):
icon='FILTER',
)
layout.prop(st, "auto_snap", text="")
row = layout.row(align=True)
tool_settings = context.tool_settings
row.prop(tool_settings, "use_snap_anim", text="")
sub = row.row(align=True)
sub.popover(
panel="DOPESHEET_PT_snapping",
icon='NONE',
text="Modes",
)
class DOPESHEET_PT_snapping(Panel):
bl_space_type = 'NLA_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Snapping"
def draw(self, context):
layout = self.layout
col = layout.column()
col.label(text="Snap With")
st = context.space_data
col.prop(st, "auto_snap", expand=True)
class NLA_PT_filters(DopesheetFilterPopoverBase, Panel):

View File

@ -613,9 +613,10 @@ static void recalcData_actedit(TransInfo *t)
const short autosnap = getAnimEdit_SnapMode(t);
TransData *td;
TransData2D *td2d;
ToolSettings *ts = t->scene->toolsettings;
int i = 0;
for (td = tc->data, td2d = tc->data_2d; i < tc->data_len; i++, td++, td2d++) {
if ((autosnap != SACTSNAP_OFF) && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
if (ts->snap_flag_anim && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
transform_snap_anim_flush_data(t, td, autosnap, td->loc);
}

View File

@ -653,7 +653,7 @@ static void flushTransGraphData(TransInfo *t)
const short autosnap = getAnimEdit_SnapMode(t);
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
ToolSettings *ts = t->scene->toolsettings;
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data; a < tc->data_len;
a++, td++, td2d++, tdg++)
@ -668,7 +668,7 @@ static void flushTransGraphData(TransInfo *t)
* - Only apply to keyframes (but never to handles).
* - Don't do this when canceling, or else these changes won't go away.
*/
if ((autosnap != SACTSNAP_OFF) && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
if (ts->snap_flag_anim && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
transform_snap_anim_flush_data(t, td, autosnap, td->loc);
}

View File

@ -486,8 +486,9 @@ static void recalcData_nla(TransInfo *t)
* NOTE: only do this when transform is still running, or we can't restore
*/
if (t->state != TRANS_CANCEL) {
const short autosnap = getAnimEdit_SnapMode(t);
if (autosnap != SACTSNAP_OFF) {
ToolSettings *ts = t->scene->toolsettings;
if (ts->snap_flag_anim) {
const short autosnap = getAnimEdit_SnapMode(t);
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
transform_snap_anim_flush_data(t, td, autosnap, td->loc);

View File

@ -615,9 +615,7 @@ static eSnapFlag snap_flag_from_spacetype(TransInfo *t)
case SPACE_GRAPH:
case SPACE_ACTION:
case SPACE_NLA:
/* These editors have their own "Auto-Snap" activation option.
* See #getAnimEdit_SnapMode. */
return eSnapFlag(0);
return eSnapFlag(ts->snap_flag_anim);
}
/* #SPACE_EMPTY.
* It can happen when the operator is called via a handle in `bpy.app.handlers`. */

View File

@ -25,7 +25,7 @@
short getAnimEdit_SnapMode(TransInfo *t)
{
short autosnap = SACTSNAP_OFF;
eAnimEdit_AutoSnap autosnap = SACTSNAP_FRAME;
if (t->spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)t->area->spacedata.first;
@ -51,19 +51,7 @@ short getAnimEdit_SnapMode(TransInfo *t)
}
}
else {
autosnap = SACTSNAP_OFF;
}
/* toggle autosnap on/off
* - when toggling on, prefer nearest frame over 1.0 frame increments
*/
if (t->modifiers & MOD_SNAP_INVERT) {
if (autosnap) {
autosnap = SACTSNAP_OFF;
}
else {
autosnap = SACTSNAP_FRAME;
}
autosnap = SACTSNAP_FRAME;
}
return autosnap;
@ -102,8 +90,6 @@ void snapFrameTransform(TransInfo *t,
deltax = floorf(deltax + 0.5f);
*r_val_final = val_initial + deltax;
break;
case SACTSNAP_OFF:
break;
}
}
@ -112,7 +98,7 @@ void transform_snap_anim_flush_data(TransInfo *t,
const eAnimEdit_AutoSnap autosnap,
float *r_val_final)
{
BLI_assert(autosnap != SACTSNAP_OFF);
BLI_assert(t->scene->toolsettings->snap_flag_anim);
float val = td->loc[0];
float ival = td->iloc[0];

View File

@ -918,8 +918,6 @@ typedef enum eAnimEdit_Context {
/* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
typedef enum eAnimEdit_AutoSnap {
/* no auto-snap */
SACTSNAP_OFF = 0,
/* snap to 1.0 frame/second intervals */
SACTSNAP_STEP = 1,
/* snap to actual frames/seconds (nla-action time) */

View File

@ -1623,7 +1623,9 @@ typedef struct ToolSettings {
short snap_flag;
short snap_flag_node;
short snap_flag_seq;
short snap_flag_anim;
short snap_uv_flag;
char _pad[6];
/** Default snap source, #eSnapSourceOP. */
/**
* TODO(@gfxcoder): Rename `snap_target` to `snap_source` to avoid previous ambiguity of

View File

@ -3279,6 +3279,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "use_snap_animation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_anim", 0);
RNA_def_property_ui_text(prop, "Snap", "Enable snapping when transforming keyframes");
RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "lock_markers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "lock_markers", 0);
RNA_def_property_ui_text(prop, "Lock Markers", "Prevent marker editing");
@ -3385,6 +3391,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_boolean_default(prop, true);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* Publish message-bus. */
prop = RNA_def_property(srna, "use_snap_anim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag_anim", SCE_SNAP);
RNA_def_property_ui_text(prop, "Snap", "Enable snapping when transforming keyframes");
RNA_def_property_ui_icon(prop, ICON_SNAP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "use_snap_uv", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_uv_flag", SCE_SNAP);
RNA_def_property_ui_text(prop, "Snap", "Snap UV during transform");

View File

@ -392,8 +392,6 @@ static const EnumPropertyItem display_channels_items[] = {
#ifndef RNA_RUNTIME
static const EnumPropertyItem autosnap_items[] = {
{SACTSNAP_OFF, "NONE", 0, "No Auto-Snap", ""},
/* {-1, "", 0, "", ""}, */
{SACTSNAP_STEP, "STEP", 0, "Frame Step", "Snap to 1.0 frame intervals"},
{SACTSNAP_TSTEP, "TIME_STEP", 0, "Second Step", "Snap to 1.0 second intervals"},
/* {-1, "", 0, "", ""}, */