From 51f5c994e9f03ec2c488ac3a2af02b43c34d7ca6 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 17 Dec 2013 09:40:52 +0100 Subject: [PATCH] Fix T37103: Keyframing custom properties issue (FCurve would not reflect Custom props type changes). Add an helper func to re-compute integer-only fcurve flags, and call it when editing custom props. Reviewed by aligorith, thanks! Summary: Proposal fix for "keyframing custom properties issue" (T37103). Reviewers: aligorith Maniphest Tasks: T37103 Differential Revision: http://developer.blender.org/D111 --- release/scripts/startup/bl_operators/wm.py | 28 +++++++ source/blender/editors/animation/keyframing.c | 76 ++++++++++++++----- .../blender/editors/include/ED_keyframing.h | 9 +++ source/blender/makesrna/intern/rna_fcurve.c | 8 ++ 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 4b954e81ee1..6a54a1ea15c 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1045,6 +1045,7 @@ class WM_OT_properties_edit(Operator): # First remove item = eval("context.%s" % data_path) + prop_type_old = type(item[prop_old]) rna_idprop_ui_prop_clear(item, prop_old) exec_str = "del item['%s']" % prop_old @@ -1067,6 +1068,33 @@ class WM_OT_properties_edit(Operator): prop_ui["description"] = self.description + # If we have changed the type of the property, update its potential anim curves! + if prop_type_old != prop_type: + data_path = '["%s"]' % prop + done = set() + def _update(fcurves): + for fcu in fcurves: + if fcu not in done and fcu.data_path == data_path: + fcu.update_autoflags(item) + done.add(fcu) + + def _update_strips(strips): + for st in strips: + if st.type in {'CLIP'} and st.action: + _update(st.action.fcurves) + elif st.type in {'META'}: + _update_strips(st.strips) + + adt = getattr(item, "animation_data", None) + if adt is not None: + if adt.action: + _update(adt.action.fcurves) + if adt.drivers: + _update(adt.drivers) + if adt.nla_tracks: + for nt in adt.nla_tracks: + _update_strips(nt.strips) + # otherwise existing buttons which reference freed # memory may crash blender [#26510] # context.area.tag_redraw() diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 07cc16aa5b6..0c4536436d3 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -229,6 +229,63 @@ FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr, return fcu; } +/* Helper */ +static void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop) +{ + /* set additional flags for the F-Curve (i.e. only integer values) */ + fcu->flag &= ~(FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES); + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + /* do nothing */ + break; + case PROP_INT: + /* do integer (only 'whole' numbers) interpolation between all points */ + fcu->flag |= FCURVE_INT_VALUES; + break; + default: + /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate + * values at all) interpolation between all points + * - however, we must also ensure that evaluated values are only integers still + */ + fcu->flag |= (FCURVE_DISCRETE_VALUES | FCURVE_INT_VALUES); + break; + } +} + +/* Update integer/discrete flags of the FCurve (used when creating/inserting keyframes, + * but also through RNA when editing an ID prop, see T37103). + */ +void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, struct PointerRNA *ptr) +{ + PointerRNA tmp_ptr; + PropertyRNA *prop; + int old_flag = fcu->flag; + + if ((ptr->id.data == NULL) && (ptr->data == NULL)) { + BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve"); + return; + } + + /* try to get property we should be affecting */ + if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) { + /* property not found... */ + const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_(""); + + BKE_reportf(reports, RPT_ERROR, + "Could not update flags for this fcurve, as RNA path is invalid for the given ID " + "(ID = %s, path = %s)", + idname, fcu->rna_path); + return; + } + + update_autoflags_fcurve_direct(fcu, prop); + + if (old_flag != fcu->flag) { + /* Same as if keyframes had been changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + } +} + /* ************************************************** */ /* KEYFRAME INSERTION */ @@ -835,24 +892,7 @@ short insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *p } } - /* set additional flags for the F-Curve (i.e. only integer values) */ - fcu->flag &= ~(FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES); - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - /* do nothing */ - break; - case PROP_INT: - /* do integer (only 'whole' numbers) interpolation between all points */ - fcu->flag |= FCURVE_INT_VALUES; - break; - default: - /* do 'discrete' (i.e. enum, boolean values which cannot take any intermediate - * values at all) interpolation between all points - * - however, we must also ensure that evaluated values are only integers still - */ - fcu->flag |= (FCURVE_DISCRETE_VALUES | FCURVE_INT_VALUES); - break; - } + update_autoflags_fcurve_direct(fcu, prop); /* obtain value to give keyframe */ if ( (flag & INSERTKEY_MATRIX) && diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index dc40efc748b..82cf216e75c 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -80,6 +80,15 @@ struct FCurve *verify_fcurve(struct bAction *act, const char group[], struct Poi /* -------- */ +/* Lesser Keyframing API call: + * Update integer/discrete flags of the FCurve (used when creating/inserting keyframes, + * but also through RNA when editing an ID prop, see T37103). + */ +void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, struct ReportList *reports, + struct PointerRNA *ptr); + +/* -------- */ + /* Lesser Keyframing API call: * Use this when validation of necessary animation data isn't necessary as it already * exists, and there is a beztriple that can be directly copied into the array. diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 2036257e5d7..e2eff5c4b32 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -1858,6 +1858,14 @@ static void rna_def_fcurve(BlenderRNA *brna) "Min/Max values", -FLT_MAX, FLT_MAX); RNA_def_property_flag(parm, PROP_THICK_WRAP); RNA_def_function_output(func, parm); + + func = RNA_def_function(srna, "update_autoflags", "update_autoflags_fcurve"); /* calls the C/API direct */ + RNA_def_function_ui_description(func, "Update FCurve flags set automatically from affected property " + "(currently, integer/discrete flags set when the property is not a float)"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "data", "AnyType", "Data", + "Data containing the property controlled by given FCurve"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); } /* *********************** */