2.5 - Assorted Animation UI/Editing Tweaks

Main Feature:
* It is now possible to choose which AnimData block is the 'active' one for editing, and/or select them too. AnimData blocks are generally the dark blue and lighter-blue expanders (i.e. Scene, Object, Camera, Lamp, Curve, Armature, etc.)

* Objects are no longer selected/deselected when AKEY is used to toggle selection of channels. This was getting a bit annoying. 

* Following on from selection of AnimData blocks, it is now possible to select/make active an AnimData block in the animation editors, and change the active action for that block via the 'Animation Data' panel in NLA Editor's properties region.
--> Be aware that user-counts are not totally handled correctly there yet, so some funky behaviour might be seen...
--> It is possible to assign a new action, or to assign an existing one, allowing to switch between actions as in the past with Actions/IPO Editors...

Other tweaks:
* Some code tweaks towards making the 'Euler Filter' feature for Graph Editor working sometime soon
* Added some backend code for snapping the values of keyframes to a single value. Still need to work out some UI for it though.
* Shuffled the code for ACT_OT_new() around, and removed the poll() callback so that it worked in NLA too.
* Fixed some more notifier bugs with deleting bones and a few other editmode operations for Armatures.
This commit is contained in:
2009-09-27 04:22:04 +00:00
parent 69995bb1b3
commit fbfa8d2f81
17 changed files with 440 additions and 112 deletions

View File

@@ -244,6 +244,8 @@ void BKE_animdata_make_local(AnimData *adt)
/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */
static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath)
{
return oldpath; // FIXME!!!
}
@@ -264,7 +266,7 @@ static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *new
/* driver targets */
for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
dtat->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, dtar->rna_path);
dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path);
}
}
}

View File

@@ -762,7 +762,7 @@ static int acf_fillactd_setting_flag(int setting, short *neg)
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return ACT_SELECTED;
return ADT_UI_SELECTED;
case ACHANNEL_SETTING_EXPAND: /* expanded */
*neg= 1;
@@ -777,13 +777,18 @@ static int acf_fillactd_setting_flag(int setting, short *neg)
static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type)
{
bAction *act= (bAction *)ale->data;
AnimData *adt= ale->adt;
/* clear extra return data first */
*type= 0;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
GET_ACF_FLAG_PTR(act->flag);
if (adt) {
GET_ACF_FLAG_PTR(adt->flag);
}
else
return 0;
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(act->flag);
@@ -1001,6 +1006,9 @@ static int acf_dsmat_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1019,6 +1027,7 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(ma->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (ma->adt)
@@ -1070,6 +1079,9 @@ static int acf_dslam_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1088,6 +1100,7 @@ static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(la->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (la->adt)
@@ -1139,6 +1152,9 @@ static int acf_dscam_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1157,6 +1173,7 @@ static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(ca->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (ca->adt)
@@ -1208,6 +1225,9 @@ static int acf_dscur_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1226,6 +1246,7 @@ static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(cu->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (cu->adt)
@@ -1277,6 +1298,9 @@ static int acf_dsskey_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1295,6 +1319,7 @@ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(key->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (key->adt)
@@ -1346,6 +1371,9 @@ static int acf_dswor_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1364,6 +1392,7 @@ static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(wo->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (wo->adt)
@@ -1415,6 +1444,9 @@ static int acf_dspart_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1433,6 +1465,7 @@ static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(part->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (part->adt)
@@ -1485,6 +1518,9 @@ static int acf_dsmball_setting_flag(int setting, short *neg)
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
}
@@ -1502,6 +1538,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(mb->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (mb->adt)
@@ -1553,6 +1590,9 @@ static int acf_dsarm_setting_flag(int setting, short *neg)
case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
*neg= 1;
return ADT_CURVES_NOT_VISIBLE;
case ACHANNEL_SETTING_SELECT: /* selected */
return ADT_UI_SELECTED;
default: /* unsupported */
return 0;
@@ -1571,6 +1611,7 @@ static void *acf_dsarm_setting_ptr(bAnimListElem *ale, int setting, short *type)
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(arm->flag);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (arm->adt)

View File

@@ -91,6 +91,7 @@
/* -------------------------- Exposed API ----------------------------------- */
/* Set the given animation-channel as the active one for the active context */
// TODO: extend for animdata types...
void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int filter, void *channel_data, short channel_type)
{
ListBase anim_data = {NULL, NULL};
@@ -130,11 +131,29 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
}
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
}
}
break;
}
}
/* set active flag */
if (channel_data != NULL) {
if (channel_data) {
switch (channel_type) {
case ANIMTYPE_GROUP:
{
@@ -154,6 +173,23 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
nlt->flag |= NLATRACK_ACTIVE;
}
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* need to verify that this data is valid for now */
if (ale->adt)
ale->adt->flag |= ADT_UI_ACTIVE;
}
break;
}
}
@@ -174,7 +210,7 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
int filter;
/* filter data */
filter= ANIMFILTER_VISIBLE;
filter= ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS;
ANIM_animdata_filter(NULL, &anim_data, filter, data, datatype);
/* See if we should be selecting or deselecting */
@@ -189,12 +225,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
sel= ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_OBJECT:
#if 0 /* for now, do not take object selection into account, since it gets too annoying */
if (ale->flag & SELECT)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_FILLACTD:
if (ale->flag & ACT_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
#endif
break;
case ANIMTYPE_GROUP:
if (ale->flag & AGRP_SELECTED)
@@ -208,6 +242,22 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
if (ale->flag & NLATRACK_SELECTED)
sel= ACHANNEL_SETFLAG_CLEAR;
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
sel= ACHANNEL_SETFLAG_CLEAR;
}
break;
}
}
}
@@ -220,23 +270,26 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
Scene *scene= (Scene *)ale->data;
ACHANNEL_SET_FLAG(scene, sel, SCE_DS_SELECTED);
if (scene->adt) {
ACHANNEL_SET_FLAG(scene, sel, ADT_UI_SELECTED);
}
}
break;
case ANIMTYPE_OBJECT:
#if 0 /* for now, do not take object selection into account, since it gets too annoying */
{
Base *base= (Base *)ale->data;
Object *ob= base->object;
ACHANNEL_SET_FLAG(base, sel, SELECT);
ACHANNEL_SET_FLAG(ob, sel, SELECT);
}
break;
case ANIMTYPE_FILLACTD:
{
bAction *act= (bAction *)ale->data;
ACHANNEL_SET_FLAG(act, sel, ACT_SELECTED);
if (ob->adt) {
ACHANNEL_SET_FLAG(ob, sel, ADT_UI_SELECTED);
}
}
#endif
break;
case ANIMTYPE_GROUP:
{
@@ -262,6 +315,25 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
nlt->flag &= ~NLATRACK_ACTIVE;
}
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
ale->adt->flag &= ~ADT_UI_ACTIVE;
}
}
break;
}
}
@@ -1310,18 +1382,22 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
}
/* action to take depends on what channel we've got */
// WARNING: must keep this in sync with the equivalent function in nla_channels.c
switch (ale->type) {
case ANIMTYPE_SCENE:
{
Scene *sce= (Scene *)ale->data;
AnimData *adt= sce->adt;
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
sce->flag ^= SCE_DS_SELECTED;
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
sce->flag |= SCE_DS_SELECTED;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
notifierFlags |= ND_ANIMCHAN_SELECT;
@@ -1333,34 +1409,75 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
Scene *sce= (Scene *)ads->source;
Base *base= (Base *)ale->data;
Object *ob= base->object;
AnimData *adt= ob->adt;
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
base->flag ^= SELECT;
ob->flag= base->flag;
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
Base *b;
/* deleselect all */
/* deselect all */
// TODO: should this deselect all other types of channels too?
for (b= sce->base.first; b; b= b->next) {
b->flag &= ~SELECT;
b->object->flag= b->flag;
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED|ADT_UI_ACTIVE);
}
/* select object now */
base->flag |= SELECT;
ob->flag |= SELECT;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
/* xxx should be ED_base_object_activate(), but we need context pointer for that... */
//set_active_base(base);
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
notifierFlags |= ND_ANIMCHAN_SELECT;
}
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this AnimData block only */
ale->adt->flag ^= ADT_UI_SELECTED;
}
else {
/* select AnimData block by itself */
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
ale->adt->flag |= ADT_UI_SELECTED;
}
/* set active? */
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
ale->adt->flag |= ADT_UI_ACTIVE;
}
notifierFlags |= ND_ANIMCHAN_SELECT;
}
break;
case ANIMTYPE_GROUP:
{
bActionGroup *agrp= (bActionGroup *)ale->data;

View File

@@ -413,7 +413,9 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
}\
}
/* quick macro to test if an anim-channel representing an AnimData block is suitably active */
#define ANIMCHANNEL_ACTIVEOK(ale) \
( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
/* quick macro to test if an anim-channel (F-Curve, Group, etc.) is selected in an acceptable way */
#define ANIMCHANNEL_SELOK(test_func) \
@@ -980,10 +982,13 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
/* include material-expand widget? */
// hmm... do we need to store the index of this material in the array anywhere?
if (filter_mode & ANIMFILTER_CHANNELS) {
ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ma) {
ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -1037,11 +1042,14 @@ static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet
/* add particle settings? */
if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
if ((filter_mode & ANIMFILTER_CHANNELS)){
ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
if ((filter_mode & ANIMFILTER_CHANNELS)) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(psys->part) {
ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -1117,9 +1125,12 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
expanded= EXPANDED_DRVD(adt);
/* include data-expand widget? */
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
if (ale) BLI_addtail(anim_data, ale);
if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(iat) {
ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
if (ale) BLI_addtail(anim_data, ale);
}
}
/* add object-data animation channels? */
@@ -1149,10 +1160,13 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
/* check if filtering by selection */
if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, NULL);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ob) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
@@ -1233,10 +1247,13 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
{ /* action (keyframes) */
/* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(key) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}

View File

@@ -461,6 +461,13 @@ static short snap_bezier_horizontal(BeztEditData *bed, BezTriple *bezt)
return 0;
}
static short snap_bezier_value(BeztEditData *bed, BezTriple *bezt)
{
/* value to snap to is stored in the custom data -> first float value slot */
if (bezt->f2 & SELECT)
bezt->vec[1][1]= bed->f1;
return 0;
}
BeztEditFunc ANIM_editkeyframes_snap(short type)
{
@@ -476,6 +483,8 @@ BeztEditFunc ANIM_editkeyframes_snap(short type)
return snap_bezier_nearestsec;
case SNAP_KEYS_HORIZONTAL: /* snap handles to same value */
return snap_bezier_horizontal;
case SNAP_KEYS_VALUE: /* snap to given value */
return snap_bezier_value;
default: /* just in case */
return snap_bezier_nearest;
}

View File

@@ -1736,7 +1736,7 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
ED_armature_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT, obedit);
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, obedit);
return OPERATOR_FINISHED;
}
@@ -3938,7 +3938,7 @@ static int armature_parent_clear_exec(bContext *C, wmOperator *op)
ED_armature_sync_selection(arm->edbo);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT, ob);
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
return OPERATOR_FINISHED;
}

View File

@@ -73,6 +73,7 @@ typedef enum eEditKeyframes_Snap {
SNAP_KEYS_NEARSEC,
SNAP_KEYS_NEARMARKER,
SNAP_KEYS_HORIZONTAL,
SNAP_KEYS_VALUE,
} eEditKeyframes_Snap;
/* mirroring tools */

View File

@@ -88,6 +88,44 @@
#include "action_intern.h"
/* ************************************************************************** */
/* ACTION MANAGEMENT */
/* ******************** New Action Operator *********************** */
static int act_new_exec(bContext *C, wmOperator *op)
{
bAction *action;
// XXX need to restore behaviour to copy old actions...
action= add_empty_action("Action");
/* combined with RNA property, this will assign & increase user,
so decrease here to compensate for that */
action->id.us--;
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
return OPERATOR_FINISHED;
}
void ACT_OT_new (wmOperatorType *ot)
{
/* identifiers */
ot->name= "New";
ot->idname= "ACT_OT_new";
ot->description= "Create new action.";
/* api callbacks */
ot->exec= act_new_exec;
// NOTE: this is used in the NLA too...
//ot->poll= ED_operator_action_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* ************************************************************************** */
/* KEYFRAME-RANGE STUFF */
@@ -1331,38 +1369,4 @@ void ACT_OT_mirror (wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
}
/* ******************** New Action Operator *********************** */
static int act_new_exec(bContext *C, wmOperator *op)
{
bAction *action;
// XXX need to restore behaviour to copy old actions...
action= add_empty_action("Action");
/* combined with RNA property, this will assign & increase user,
so decrease here to compensate for that */
action->id.us--;
/* set notifier that keyframes have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
return OPERATOR_FINISHED;
}
void ACT_OT_new (wmOperatorType *ot)
{
/* identifiers */
ot->name= "New";
ot->idname= "ACT_OT_new";
ot->description= "Create new action.";
/* api callbacks */
ot->exec= act_new_exec;
ot->poll= ED_operator_action_active;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* ************************************************************************** */

View File

@@ -858,9 +858,6 @@ 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)) {
/* enable blending to allow fading of curves */
glEnable(GL_BLEND);
if (fcurve_needs_draw_fmodifier_controls(fcu, fcm)) {
/* only draw controls if this is the active modifier */
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
@@ -874,7 +871,10 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) {
if (fcu->bezt) {
/* only draw handles/vertices on keyframes */
draw_fcurve_handles(sipo, ar, fcu);
glEnable(GL_BLEND);
draw_fcurve_handles(sipo, ar, fcu);
glDisable(GL_BLEND);
draw_fcurve_vertices(sipo, ar, fcu);
}
else {
@@ -882,9 +882,6 @@ void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGri
draw_fcurve_samples(sipo, ar, fcu);
}
}
/* restore settings */
glDisable(GL_BLEND);
}
/* undo mapping of keyframes for drawing if scaled F-Curve */

View File

@@ -1296,8 +1296,7 @@ void GRAPH_OT_handle_type (wmOperatorType *ot)
/* set of three euler-rotation F-Curves */
typedef struct tEulerFilter {
ID *id; /* ID-block which owns the channels */
FCurve *fcu1, *fcu2, *fcu3; /* x,y,z rotation curves */
int i1, i2, i3; /* current index for each curve */
FCurve (*fcurves)[3]; /* 3 Pointers to F-Curves */
} tEulerFilter;
static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
@@ -1347,10 +1346,26 @@ static int graphkeys_euler_filter_exec (bContext *C, wmOperator *op)
if ((euf) && (ale->id != euf->id)) {
}
else {
/* just add to a new block */
euf= MEM_callocN(sizeof(tEulerFilter), "tEulerFilter");
BLI_addtail(&eulers, euf);
euf->id= ale->id;
euf->fcurves[fcu->array_index]= fcu;
}
}
BLI_freelistN(&anim_data);
// XXX for now
return OPERATOR_CANCELLED;
/* step 2: go through each set of curves, processing the values at each keyframe
* - it is assumed that there must be a full set of keyframes at each keyframe position
*/
for (euf= eulers.first; euf; euf= euf->next) {
}
BLI_freelistN(&eulers);
return OPERATOR_FINISHED;
}
void GRAPH_OT_euler_filter (wmOperatorType *ot)
@@ -1789,7 +1804,7 @@ void GRAPH_OT_fmodifier_add (wmOperatorType *ot)
/* api callbacks */
ot->invoke= graph_fmodifier_add_invoke;
ot->exec= graph_fmodifier_add_exec;
ot->poll= graphop_active_fcurve_poll;
ot->poll= graphop_selected_fcurve_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;

View File

@@ -155,6 +155,7 @@ short fcurve_needs_draw_fmodifier_controls(struct FCurve *fcu, struct FModifier
int graphop_visible_keyframes_poll(struct bContext *C);
int graphop_editable_keyframes_poll(struct bContext *C);
int graphop_active_fcurve_poll(struct bContext *C);
int graphop_selected_fcurve_poll(struct bContext *C);
/* ***************************************** */
/* graph_ops.c */

View File

@@ -285,4 +285,34 @@ int graphop_active_fcurve_poll (bContext *C)
return has_fcurve;
}
/* has selected F-Curve that's editable */
int graphop_selected_fcurve_poll (bContext *C)
{
bAnimContext ac;
bAnimListElem *ale;
ListBase anim_data = {NULL, NULL};
ScrArea *sa= CTX_wm_area(C);
int filter, items;
short found = 0;
/* firstly, check if in Graph Editor */
// TODO: also check for region?
if ((sa == NULL) || (sa->spacetype != SPACE_IPO))
return 0;
/* try to init Anim-Context stuff ourselves and check */
if (ANIM_animdata_get_context(C, &ac) == 0)
return 0;
/* get the editable + selected F-Curves, and as long as we got some, we can return */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
if (items == 0)
return 0;
/* cleanup and return findings */
BLI_freelistN(&anim_data);
return found;
}
/* ************************************************************** */

View File

@@ -114,34 +114,69 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA
if (ANIM_animdata_get_context(C, &ac) == 0)
return 0;
/* extract list of active channel(s), of which we should only take the first one (expecting it to be an NLA track) */
filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE);
/* extract list of active channel(s), of which we should only take the first one
* - we need the channels flag to get the active AnimData block when there are no NLA Tracks
*/
filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE|ANIMFILTER_CHANNELS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale= anim_data.first; ale; ale= ale->next) {
// TODO: need some way to select active animdata too...
if (ale->type == ANIMTYPE_NLATRACK) {
NlaTrack *nlt= (NlaTrack *)ale->data;
AnimData *adt= ale->adt;
/* found it, now set the pointers */
if (adt_ptr) {
/* AnimData pointer */
RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
switch (ale->type) {
case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */
{
NlaTrack *nlt= (NlaTrack *)ale->data;
AnimData *adt= ale->adt;
/* found it, now set the pointers */
if (adt_ptr) {
/* AnimData pointer */
RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
}
if (nlt_ptr) {
/* NLA-Track pointer */
RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
}
if (strip_ptr) {
/* NLA-Strip pointer */
NlaStrip *strip= BKE_nlastrip_find_active(nlt);
RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
}
found= 1;
}
if (nlt_ptr) {
/* NLA-Track pointer */
RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
}
if (strip_ptr) {
/* NLA-Strip pointer */
NlaStrip *strip= BKE_nlastrip_find_active(nlt);
RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
}
found= 1;
break;
break;
case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
case ANIMTYPE_OBJECT:
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* for these channels, we only do AnimData */
if (ale->id && ale->adt) {
if (adt_ptr) {
/* AnimData pointer */
RNA_pointer_create(ale->id, &RNA_AnimData, ale->adt, adt_ptr);
/* set found status to -1, since setting to 1 would break the loop
* and potentially skip an active NLA-Track in some cases...
*/
found= -1;
}
}
}
break;
}
if (found > 0)
break;
}
/* free temp data */
@@ -211,7 +246,7 @@ static void nla_panel_animdata (const bContext *C, Panel *pa)
/* Active Action Properties ------------------------------------- */
/* action */
row= uiLayoutRow(layout, 1);
uiTemplateID(row, (bContext *)C, &adt_ptr, "action", NULL /*"ACT_OT_new"*/, NULL, NULL /*"ACT_OT_unlink"*/); // XXX: need to make these operators
uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACT_OT_new", NULL, NULL /*"ACT_OT_unlink"*/); // XXX: need to make these operators
/* extrapolation */
row= uiLayoutRow(layout, 1);

View File

@@ -116,18 +116,22 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho
}
/* action to take depends on what channel we've got */
// WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c
switch (ale->type) {
case ANIMTYPE_SCENE:
{
Scene *sce= (Scene *)ale->data;
AnimData *adt= sce->adt;
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
sce->flag ^= SCE_DS_SELECTED;
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
sce->flag |= SCE_DS_SELECTED;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
notifierFlags |= ND_ANIMCHAN_SELECT;
@@ -139,6 +143,7 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho
Scene *sce= (Scene *)ads->source;
Base *base= (Base *)ale->data;
Object *ob= base->object;
AnimData *adt= ob->adt;
if (nlaedit_is_tweakmode_on(ac) == 0) {
/* set selection status */
@@ -146,23 +151,30 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho
/* swap select */
base->flag ^= SELECT;
ob->flag= base->flag;
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
Base *b;
/* deleselect all */
/* deselect all */
// TODO: should this deselect all other types of channels too?
for (b= sce->base.first; b; b= b->next) {
b->flag &= ~SELECT;
b->object->flag= b->flag;
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED|ADT_UI_ACTIVE);
}
/* select object now */
base->flag |= SELECT;
ob->flag |= SELECT;
if (adt) adt->flag |= ADT_UI_SELECTED;
}
/* xxx should be ED_base_object_activate(), but we need context pointer for that... */
//set_active_base(base);
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
/* notifiers - channel was selected */
notifierFlags |= ND_ANIMCHAN_SELECT;
@@ -170,6 +182,39 @@ static int mouse_nla_channels (bAnimContext *ac, float x, int channel_index, sho
}
break;
case ANIMTYPE_FILLACTD: /* Action Expander */
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
{
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
if (selectmode == SELECT_INVERT) {
/* inverse selection status of this AnimData block only */
ale->adt->flag ^= ADT_UI_SELECTED;
}
else {
/* select AnimData block by itself */
ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
ale->adt->flag |= ADT_UI_SELECTED;
}
/* set active? */
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
ale->adt->flag |= ADT_UI_ACTIVE;
}
notifierFlags |= ND_ANIMCHAN_SELECT;
}
break;
case ANIMTYPE_NLATRACK:
{
NlaTrack *nlt= (NlaTrack *)ale->data;

View File

@@ -763,6 +763,11 @@ typedef enum eAnimData_Flag {
/* don't execute drivers */
ADT_DRIVERS_DISABLED = (1<<11),
/* AnimData block is selected in UI */
ADT_UI_SELECTED = (1<<14),
/* AnimData block is active in UI */
ADT_UI_ACTIVE = (1<<15),
/* F-Curves from this AnimData block are not visible in the Graph Editor */
ADT_CURVES_NOT_VISIBLE = (1<<16),
} eAnimData_Flag;

View File

@@ -57,6 +57,12 @@ static int rna_AnimData_action_editable(PointerRNA *ptr)
return 1;
}
static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
{
AnimData *adt= (AnimData*)(ptr->data);
adt->action= value.data;
}
static void rna_ksPath_RnaPath_get(PointerRNA *ptr, char *value)
{
KS_Path *ksp= (KS_Path *)ptr->data;
@@ -202,8 +208,11 @@ void rna_def_animdata(BlenderRNA *brna)
/* Active Action */
prop= RNA_def_property(srna, "action", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock.");
RNA_def_property_pointer_funcs(prop, NULL, "rna_AnimData_action_set", NULL);
RNA_def_property_flag(prop, PROP_EDITABLE); /* this flag as well as the dynamic test must be defined for this to be editable... */
RNA_def_property_editable_func(prop, "rna_AnimData_action_editable");
RNA_def_property_ui_text(prop, "Action", "Active Action for this datablock.");
/* Active Action Settings */
prop= RNA_def_property(srna, "action_extrapolation", PROP_ENUM, PROP_NONE);

View File

@@ -239,7 +239,7 @@ void wm_event_do_notifiers(bContext *C)
if(G.rendering==0) { // XXX make lock in future, or separated derivedmesh users in scene
/* update all objects, ipos, matrices, displists, etc. Flags set by depgraph or manual,
/* update all objects, drivers, matrices, displists, etc. Flags set by depgraph or manual,
no layer check here, gets correct flushed */
/* sets first, we allow per definition current scene to have dependencies on sets */
if(scene->set) {