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:
Diffstat (limited to 'source/blender/editors/animation/anim_channels_edit.c')
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c257
1 files changed, 230 insertions, 27 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 01ab7bd530c..0c77c2b0010 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -86,9 +86,9 @@
#include "WM_types.h"
/* ************************************************************************** */
-/* CHANNELS API */
+/* CHANNELS API - Exposed API */
-/* -------------------------- Exposed API ----------------------------------- */
+/* -------------------------- Selection ------------------------------------- */
/* Set the given animation-channel as the active one for the active context */
// TODO: extend for animdata types...
@@ -352,6 +352,137 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
BLI_freelistN(&anim_data);
}
+/* ---------------------------- Graph Editor ------------------------------------- */
+
+/* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting
+ * - anim_data: list of the all the anim channels that can be chosen
+ * -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too,
+ * then the channels under closed expanders get ignored...
+ * - ale_setting: the anim channel (not in the anim_data list directly, though occuring there)
+ * with the new state of the setting that we want flushed up/down the hierarchy
+ * - vizOn: whether the visibility setting has been enabled or disabled
+ */
+void ANIM_visibility_flush_anim_channels (bAnimContext *ac, ListBase *anim_data, bAnimListElem *ale_setting, short vizOn)
+{
+ bAnimListElem *ale, *match=NULL;
+ int prevLevel=0, matchLevel=0;
+
+ /* find the channel that got changed */
+ for (ale= anim_data->first; ale; ale= ale->next) {
+ /* compare data, and type as main way of identifying the channel */
+ if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
+ /* we also have to check the ID, this is assigned to, since a block may have multiple users */
+ // TODO: is the owner-data more revealing?
+ if (ale->id == ale_setting->id) {
+ match= ale;
+ break;
+ }
+ }
+ }
+ if (match == NULL) {
+ printf("ERROR: no channel matching the one changed was found \n");
+ return;
+ }
+ else {
+ bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale_setting);
+
+ /* get the level of the channel that was affected
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ matchLevel= (acf->get_offset)? acf->get_offset(ac, ale_setting) : 0;
+ }
+
+ /* flush up?
+ * - only flush up if the current state is now enabled
+ * (otherwise, it's too much work to force the parents to be inactive too)
+ */
+ if (vizOn) {
+ /* go backwards in the list, until the highest-ranking element (by indention has been covered) */
+ for (ale= match->prev; ale; ale= ale->prev) {
+ bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
+ int level;
+
+ /* get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ level= (acf->get_offset)? acf->get_offset(ac, ale) : 0;
+
+ /* if the level is 'less than' (i.e. more important) the level we're matching
+ * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves,
+ * when toggling visibility of F-Curves, gets flushed), flush the new status...
+ */
+ if (level < prevLevel)
+ ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
+ /* however, if the level is 'greater than' (i.e. less important than the previous channel,
+ * stop searching, since we've already reached the bottom of another hierarchy
+ */
+ else if (level > matchLevel)
+ break;
+
+ /* store this level as the 'old' level now */
+ prevLevel= level;
+ }
+ }
+
+ /* flush down (always) */
+ {
+ /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
+ for (ale= match->next; ale; ale= ale->next) {
+ bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
+ int level;
+
+ /* get the level of the current channel traversed
+ * - we define the level as simply being the offset for the start of the channel
+ */
+ level= (acf->get_offset)? acf->get_offset(ac, ale) : 0;
+
+ /* if the level is 'greater than' (i.e. less important) the channel that was changed,
+ * flush the new status...
+ */
+ if (level > matchLevel)
+ ANIM_channel_setting_set(ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
+ /* however, if the level is 'less than or equal to' the channel that was changed,
+ * (i.e. the current channel is as important if not more important than the changed channel)
+ * then we should stop, since we've found the last one of the children we should flush
+ */
+ else
+ break;
+
+ /* store this level as the 'old' level now */
+ prevLevel= level;
+ }
+ }
+}
+
+/* -------------------------- F-Curves ------------------------------------- */
+
+/* Delete the given F-Curve from its AnimData block */
+void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *fcu)
+{
+ /* - if no AnimData, we've got nowhere to remove the F-Curve from
+ * (this doesn't guarantee that the F-Curve is in there, but at least we tried
+ * - if no F-Curve, there is nothing to remove
+ */
+ if (ELEM(NULL, adt, fcu))
+ return;
+
+ /* remove from whatever list it came from
+ * - Action Group
+ * - Action
+ * - Drivers
+ * - TODO... some others?
+ */
+ if (fcu->grp)
+ action_groups_remove_channel(adt->action, fcu);
+ else if ((ac) && (ac->datatype == ANIMCONT_DRIVERS))
+ BLI_remlink(&adt->drivers, fcu);
+ else if (adt->action)
+ BLI_remlink(&adt->action->curves, fcu);
+
+ /* free the F-Curve itself */
+ free_fcurve(fcu);
+}
+
/* ************************************************************************** */
/* OPERATORS */
@@ -845,28 +976,8 @@ static int animchannels_delete_exec(bContext *C, wmOperator *op)
AnimData *adt= ale->adt;
FCurve *fcu= (FCurve *)ale->data;
- /* if no AnimData, we've got nowhere to remove the F-Curve from */
- if (adt == NULL)
- continue;
-
- /* remove from whatever list it came from
- * - Action Group
- * - Action
- * - Drivers
- * - TODO... some others?
- *
- * note: this isn't well tested, we could also try remove
- * from all lists just to be safe - campbell
- */
- if (fcu->grp)
- action_groups_remove_channel(adt->action, fcu);
- else if (ac.datatype == ANIMCONT_DRIVERS)
- BLI_remlink(&adt->drivers, fcu);
- else if (adt->action)
- BLI_remlink(&adt->action->curves, fcu);
-
- /* free the F-Curve itself */
- free_fcurve(fcu);
+ /* try to free F-Curve */
+ ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
}
}
@@ -895,12 +1006,87 @@ void ANIM_OT_channels_delete (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+/* ******************** Set Channel Visibility Operator *********************** */
+/* NOTE: this operator is only valid in the Graph Editor channels region */
+
+static int animchannels_visibility_set_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+
+ /* hide all channels not selected */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_UNSEL);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next)
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_CLEAR);
+
+ BLI_freelistN(&anim_data);
+
+
+ /* get list of all channels that selection may need to be flushed to */
+ filter= ANIMFILTER_CHANNELS;
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
+ /* make all the selected channels visible */
+ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ // TODO: find out why this is the case, and fix that
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* enable the setting */
+ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_visibility_flush_anim_channels(&ac, &all_data, ale, 1);
+ }
+
+ BLI_freelistN(&anim_data);
+ BLI_freelistN(&all_data);
+
+
+ /* send notifier that things have changed */
+ WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void ANIM_OT_channels_visibility_set (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Set Visibility";
+ ot->idname= "ANIM_OT_channels_visibility_set";
+ ot->description= "Make only the selected animation channels visible in the Graph Editor.";
+
+ /* api callbacks */
+ ot->exec= animchannels_visibility_set_exec;
+ ot->poll= ED_operator_ipo_active;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
/* ******************** Toggle Channel Visibility Operator *********************** */
+/* NOTE: this operator is only valid in the Graph Editor channels region */
static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
+ ListBase all_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
short vis= ACHANNEL_SETFLAG_ADD;
@@ -909,6 +1095,10 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
+ /* get list of all channels that selection may need to be flushed to */
+ filter= ANIMFILTER_CHANNELS;
+ ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
+
/* filter data */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
@@ -922,14 +1112,24 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE))
vis= ACHANNEL_SETFLAG_CLEAR;
}
-
+
/* Now set the flags */
for (ale= anim_data.first; ale; ale= ale->next) {
+ /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */
+ // TODO: find out why this is the case, and fix that
+ if (ale->type == ANIMTYPE_OBJECT)
+ continue;
+
+ /* change the setting */
ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
+
+ /* now, also flush selection status up/down as appropriate */
+ ANIM_visibility_flush_anim_channels(&ac, &all_data, ale, (vis == ACHANNEL_SETFLAG_ADD));
}
/* cleanup */
BLI_freelistN(&anim_data);
+ BLI_freelistN(&all_data);
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
@@ -1696,11 +1896,12 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_collapse);
WM_operatortype_append(ANIM_OT_channels_visibility_toggle);
+ WM_operatortype_append(ANIM_OT_channels_visibility_set);
}
void ED_keymap_animchannels(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation_Channels", 0, 0);
+ wmKeyMap *keymap = WM_keymap_find(keyconf, "Animation Channels", 0, 0);
/* selection */
/* click-select */
@@ -1715,6 +1916,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
/* borderselect */
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", BKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
/* delete */
WM_keymap_add_item(keymap, "ANIM_OT_channels_delete", XKEY, KM_PRESS, 0, 0);
@@ -1742,7 +1944,8 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
//WM_keymap_add_item(keymap, "ANIM_OT_channels_move_to_bottom", PAGEDOWNKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
/* Graph Editor only */
- WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_set", VKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_visibility_toggle", VKEY, KM_PRESS, KM_SHIFT, 0);
}
/* ************************************************************************** */