forked from bartvdbraak/blender
Keyframing Operators: Improved Error Messages
* Keyframing operators now use the reports system for displaying all its error messages. - The benefit of this is that users no longer need to check the console for error messages if keyframing fails. - Unfortunately, reports are not currently viewable in any space/view in Blender, so... * Added a temporary operator (UI_OT_reports_to_textblock), which can be accessed in the UI from the button which appears in place of the icon when more than one report exists. This dumps the current list of reports to a textblock "Recent Reports", from which they can be viewed. This isn't really nice, but at least we now have a way to view these again, which makes debugging some things a pain. * Bugfix #24606 - when trying to add keyframes to F-Curves with F-Modifiers already which alter the curve significantly enough that the keyframes will have no effect, there are now warnings which aim to alleviate any confusion.
This commit is contained in:
parent
91217f117f
commit
f713761039
@ -214,6 +214,14 @@ void calc_fcurve_range(struct FCurve *fcu, float *min, float *max);
|
||||
/* get the bounding-box extents for F-Curve */
|
||||
void calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax);
|
||||
|
||||
/* .............. */
|
||||
|
||||
/* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */
|
||||
short fcurve_are_keyframes_usable(struct FCurve *fcu);
|
||||
|
||||
/* Can keyframes be added to F-Curve? */
|
||||
short fcurve_is_keyframable(struct FCurve *fcu);
|
||||
|
||||
/* -------- Curve Sanity -------- */
|
||||
|
||||
void calchandles_fcurve(struct FCurve *fcu);
|
||||
|
@ -163,7 +163,7 @@ void copy_fcurves (ListBase *dst, ListBase *src)
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------- Finding -------------------------- */
|
||||
/* ----------------- Finding F-Curves -------------------------- */
|
||||
|
||||
/* high level function to get an fcurve from C without having the rna */
|
||||
FCurve *id_data_find_fcurve(ID *id, void *data, StructRNA *type, char *prop_name, int index)
|
||||
@ -298,36 +298,36 @@ int list_find_data_fcurves (ListBase *dst, ListBase *src, const char *dataPrefix
|
||||
return matches;
|
||||
}
|
||||
|
||||
FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
|
||||
FCurve *rna_get_fcurve (PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, int *driven)
|
||||
{
|
||||
FCurve *fcu= NULL;
|
||||
|
||||
*driven= 0;
|
||||
|
||||
/* there must be some RNA-pointer + property combon */
|
||||
if(prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
|
||||
if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) {
|
||||
AnimData *adt= BKE_animdata_from_id(ptr->id.data);
|
||||
char *path;
|
||||
|
||||
if(adt) {
|
||||
if((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
|
||||
if (adt) {
|
||||
if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) {
|
||||
/* XXX this function call can become a performance bottleneck */
|
||||
path= RNA_path_from_ID_to_property(ptr, prop);
|
||||
|
||||
if(path) {
|
||||
if (path) {
|
||||
/* animation takes priority over drivers */
|
||||
if(adt->action && adt->action->curves.first)
|
||||
if (adt->action && adt->action->curves.first)
|
||||
fcu= list_find_fcurve(&adt->action->curves, path, rnaindex);
|
||||
|
||||
/* if not animated, check if driven */
|
||||
if(!fcu && (adt->drivers.first)) {
|
||||
if (!fcu && (adt->drivers.first)) {
|
||||
fcu= list_find_fcurve(&adt->drivers, path, rnaindex);
|
||||
|
||||
if(fcu)
|
||||
if (fcu)
|
||||
*driven= 1;
|
||||
}
|
||||
|
||||
if(fcu && action)
|
||||
if (fcu && action)
|
||||
*action= adt->action;
|
||||
|
||||
MEM_freeN(path);
|
||||
@ -339,6 +339,8 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction
|
||||
return fcu;
|
||||
}
|
||||
|
||||
/* ----------------- Finding Keyframes/Extents -------------------------- */
|
||||
|
||||
/* threshold for binary-searching keyframes - threshold here should be good enough for now, but should become userpref */
|
||||
#define BEZT_BINARYSEARCH_THRESH 0.01f /* was 0.00001, but giving errors */
|
||||
|
||||
@ -520,6 +522,87 @@ void calc_fcurve_range (FCurve *fcu, float *start, float *end)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------- Status Checks -------------------------- */
|
||||
|
||||
/* Are keyframes on F-Curve of any use?
|
||||
* Usability of keyframes refers to whether they should be displayed,
|
||||
* and also whether they will have any influence on the final result.
|
||||
*/
|
||||
short fcurve_are_keyframes_usable (FCurve *fcu)
|
||||
{
|
||||
/* F-Curve must exist */
|
||||
if (fcu == NULL)
|
||||
return 0;
|
||||
|
||||
/* F-Curve must not have samples - samples are mutually exclusive of keyframes */
|
||||
if (fcu->fpt)
|
||||
return 0;
|
||||
|
||||
/* if it has modifiers, none of these should "drastically" alter the curve */
|
||||
if (fcu->modifiers.first) {
|
||||
FModifier *fcm;
|
||||
|
||||
/* check modifiers from last to first, as last will be more influential */
|
||||
// TODO: optionally, only check modifier if it is the active one...
|
||||
for (fcm = fcu->modifiers.last; fcm; fcm = fcm->prev) {
|
||||
/* ignore if muted/disabled */
|
||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
|
||||
continue;
|
||||
|
||||
/* type checks */
|
||||
switch (fcm->type) {
|
||||
/* clearly harmless - do nothing */
|
||||
case FMODIFIER_TYPE_CYCLES:
|
||||
case FMODIFIER_TYPE_STEPPED:
|
||||
case FMODIFIER_TYPE_NOISE:
|
||||
break;
|
||||
|
||||
/* sometimes harmful - depending on whether they're "additive" or not */
|
||||
case FMODIFIER_TYPE_GENERATOR:
|
||||
{
|
||||
FMod_Generator *data = (FMod_Generator *)fcm->data;
|
||||
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case FMODIFIER_TYPE_FN_GENERATOR:
|
||||
{
|
||||
FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data;
|
||||
|
||||
if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* always harmful - cannot allow */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* keyframes are usable */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Can keyframes be added to F-Curve?
|
||||
* Keyframes can only be added if they are already visible
|
||||
*/
|
||||
short fcurve_is_keyframable (FCurve *fcu)
|
||||
{
|
||||
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
|
||||
if (fcurve_are_keyframes_usable(fcu) == 0)
|
||||
return 0;
|
||||
|
||||
/* F-Curve must currently be editable too */
|
||||
if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) )
|
||||
return 0;
|
||||
|
||||
/* F-Curve is keyframable */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ***************************** Keyframe Column Tools ********************************* */
|
||||
|
||||
/* add a BezTriple to a column */
|
||||
|
@ -2917,6 +2917,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
|
||||
ID *id= (ID *)id_poin;
|
||||
FCurve *fcu= (FCurve *)fcu_poin;
|
||||
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
PointerRNA id_ptr, ptr;
|
||||
PropertyRNA *prop;
|
||||
@ -2940,7 +2941,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
|
||||
flag |= INSERTKEY_REPLACE;
|
||||
|
||||
/* insert a keyframe for this F-Curve */
|
||||
done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
|
||||
done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag);
|
||||
|
||||
if (done)
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
|
||||
@ -2954,6 +2955,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
|
||||
KeyBlock *kb= (KeyBlock *)kb_poin;
|
||||
char *rna_path= key_get_curValue_rnaPath(key, kb);
|
||||
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
PointerRNA id_ptr, ptr;
|
||||
PropertyRNA *prop;
|
||||
@ -2982,7 +2984,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi
|
||||
flag |= INSERTKEY_REPLACE;
|
||||
|
||||
/* insert a keyframe for this F-Curve */
|
||||
done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
|
||||
done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag);
|
||||
|
||||
if (done)
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
|
||||
|
@ -697,25 +697,26 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
|
||||
* 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)
|
||||
short insert_keyframe_direct (ReportList *reports, 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");
|
||||
BKE_report(reports, RPT_ERROR, "No F-Curve to add keyframes to");
|
||||
return 0;
|
||||
}
|
||||
/* F-Curve not editable? */
|
||||
if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
|
||||
if (G.f & G_DEBUG)
|
||||
printf("WARNING: not inserting keyframe for locked F-Curve \n");
|
||||
if (fcurve_is_keyframable(fcu) == 0) {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"F-Curve with path = '%s' [%d] cannot be keyframed. Ensure that it is not locked or sampled. Also, try removing F-Modifiers.",
|
||||
fcu->rna_path, fcu->array_index);
|
||||
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");
|
||||
BKE_report(reports, RPT_ERROR, "No RNA-pointer available to retrieve values for keyframing from");
|
||||
return 0;
|
||||
}
|
||||
if (prop == NULL) {
|
||||
@ -726,7 +727,9 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl
|
||||
/* 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);
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
|
||||
idname, fcu->rna_path);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
@ -815,7 +818,7 @@ short insert_keyframe_direct (PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, fl
|
||||
*
|
||||
* index of -1 keys all array indices
|
||||
*/
|
||||
short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
|
||||
short insert_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag)
|
||||
{
|
||||
PointerRNA id_ptr, ptr;
|
||||
PropertyRNA *prop = NULL;
|
||||
@ -825,13 +828,14 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
|
||||
/* validate pointer first - exit if failure */
|
||||
if (id == NULL) {
|
||||
printf("Insert Key: no ID-block to insert keyframe in (Path = %s) \n", rna_path);
|
||||
BKE_reportf(reports, RPT_ERROR, "No ID-block to insert keyframe in (Path = %s)", rna_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
|
||||
printf("Insert Key: Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n",
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
|
||||
(id)? id->name : "<Missing ID-Block>", rna_path);
|
||||
return 0;
|
||||
}
|
||||
@ -844,7 +848,9 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
act= verify_adt_action(id, 1);
|
||||
|
||||
if (act == NULL) {
|
||||
printf("Insert Key: Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)\n", id->name, rna_path);
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)",
|
||||
id->name, rna_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -900,7 +906,7 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
}
|
||||
|
||||
/* insert keyframe */
|
||||
ret += insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
|
||||
ret += insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -917,7 +923,7 @@ short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
* The flag argument is used for special settings that alter the behaviour of
|
||||
* the keyframe deletion. These include the quick refresh options.
|
||||
*/
|
||||
short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
|
||||
short delete_keyframe (ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag))
|
||||
{
|
||||
AnimData *adt= BKE_animdata_from_id(id);
|
||||
PointerRNA id_ptr, ptr;
|
||||
@ -927,14 +933,14 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
|
||||
/* sanity checks */
|
||||
if ELEM(NULL, id, adt) {
|
||||
printf("ERROR: no ID-block and/or AnimData to delete keyframe from \n");
|
||||
BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* validate pointer first - exit if failure */
|
||||
RNA_id_pointer_create(id, &id_ptr);
|
||||
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
|
||||
printf("Delete Key: Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
|
||||
BKE_reportf(reports, RPT_ERROR, "Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -953,7 +959,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
cfra= BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
|
||||
}
|
||||
else {
|
||||
printf("ERROR: no Action to delete keyframes from for ID = %s \n", id->name);
|
||||
BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s \n", id->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -997,7 +1003,7 @@ short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_
|
||||
|
||||
if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) {
|
||||
if (G.f & G_DEBUG)
|
||||
printf("WARNING: not inserting keyframe for locked F-Curve \n");
|
||||
printf("WARNING: not deleting keyframe for locked F-Curve \n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1308,7 +1314,7 @@ static int delete_key_v3d_exec (bContext *C, wmOperator *op)
|
||||
|
||||
for (fcu= act->curves.first; fcu; fcu= fcn) {
|
||||
fcn= fcu->next;
|
||||
success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
|
||||
success+= delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1378,7 +1384,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
|
||||
length= 1;
|
||||
|
||||
for (a=0; a<length; a++)
|
||||
success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, flag);
|
||||
success+= insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, flag);
|
||||
|
||||
MEM_freeN(path);
|
||||
}
|
||||
@ -1387,7 +1393,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
|
||||
NlaStrip *strip= (NlaStrip *)ptr.data;
|
||||
FCurve *fcu= list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag);
|
||||
|
||||
success+= insert_keyframe_direct(ptr, prop, fcu, cfra, 0);
|
||||
success+= insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0);
|
||||
}
|
||||
else {
|
||||
if (G.f & G_DEBUG)
|
||||
@ -1456,14 +1462,14 @@ static int delete_key_button_exec (bContext *C, wmOperator *op)
|
||||
if (all) {
|
||||
length= RNA_property_array_length(&ptr, prop);
|
||||
|
||||
if(length) index= 0;
|
||||
if (length) index= 0;
|
||||
else length= 1;
|
||||
}
|
||||
else
|
||||
length= 1;
|
||||
|
||||
for (a=0; a<length; a++)
|
||||
success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
|
||||
success+= delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index+a, cfra, 0);
|
||||
|
||||
MEM_freeN(path);
|
||||
}
|
||||
|
@ -818,6 +818,7 @@ void ANIM_relative_keyingset_add_source (ListBase *dsources, ID *id, StructRNA *
|
||||
int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
|
||||
{
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
KS_Path *ksp;
|
||||
int kflag=0, success= 0;
|
||||
char *groupname= NULL;
|
||||
@ -913,9 +914,9 @@ int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingS
|
||||
for (; i < arraylen; i++) {
|
||||
/* action to take depends on mode */
|
||||
if (mode == MODIFYKEY_MODE_INSERT)
|
||||
success += insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
|
||||
success += insert_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
|
||||
else if (mode == MODIFYKEY_MODE_DELETE)
|
||||
success += delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
|
||||
success += delete_keyframe(reports, ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag2);
|
||||
}
|
||||
|
||||
/* set recalc-flags */
|
||||
|
@ -35,6 +35,7 @@ struct AnimData;
|
||||
|
||||
struct bContext;
|
||||
struct wmKeyConfig;
|
||||
struct ReportList;
|
||||
struct ScrArea;
|
||||
struct ARegion;
|
||||
struct View2D;
|
||||
@ -73,7 +74,8 @@ typedef struct bAnimContext {
|
||||
struct Scene *scene; /* active scene */
|
||||
struct Object *obact; /* active object */
|
||||
ListBase *markers; /* active set of markers */
|
||||
ListBase *reports; /* pointer to current reports list */ // XXX not yet used
|
||||
|
||||
struct ReportList *reports; /* pointer to current reports list */
|
||||
} bAnimContext;
|
||||
|
||||
/* Main Data container types */
|
||||
|
@ -47,6 +47,7 @@ struct bConstraint;
|
||||
|
||||
struct bContext;
|
||||
struct wmOperatorType;
|
||||
struct ReportList;
|
||||
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
@ -93,7 +94,7 @@ int insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag);
|
||||
* 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);
|
||||
short insert_keyframe_direct(struct ReportList *reports, struct PointerRNA ptr, struct PropertyRNA *prop, struct FCurve *fcu, float cfra, short flag);
|
||||
|
||||
/* -------- */
|
||||
|
||||
@ -101,12 +102,12 @@ short insert_keyframe_direct(struct PointerRNA ptr, struct PropertyRNA *prop, st
|
||||
* 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.
|
||||
*/
|
||||
short insert_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
|
||||
short insert_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
|
||||
|
||||
/* Main Keyframing API call:
|
||||
* Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case.
|
||||
*/
|
||||
short delete_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
|
||||
short delete_keyframe(struct ReportList *reports, struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag);
|
||||
|
||||
/* ************ Keying Sets ********************** */
|
||||
|
||||
|
@ -105,10 +105,11 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
|
||||
|
||||
// TODO: this should probably respect the keyingset only option for anim
|
||||
if(autokeyframe_cfra_can_key(scene, id)) {
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
short flag = ANIM_get_keyframing_flags(scene, 1);
|
||||
|
||||
fcu->flag &= ~FCURVE_SELECTED;
|
||||
insert_keyframe(id, action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
insert_keyframe(reports, id, action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -34,11 +34,15 @@
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math_color.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_text.h" /* for UI_OT_reports_to_text */
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
@ -403,6 +407,50 @@ void UI_OT_copy_to_selected_button(wmOperatorType *ot)
|
||||
RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
|
||||
}
|
||||
|
||||
/* Reports to Textblock Operator ------------------------ */
|
||||
|
||||
/* FIXME: this is just a temporary operator so that we can see all the reports somewhere
|
||||
* when there are too many to display...
|
||||
*/
|
||||
|
||||
static int reports_to_text_poll(bContext *C)
|
||||
{
|
||||
return CTX_wm_reports(C) != NULL;
|
||||
}
|
||||
|
||||
static int reports_to_text_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
Text *txt;
|
||||
char *str;
|
||||
|
||||
/* create new text-block to write to */
|
||||
txt = add_empty_text("Recent Reports");
|
||||
|
||||
/* convert entire list to a display string, and add this to the text-block
|
||||
* - if commandline debug option enabled, show debug reports too
|
||||
* - otherwise, up to info (which is what users normally see)
|
||||
*/
|
||||
str = BKE_reports_string(reports, (G.f & G_DEBUG)? RPT_DEBUG : RPT_INFO);
|
||||
|
||||
write_text(txt, str);
|
||||
MEM_freeN(str);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void UI_OT_reports_to_textblock(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name= "Reports to Text Block";
|
||||
ot->idname= "UI_OT_reports_to_textblock";
|
||||
ot->description= "Write the reports ";
|
||||
|
||||
/* callbacks */
|
||||
ot->poll= reports_to_text_poll;
|
||||
ot->exec= reports_to_text_exec;
|
||||
}
|
||||
|
||||
/* ********************************************************* */
|
||||
/* Registration */
|
||||
|
||||
@ -413,5 +461,6 @@ void UI_buttons_operatortypes(void)
|
||||
WM_operatortype_append(UI_OT_copy_data_path_button);
|
||||
WM_operatortype_append(UI_OT_reset_default_button);
|
||||
WM_operatortype_append(UI_OT_copy_to_selected_button);
|
||||
WM_operatortype_append(UI_OT_reports_to_textblock); // XXX: temp?
|
||||
}
|
||||
|
||||
|
@ -2331,6 +2331,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
||||
uiBut *but;
|
||||
uiStyle *style= U.uistyles.first;
|
||||
int width;
|
||||
int icon=0;
|
||||
|
||||
/* if the report display has timed out, don't show */
|
||||
if (!reports->reporttimer) return;
|
||||
@ -2364,13 +2365,20 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
|
||||
|
||||
/* icon and report message on top */
|
||||
if(report->type & RPT_ERROR_ALL)
|
||||
uiDefIconBut(block, LABEL, 0, ICON_ERROR, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
|
||||
icon = ICON_ERROR;
|
||||
else if(report->type & RPT_WARNING_ALL)
|
||||
uiDefIconBut(block, LABEL, 0, ICON_ERROR, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
|
||||
icon = ICON_ERROR;
|
||||
else if(report->type & RPT_INFO_ALL)
|
||||
uiDefIconBut(block, LABEL, 0, ICON_INFO, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
|
||||
icon = ICON_INFO;
|
||||
|
||||
/* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
|
||||
* to be shown instead of icon when appropriate...
|
||||
*/
|
||||
if (reports->list.first != reports->list.last)
|
||||
uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Click to see rest of reports in textblock: 'Recent Reports'");
|
||||
else
|
||||
uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
|
||||
|
||||
uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
|
||||
|
||||
}
|
||||
|
||||
|
@ -410,6 +410,7 @@ static void insert_action_keys(bAnimContext *ac, short mode)
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
ReportList *reports = ac->reports;
|
||||
Scene *scene= ac->scene;
|
||||
float cfra= (float)CFRA;
|
||||
short flag = 0;
|
||||
@ -437,7 +438,7 @@ static void insert_action_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* if there's an id */
|
||||
if (ale->id)
|
||||
insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
insert_keyframe(reports, ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
else
|
||||
insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
|
||||
}
|
||||
|
@ -899,7 +899,7 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
|
||||
* - if the option to only show controls if the F-Curve is selected is enabled, we must obey this
|
||||
*/
|
||||
if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
|
||||
if (fcurve_needs_draw_fmodifier_controls(fcu, fcm)) {
|
||||
if (fcurve_are_keyframes_usable(fcu) == 0) {
|
||||
/* only draw controls if this is the active modifier */
|
||||
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
|
||||
switch (fcm->type) {
|
||||
|
@ -406,6 +406,7 @@ static void insert_graph_keys(bAnimContext *ac, short mode)
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
ReportList *reports = ac->reports;
|
||||
Scene *scene= ac->scene;
|
||||
float cfra= (float)CFRA;
|
||||
short flag = 0;
|
||||
@ -432,7 +433,7 @@ static void insert_graph_keys(bAnimContext *ac, short mode)
|
||||
|
||||
/* if there's an id */
|
||||
if (ale->id)
|
||||
insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
insert_keyframe(reports, ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
else
|
||||
insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
|
||||
}
|
||||
@ -507,19 +508,33 @@ static int graphkeys_click_insert_exec (bContext *C, wmOperator *op)
|
||||
}
|
||||
fcu = ale->data;
|
||||
|
||||
/* get frame and value from props */
|
||||
frame= RNA_float_get(op->ptr, "frame");
|
||||
val= RNA_float_get(op->ptr, "value");
|
||||
/* when there are F-Modifiers on the curve, only allow adding
|
||||
* keyframes if these will be visible after doing so...
|
||||
*/
|
||||
if (fcurve_is_keyframable(fcu)) {
|
||||
/* get frame and value from props */
|
||||
frame= RNA_float_get(op->ptr, "frame");
|
||||
val= RNA_float_get(op->ptr, "value");
|
||||
|
||||
/* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
|
||||
adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
frame= BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
|
||||
/* apply inverse NLA-mapping to frame to get correct time in un-scaled action */
|
||||
adt= ANIM_nla_mapping_get(&ac, ale);
|
||||
frame= BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
|
||||
|
||||
/* apply inverse unit-mapping to value to get correct value for F-Curves */
|
||||
val *= ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, 1);
|
||||
/* apply inverse unit-mapping to value to get correct value for F-Curves */
|
||||
val *= ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, 1);
|
||||
|
||||
/* insert keyframe on the specified frame + value */
|
||||
insert_vert_fcurve(fcu, frame, val, 0);
|
||||
/* insert keyframe on the specified frame + value */
|
||||
insert_vert_fcurve(fcu, frame, val, 0);
|
||||
}
|
||||
else {
|
||||
/* warn about why this can't happen */
|
||||
if (fcu->fpt)
|
||||
BKE_report(op->reports, RPT_ERROR, "Keyframes cannot be added to sampled F-Curves");
|
||||
else if (fcu->flag & FCURVE_PROTECTED)
|
||||
BKE_report(op->reports, RPT_ERROR, "Active F-Curve is not editable");
|
||||
else
|
||||
BKE_report(op->reports, RPT_ERROR, "Remove F-Modifiers from F-Curve to add keyframes");
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
MEM_freeN(ale);
|
||||
|
@ -87,57 +87,6 @@ bAnimListElem *get_active_fcurve_channel (bAnimContext *ac)
|
||||
/* ************************************************************** */
|
||||
/* Operator Polling Callbacks */
|
||||
|
||||
/* check if any FModifiers to draw controls for - fcm is 'active' modifier
|
||||
* used for the polling callbacks + also for drawing
|
||||
*/
|
||||
// TODO: restructure these tests
|
||||
// TODO: maybe for now, just allow editing always for now...
|
||||
short fcurve_needs_draw_fmodifier_controls (FCurve *fcu, FModifier *fcm)
|
||||
{
|
||||
/* don't draw if there aren't any modifiers at all */
|
||||
if (fcu->modifiers.first == NULL)
|
||||
return 0;
|
||||
|
||||
/* if only one modifier
|
||||
* - don't draw if it is muted or disabled
|
||||
* - set it as the active one if no active one is present
|
||||
*/
|
||||
if (fcu->modifiers.first == fcu->modifiers.last) {
|
||||
fcm= fcu->modifiers.first;
|
||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if there's an active modifier - don't draw if it doesn't drastically
|
||||
* alter the curve...
|
||||
*/
|
||||
if (fcm) {
|
||||
switch (fcm->type) {
|
||||
/* clearly harmless */
|
||||
case FMODIFIER_TYPE_CYCLES:
|
||||
return 0;
|
||||
case FMODIFIER_TYPE_STEPPED:
|
||||
return 0;
|
||||
|
||||
/* borderline... */
|
||||
case FMODIFIER_TYPE_NOISE:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* if only active modifier - don't draw if it is muted or disabled */
|
||||
if (fcm) {
|
||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we're still here, this means that there are modifiers with controls to be drawn */
|
||||
// FIXME: what happens if all the modifiers were muted/disabled
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
/* Check if there are any visible keyframes (for selection tools) */
|
||||
int graphop_visible_keyframes_poll (bContext *C)
|
||||
{
|
||||
@ -167,7 +116,6 @@ int graphop_visible_keyframes_poll (bContext *C)
|
||||
|
||||
for (ale = anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
FModifier *fcm;
|
||||
|
||||
/* visible curves for selection must fulfull the following criteria:
|
||||
* - it has bezier keyframes
|
||||
@ -176,10 +124,10 @@ int graphop_visible_keyframes_poll (bContext *C)
|
||||
*/
|
||||
if (fcu->bezt == NULL)
|
||||
continue;
|
||||
fcm= find_active_fmodifier(&fcu->modifiers);
|
||||
|
||||
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
|
||||
if (found) break;
|
||||
if (fcurve_are_keyframes_usable(fcu)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup and return findings */
|
||||
@ -216,7 +164,6 @@ int graphop_editable_keyframes_poll (bContext *C)
|
||||
|
||||
for (ale = anim_data.first; ale; ale= ale->next) {
|
||||
FCurve *fcu= (FCurve *)ale->data;
|
||||
FModifier *fcm;
|
||||
|
||||
/* editable curves must fulfull the following criteria:
|
||||
* - it has bezier keyframes
|
||||
@ -226,10 +173,10 @@ int graphop_editable_keyframes_poll (bContext *C)
|
||||
*/
|
||||
if (fcu->bezt == NULL)
|
||||
continue;
|
||||
fcm= find_active_fmodifier(&fcu->modifiers);
|
||||
|
||||
found= (fcurve_needs_draw_fmodifier_controls(fcu, fcm) == 0);
|
||||
if (found) break;
|
||||
if (fcurve_is_keyframable(fcu)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup and return findings */
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_bmesh.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
@ -4546,6 +4547,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
|
||||
|
||||
// TODO: this should probably be done per channel instead...
|
||||
if (autokeyframe_cfra_can_key(scene, id)) {
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
|
||||
ListBase dsources = {NULL, NULL};
|
||||
float cfra= (float)CFRA; // xxx this will do for now
|
||||
@ -4570,7 +4572,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
|
||||
if (adt && adt->action) {
|
||||
for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) {
|
||||
fcu->flag &= ~FCURVE_SELECTED;
|
||||
insert_keyframe(id, adt->action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
insert_keyframe(reports, id, adt->action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4645,6 +4647,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
|
||||
|
||||
// TODO: this should probably be done per channel instead...
|
||||
if (autokeyframe_cfra_can_key(scene, id)) {
|
||||
ReportList *reports = CTX_wm_reports(C);
|
||||
KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene);
|
||||
float cfra= (float)CFRA;
|
||||
short flag= 0;
|
||||
@ -4686,7 +4689,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o
|
||||
* NOTE: this will do constraints too, but those are ok to do here too?
|
||||
*/
|
||||
if (pchanName && strcmp(pchanName, pchan->name) == 0)
|
||||
insert_keyframe(id, act, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
insert_keyframe(reports, id, act, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
|
||||
|
||||
if (pchanName) MEM_freeN(pchanName);
|
||||
}
|
||||
|
@ -2122,7 +2122,7 @@ static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *arg
|
||||
if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1)
|
||||
return NULL;
|
||||
|
||||
result= PyBool_FromLong(insert_keyframe((ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0));
|
||||
result= PyBool_FromLong(insert_keyframe(/*ReportList*/NULL, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0));
|
||||
MEM_freeN(path_full);
|
||||
|
||||
return result;
|
||||
@ -2156,7 +2156,7 @@ static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *arg
|
||||
if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1)
|
||||
return NULL;
|
||||
|
||||
result= PyBool_FromLong(delete_keyframe((ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0));
|
||||
result= PyBool_FromLong(delete_keyframe(/*ReportList*/NULL, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0));
|
||||
MEM_freeN(path_full);
|
||||
|
||||
return result;
|
||||
|
Loading…
Reference in New Issue
Block a user