Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_nla.h4
-rw-r--r--source/blender/blenkernel/intern/nla.c52
-rw-r--r--source/blender/editors/animation/keyframing.c237
-rw-r--r--source/blender/editors/include/ED_keyframing.h13
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c17
-rw-r--r--source/blender/makesrna/intern/rna_nla.c36
6 files changed, 255 insertions, 104 deletions
diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h
index 5cb967c9c59..7fdff7e41f7 100644
--- a/source/blender/blenkernel/BKE_nla.h
+++ b/source/blender/blenkernel/BKE_nla.h
@@ -80,8 +80,12 @@ short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
/* ............ */
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
+
short BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
+void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip);
+
+/* ............ */
void BKE_nla_action_pushdown(struct AnimData *adt);
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 511623f46fc..217444d16d2 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1049,6 +1049,58 @@ short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
/* should be first now */
return 1;
}
+
+/* Validate the NLA-Strips 'control' F-Curves based on the flags set*/
+void BKE_nlastrip_validate_fcurves (NlaStrip *strip)
+{
+ FCurve *fcu;
+
+ /* sanity checks */
+ if (strip == NULL)
+ return;
+
+ /* if controlling influence... */
+ if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
+ /* try to get F-Curve */
+ fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
+
+ /* add one if not found */
+ if (fcu == NULL) {
+ /* make new F-Curve */
+ fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
+ BLI_addtail(&strip->fcurves, fcu);
+
+ /* set default flags */
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+
+ /* store path - make copy, and store that */
+ fcu->rna_path= BLI_strdupn("influence", 9);
+
+ // TODO: insert a few keyframes to ensure default behaviour?
+ }
+ }
+
+ /* if controlling time... */
+ if (strip->flag & NLASTRIP_FLAG_USR_TIME) {
+ /* try to get F-Curve */
+ fcu= list_find_fcurve(&strip->fcurves, "strip_time", 0);
+
+ /* add one if not found */
+ if (fcu == NULL) {
+ /* make new F-Curve */
+ fcu= MEM_callocN(sizeof(FCurve), "NlaStrip FCurve");
+ BLI_addtail(&strip->fcurves, fcu);
+
+ /* set default flags */
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+
+ /* store path - make copy, and store that */
+ fcu->rna_path= BLI_strdupn("strip_time", 10);
+
+ // TODO: insert a few keyframes to ensure default behaviour?
+ }
+ }
+}
/* Tools ------------------------------------------- */
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 331e2d0894e..ac195f42f03 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -54,6 +54,7 @@
#include "BKE_action.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
+#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_context.h"
@@ -722,9 +723,119 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
/* ------------------------- Insert Key API ------------------------- */
+/* Secondary Keyframing API call:
+ * Use this when validation of necessary animation data is not necessary, since an RNA-pointer to the necessary
+ * data being keyframed, and a pointer to the F-Curve to use have both been provided.
+ *
+ * The flag argument is used for special settings that alter the behaviour of
+ * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
+ * and extra keyframe filtering.
+ */
+short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, float cfra, short flag)
+{
+ float curval= 0.0f;
+
+ /* no F-Curve to add keyframe to? */
+ if (fcu == NULL) {
+ printf("ERROR: no F-Curve to add keyframes to \n");
+ return 0;
+ }
+
+ /* if no property given yet, try to validate from F-Curve info */
+ if ((ptr.id.data == NULL) && (ptr.data==NULL)) {
+ printf("ERROR: no RNA-pointer available to retrieve values for keyframing from\n");
+ return 0;
+ }
+ if (prop == NULL) {
+ PointerRNA tmp_ptr;
+
+ /* try to get property we should be affecting */
+ if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) {
+ /* property not found... */
+ char *idname= (ptr.id.data) ? ((ID *)ptr.id.data)->name : "<No ID-Pointer>";
+
+ printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", idname, fcu->rna_path);
+ return 0;
+ }
+ else {
+ /* property found, so overwrite 'ptr' to make later code easier */
+ ptr= tmp_ptr;
+ }
+ }
+
+ /* 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;
+ }
+
+ /* obtain value to give keyframe */
+ if ( (flag & INSERTKEY_MATRIX) &&
+ (visualkey_can_use(&ptr, prop)) )
+ {
+ /* visual-keying is only available for object and pchan datablocks, as
+ * it works by keyframing using a value extracted from the final matrix
+ * instead of using the kt system to extract a value.
+ */
+ curval= visualkey_get_value(&ptr, prop, fcu->array_index);
+ }
+ else {
+ /* read value from system */
+ curval= setting_get_rna_value(&ptr, prop, fcu->array_index);
+ }
+
+ /* only insert keyframes where they are needed */
+ if (flag & INSERTKEY_NEEDED) {
+ short insert_mode;
+
+ /* check whether this curve really needs a new keyframe */
+ insert_mode= new_key_needed(fcu, cfra, curval);
+
+ /* insert new keyframe at current frame */
+ if (insert_mode)
+ insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+
+ /* delete keyframe immediately before/after newly added */
+ switch (insert_mode) {
+ case KEYNEEDED_DELPREV:
+ delete_fcurve_key(fcu, fcu->totvert-2, 1);
+ break;
+ case KEYNEEDED_DELNEXT:
+ delete_fcurve_key(fcu, 1, 1);
+ break;
+ }
+
+ /* only return success if keyframe added */
+ if (insert_mode)
+ return 1;
+ }
+ else {
+ /* just insert keyframe */
+ insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
+
+ /* return success */
+ return 1;
+ }
+
+ /* failed */
+ return 0;
+}
+
/* Main Keyframing API call:
- * Use this when validation of necessary animation data isn't necessary as it
- * already exists. It will insert a keyframe using the current value being keyframed.
+ * Use this when validation of necessary animation data is necessary, since it may not exist yet.
*
* The flag argument is used for special settings that alter the behaviour of
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
@@ -744,102 +855,31 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
}
/* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */
- if (act == NULL)
+ if (act == NULL) {
+ AnimData *adt= BKE_animdata_from_id(id);
+
+ /* get action to add F-Curve+keyframe to */
act= verify_adt_action(id, 1);
+
+ /* apply NLA-mapping to frame to use (if applicable) */
+ cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
+ }
fcu= verify_fcurve(act, group, rna_path, array_index, 1);
- /* only continue if we have an F-Curve to add keyframe to */
- if (fcu) {
- float curval= 0.0f;
+ /* apply special time tweaking */
+ // XXX check on this stuff...
+ if (GS(id->name) == ID_OB) {
+ //Object *ob= (Object *)id;
- /* 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;
- }
-
- /* apply special time tweaking */
- // XXX check on this stuff...
- if (GS(id->name) == ID_OB) {
- //Object *ob= (Object *)id;
-
- /* apply NLA-scaling (if applicable) */
- //cfra= get_action_frame(ob, cfra);
-
- /* ancient time-offset cruft */
- //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
- // /* actually frametofloat calc again! */
- // cfra-= give_timeoffset(ob)*scene->r.framelen;
- //}
- }
-
- /* obtain value to give keyframe */
- if ( (flag & INSERTKEY_MATRIX) &&
- (visualkey_can_use(&ptr, prop)) )
- {
- /* visual-keying is only available for object and pchan datablocks, as
- * it works by keyframing using a value extracted from the final matrix
- * instead of using the kt system to extract a value.
- */
- curval= visualkey_get_value(&ptr, prop, array_index);
- }
- else {
- /* read value from system */
- curval= setting_get_rna_value(&ptr, prop, array_index);
- }
-
- /* only insert keyframes where they are needed */
- if (flag & INSERTKEY_NEEDED) {
- short insert_mode;
-
- /* check whether this curve really needs a new keyframe */
- insert_mode= new_key_needed(fcu, cfra, curval);
-
- /* insert new keyframe at current frame */
- if (insert_mode)
- insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
-
- /* delete keyframe immediately before/after newly added */
- switch (insert_mode) {
- case KEYNEEDED_DELPREV:
- delete_fcurve_key(fcu, fcu->totvert-2, 1);
- break;
- case KEYNEEDED_DELNEXT:
- delete_fcurve_key(fcu, 1, 1);
- break;
- }
-
- /* only return success if keyframe added */
- if (insert_mode)
- return 1;
- }
- else {
- /* just insert keyframe */
- insert_vert_fcurve(fcu, cfra, curval, (flag & INSERTKEY_FAST));
-
- /* return success */
- return 1;
- }
+ /* ancient time-offset cruft */
+ //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
+ // /* actually frametofloat calc again! */
+ // cfra-= give_timeoffset(ob)*scene->r.framelen;
+ //}
}
- /* no F-Curve to add keyframes to */
- printf("ERROR: no F-Curve to add keyframes to \n");
-
- /* return failure */
- return 0;
+ /* insert keyframe */
+ return insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
}
/* ************************************************** */
@@ -864,6 +904,9 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
/* if no action is provided, use the default one attached to this ID-block */
AnimData *adt= BKE_animdata_from_id(id);
act= adt->action;
+
+ /* apply NLA-mapping to frame to use (if applicable) */
+ cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
}
/* we don't check the validity of the path here yet, but it should be ok... */
fcu= verify_fcurve(act, group, rna_path, array_index, 0);
@@ -877,9 +920,6 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
if (GS(id->name) == ID_OB) {
//Object *ob= (Object *)id;
- /* apply NLA-scaling (if applicable) */
- // cfra= get_action_frame(ob, cfra);
-
/* ancient time-offset cruft */
//if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
// /* actually frametofloat calc again! */
@@ -1266,6 +1306,13 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
MEM_freeN(path);
}
+ else if (ptr.type == &RNA_NlaStrip) {
+ /* handle special vars for NLA-strips */
+ NlaStrip *strip= (NlaStrip *)ptr.data;
+ FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
+
+ success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
+ }
else {
if (G.f & G_DEBUG)
printf("Button Insert-Key: no path to property \n");
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 9d063910aa9..ffebb42ce99 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -43,6 +43,9 @@ struct bConstraint;
struct bContext;
struct wmOperatorType;
+struct PointerRNA;
+struct PropertyRNA;
+
/* ************ Keyframing Management **************** */
/* Get (or add relevant data to be able to do so) the Active Action for the given
@@ -71,6 +74,16 @@ void insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag);
/* -------- */
+/* Secondary Keyframing API calls:
+ * Use this to insert a keyframe using the current value being keyframed, in the
+ * nominated F-Curve (no creation of animation data performed). Returns success.
+ */
+short insert_keyframe_direct(struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, short flag);
+
+
+
+/* -------- */
+
/* Main Keyframing API calls:
* Use this to create any necessary animation data, and then insert a keyframe
* using the current value being keyframed, in the relevant place. Returns success.
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 38ac59cbc9e..d09cc6a1e53 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -271,7 +271,7 @@ static void nla_panel_actclip(const bContext *C, Panel *pa)
uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0, 0, 0);
/* action extents */
- // XXX custom names were used here... probably not necessary in future?
+ // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
column= uiLayoutColumn(layout, 1);
uiItemL(column, "Action Extents:", 0);
uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0, 0, 0);
@@ -289,7 +289,7 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
{
PointerRNA strip_ptr;
uiLayout *layout= pa->layout;
- uiLayout *column;
+ uiLayout *column, *subcolumn;
uiBlock *block;
/* check context and also validity of pointer */
@@ -300,14 +300,19 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa)
uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
column= uiLayoutColumn(layout, 1);
- uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit
uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0, 0, 0);
- uiItemR(column, NULL, 0, &strip_ptr, "influence", 0, 0, 0);
+ subcolumn= uiLayoutColumn(column, 1);
+ uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_influence"));
+ uiItemR(subcolumn, NULL, 0, &strip_ptr, "influence", 0, 0, 0);
+
+
column= uiLayoutColumn(layout, 1);
- uiLayoutSetEnabled(column, 0); // XXX for now, don't allow user to edit
uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0, 0, 0);
- uiItemR(column, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0);
+
+ subcolumn= uiLayoutColumn(column, 1);
+ uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_time"));
+ uiItemR(subcolumn, NULL, 0, &strip_ptr, "strip_time", 0, 0, 0);
}
/* F-Modifiers for active NLA-Strip */
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index b0149d29e69..219feaad09b 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -40,6 +40,9 @@
#include <stdio.h>
#include <math.h>
+/* needed for some of the validation stuff... */
+#include "BKE_nla.h"
+
/* temp constant defined for these funcs only... */
#define NLASTRIP_MIN_LEN_THRESH 0.1f
@@ -196,6 +199,32 @@ static void rna_NlaStrip_action_end_frame_set(PointerRNA *ptr, float value)
data->actend= value;
}
+static void rna_NlaStrip_animated_influence_set(PointerRNA *ptr, int value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+
+ if (value) {
+ /* set the flag, then make sure a curve for this exists */
+ data->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+ BKE_nlastrip_validate_fcurves(data);
+ }
+ else
+ data->flag &= ~NLASTRIP_FLAG_USR_INFLUENCE;
+}
+
+static void rna_NlaStrip_animated_time_set(PointerRNA *ptr, int value)
+{
+ NlaStrip *data= (NlaStrip*)ptr->data;
+
+ if (value) {
+ /* set the flag, then make sure a curve for this exists */
+ data->flag |= NLASTRIP_FLAG_USR_TIME;
+ BKE_nlastrip_validate_fcurves(data);
+ }
+ else
+ data->flag &= ~NLASTRIP_FLAG_USR_TIME;
+}
+
#else
void rna_def_nlastrip(BlenderRNA *brna)
@@ -321,14 +350,15 @@ void rna_def_nlastrip(BlenderRNA *brna)
prop= RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate.");
+ // TODO: should the animated_influence/time settings be animatable themselves?
prop= RNA_def_property(srna, "animated_influence", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable
RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_influence_set");
RNA_def_property_ui_text(prop, "Animated Influence", "Influence setting is controlled by an F-Curve rather than automatically determined.");
prop= RNA_def_property(srna, "animated_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now, not editable
- RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_INFLUENCE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", NLASTRIP_FLAG_USR_TIME);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_NlaStrip_animated_time_set");
RNA_def_property_ui_text(prop, "Animated Strip Time", "Strip time is controlled by an F-Curve rather than automatically determined.");
/* settings */