Assorted animsys fixes/tweaks:

* Fixed all the dangerous code added in 27907. Using the code there, scripters could corrupt animation files in ways which would render them useless, with channels not appearing in any animation editors, and others not getting evaluated at all. 

* Partial fix of bug 21818, by disabling destructive replacement of keyframes. Will followup this commit with a more comprehensive commit which gets rid of the rest of the problems, by incorporating some requests from Durian team.

* Fixed problems with users being able to see+edit the name of the active Keying Set in the Scene buttons. There is still a bug though with the list widget given how the indices are now interpreted...
This commit is contained in:
Joshua Leung 2010-04-01 06:26:41 +00:00
parent ceebd182ed
commit c46a955ee0
10 changed files with 186 additions and 66 deletions

@ -81,7 +81,7 @@ def get_transform_generators_base_info(data):
path = ""
# data on ID-blocks directly should get grouped by the KeyingSet
grouping = None;
grouping = None
else:
# get the path to the ID-block
path = data.path_to_id()

@ -89,6 +89,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel):
row = layout.row()
col = row.column()
# XXX: this fails because index is not what this expects...
col.template_list(scene, "keying_sets", scene, "active_keying_set_index", rows=2)
col = row.column(align=True)
@ -96,7 +97,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel):
col.operator("anim.keying_set_remove", icon='ZOOMOUT', text="")
ks = scene.active_keying_set
if ks:
if ks and ks.absolute:
row = layout.row()
col = row.column()
@ -310,8 +311,10 @@ class ANIM_OT_keying_set_export(bpy.types.Operator):
f.write("%s, '%s'" % (id_bpy_path, ksp.data_path))
# array index settings (if applicable)
if ksp.entire_array is False:
f.write(", entire_array=False, array_index=%d" % ksp.array_index)
if ksp.entire_array:
f.write(", index=-1")
else:
f.write(", index=%d" % ksp.array_index)
# grouping settings (if applicable)
# NOTE: the current default is KEYINGSET, but if this changes, change this code too

@ -105,6 +105,9 @@ struct bActionGroup *get_active_actiongroup(struct bAction *act);
/* Make the given Action Group the active one */
void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select);
/* Add a new action group with the given name to the action */
struct bActionGroup *action_groups_add_new(struct bAction *act, const char name[]);
/* Add given channel into (active) group */
void action_groups_add_channel(struct bAction *act, struct bActionGroup *agrp, struct FCurve *fcurve);

@ -77,6 +77,8 @@ void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
short BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
short BKE_nlatrack_get_bounds(struct NlaTrack *nlt, float bounds[2]);
/* ............ */
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);

@ -238,6 +238,30 @@ void set_active_action_group (bAction *act, bActionGroup *agrp, short select)
}
}
/* Add a new action group with the given name to the action */
bActionGroup *action_groups_add_new (bAction *act, const char name[])
{
bActionGroup *agrp;
/* sanity check: must have action and name */
if (ELEM(NULL, act, name) || (name[0] == 0))
return NULL;
/* allocate a new one */
agrp = MEM_callocN(sizeof(bActionGroup), "bActionGroup");
/* make it selected, with default name */
agrp->flag = AGRP_SELECTED;
strncpy(agrp->name, name, sizeof(agrp->name));
/* add to action, and validate */
BLI_addtail(&act->groups, agrp);
BLI_uniquename(&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
/* return the new group */
return agrp;
}
/* Add given channel into (active) group
* - assumes that channel is not linked to anything anymore
* - always adds at the end of the group

@ -39,10 +39,12 @@
#include "BLI_ghash.h"
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_utildefines.h"
@ -956,6 +958,35 @@ short BKE_nlatrack_add_strip (NlaTrack *nlt, NlaStrip *strip)
return BKE_nlastrips_add_strip(&nlt->strips, strip);
}
/* Get the extents of the given NLA-Track including gaps between strips,
* returning whether this succeeded or not
*/
short BKE_nlatrack_get_bounds (NlaTrack *nlt, float bounds[2])
{
NlaStrip *strip;
/* initialise bounds */
if (bounds)
bounds[0] = bounds[1] = 0.0f;
else
return 0;
/* sanity checks */
if ELEM(NULL, nlt, nlt->strips.first)
return 0;
/* lower bound is first strip's start frame */
strip = nlt->strips.first;
bounds[0] = strip->start;
/* upper bound is last strip's end frame */
strip = nlt->strips.last;
bounds[1] = strip->end;
/* done */
return 1;
}
/* NLA Strips -------------------------------------- */
/* Find the active NLA-strip within the given track */
@ -1474,7 +1505,10 @@ short BKE_nla_tweakmode_enter (AnimData *adt)
}
}
if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
printf("NLA tweakmode enter - neither active requirement found \n");
if (G.f & G_DEBUG) {
printf("NLA tweakmode enter - neither active requirement found \n");
printf("\tactiveTrack = %p, activeStrip = %p \n", activeTrack, activeStrip);
}
return 0;
}
@ -1553,4 +1587,29 @@ void BKE_nla_tweakmode_exit (AnimData *adt)
adt->flag &= ~ADT_NLA_EDIT_ON;
}
/* Baking Tools ------------------------------------------- */
void BKE_nla_bake (Scene *scene, ID *id, AnimData *adt, int flag)
{
/* verify that data is valid
* 1) Scene and AnimData must be provided
* 2) there must be tracks to merge...
*/
if ELEM3(NULL, scene, adt, adt->nla_tracks.first)
return;
/* if animdata currently has an action, 'push down' this onto the stack first */
if (adt->action)
BKE_nla_action_pushdown(adt);
/* get range of motion to bake, and the channels involved... */
/* temporarily mute the action, and start keying to it */
/* start keying... */
/* unmute the action */
}
/* *************************************************** */

@ -176,16 +176,8 @@ FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[],
grp= action_groups_find_named(act, group);
/* no matching groups, so add one */
if (grp == NULL) {
/* Add a new group, and make it active */
grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
grp->flag = AGRP_SELECTED;
strncpy(grp->name, group, sizeof(grp->name));
BLI_addtail(&act->groups, grp);
BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name));
}
if (grp == NULL)
grp= action_groups_add_new(act, group);
/* add F-Curve to group */
action_groups_add_channel(act, grp, fcu);
@ -226,7 +218,8 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag)
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert)) {
/* take care with the handletypes and other info if the replacement flags are set */
if (flag & INSERTKEY_REPLACE) {
// NOTE: for now, always do non-destructive replace... if everybody likes this, just keep it as default
if (1/*flag & INSERTKEY_REPLACE*/) {
BezTriple *dst= (fcu->bezt + i);
float dy= bezt->vec[1][1] - dst->vec[1][1];

@ -903,6 +903,7 @@ static int nlaedit_bake_exec (bContext *C, wmOperator *op)
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
int flag = 0;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@ -914,16 +915,7 @@ static int nlaedit_bake_exec (bContext *C, wmOperator *op)
/* for each AnimData block, bake strips to animdata... */
for (ale= anim_data.first; ale; ale= ale->next) {
AnimData *adt = (AnimData *)ale->data;
/* if animdata currently has an action, 'push down' this onto the stack first */
BKE_nla_action_pushdown(adt);
/* temporarily mute the action, and start keying to it */
/* start keying... */
/* unmute the action */
//BKE_nla_bake(ac.scene, ale->id, ale->data, flag);
}
/* free temp data */

@ -34,6 +34,8 @@
#include "MEM_guardedalloc.h"
#include "BKE_action.h"
#include "WM_types.h"
@ -54,32 +56,34 @@ static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter)
iter->valid= (internal->link != NULL);
}
static bActionGroup *rna_Action_groups_add(bAction *act, char *name)
static bActionGroup *rna_Action_groups_add(bAction *act, char name[])
{
bActionGroup *agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
strncpy(agrp->name, name, sizeof(agrp->name));
BLI_addtail(&act->groups, agrp);
BLI_uniquename(&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
return agrp;
return action_groups_add_new(act, name);
}
static void rna_Action_groups_remove(bAction *act, ReportList *reports, bActionGroup *agrp)
{
FCurve *fcu;
if(!BLI_remlink_safe(&act->groups, agrp)) {
FCurve *fcu, *fcn;
/* try to remove the F-Curve from the action */
if (!BLI_remlink_safe(&act->groups, agrp)) {
BKE_reportf(reports, RPT_ERROR, "ActionGroup '%s' not found in action '%s'", agrp->name, act->id.name);
return;
}
for(fcu= act->curves.first; fcu; fcu= fcu->next) {
if(fcu->grp==agrp)
fcu->grp= NULL;
/* move every one one of the group's F-Curves out into the Action again */
for (fcu= agrp->channels.first; (fcu) && (fcu->grp==agrp); fcu=fcn) {
fcn= fcu->next;
/* remove from group */
action_groups_remove_channel(act, fcu);
/* tack onto the end */
BLI_addtail(&act->curves, fcu);
}
/* XXX, can these be added to drivers??? */
MEM_freeN(agrp); /* XXX, invalidate PyObject */
/* XXX, invalidates PyObject */
MEM_freeN(agrp);
}
@ -243,8 +247,11 @@ static void rna_def_action_group(BlenderRNA *brna)
* defined like a standard ListBase. Adding/removing channels from this list needs
* extreme care, otherwise the F-Curve list running through adjacent groups does
* not match up with the one stored in the Action, resulting in curves which do not
* show up in animation editors. For that reason, such operations are currently
* prohibited.
* show up in animation editors. In extreme cases, animation may also selectively
* fail to play back correctly.
*
* If such changes are required, these MUST go through the API functions for manipulating
* these F-Curve groupings. Also, note that groups only apply in actions ONLY.
*/
prop= RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "channels", NULL);

@ -321,6 +321,53 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
fcu->rna_path= NULL;
}
static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value)
{
AnimData *adt= BKE_animdata_from_id(ptr->id.data);
bAction *act= (adt) ? adt->action : NULL;
FCurve *fcu= ptr->data;
/* same ID? */
if (value.data && (ptr->id.data != value.id.data)) {
/* id's differ, cant do this, should raise an error */
return;
}
/* already belongs to group? */
if (fcu->grp == value.data) {
/* nothing to do */
return;
}
/* can only change group if we have info about the action the F-Curve is in
* (i.e. for drivers or random F-Curves, this cannot be done)
*/
if (act == NULL) {
/* can't change the grouping of F-Curve when it doesn't belong to an action */
return;
}
/* try to remove F-Curve from action (including from any existing groups)
* - if after this op it is still attached to something, then it is a driver
* not an animation curve as we thought, and we should exit
*/
action_groups_remove_channel(act, fcu);
if (fcu->next) {
/* F-Curve is not one that exists in the action, since the above op couldn't remove it from the list */
return;
}
/* add the F-Curve back to the action now in the right place */
// TODO: make the api function handle the case where there isn't any group to assign to
if (value.data) {
/* add to its group using API function, which makes sure everything goes ok */
action_groups_add_channel(act, value.data, fcu);
}
else {
/* need to add this back, but it can only go at the end of the list (or else will corrupt groups) */
BLI_addtail(&act->curves, fcu);
}
}
DriverVar *rna_Driver_new_variable(ChannelDriver *driver)
{
/* call the API function for this */
@ -488,28 +535,6 @@ static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, BezTri
delete_fcurve_key(fcu, index, !do_fast);
}
static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value)
{
FCurve *fcu= ptr->data;
if(value.data && (ptr->id.data != value.id.data)) {
return; /* id's differ, cant do this, should raise an error */
}
if(fcu->grp == value.data) {
return; /* nothing to do */
}
if(fcu->grp) {
BLI_remlink(&fcu->grp->channels, fcu);
}
fcu->grp= value.data;
if(fcu->grp) {
BLI_addtail(&fcu->grp->channels, fcu);
}
}
#else
static void rna_def_fmodifier_generator(BlenderRNA *brna)
@ -1090,6 +1115,12 @@ static void rna_def_channeldriver(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", DRIVER_FLAG_SHOWDEBUG);
RNA_def_property_ui_text(prop, "Show Debug Info", "Show intermediate values for the driver calculations to allow debugging of drivers");
/* State Info (for Debugging) */
prop= RNA_def_property(srna, "invalid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", DRIVER_FLAG_INVALID);
RNA_def_property_ui_text(prop, "Invalid", "Driver could not be evaluated in past, so should be skipped");
/* Functions */
RNA_api_drivers(srna);
}
@ -1359,6 +1390,12 @@ static void rna_def_fcurve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Visible", "F-Curve and its keyframes are shown in the Graph Editor graphs");
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_GRAPH, NULL);
/* State Info (for Debugging) */
prop= RNA_def_property(srna, "disabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FCURVE_DISABLED);
RNA_def_property_ui_text(prop, "Disabled", "F-Curve could not be evaluated in past, so should be skipped when evaluating");
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
/* Collections */
prop= RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");