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.c278
1 files changed, 256 insertions, 22 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index fe836204c27..481430f37e4 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -124,6 +124,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -169,6 +170,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, short datatype, int f
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -249,6 +251,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED))
@@ -343,6 +346,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* need to verify that this data is valid for now */
@@ -538,12 +542,26 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
BLI_remlink(&adt->drivers, fcu);
}
else if (adt->action) {
+ bAction *act = adt->action;
+
/* remove from group or action, whichever one "owns" the F-Curve */
- if (fcu->grp)
- action_groups_remove_channel(adt->action, fcu);
- else
- BLI_remlink(&adt->action->curves, fcu);
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
+
+ /* remove F-Curve from group+action */
+ action_groups_remove_channel(act, fcu);
+ /* if group has no more channels, remove it too,
+ * otherwise can have many dangling groups [#33541]
+ */
+ if (agrp->channels.first == NULL) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ else {
+ BLI_remlink(&act->curves, fcu);
+ }
+
/* if action has no more F-Curves as a result of this, unlink it from
* AnimData if it did not come from a NLA Strip being tweaked.
*
@@ -551,12 +569,8 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f
* channel list that are empty, and linger around long after the data they
* are for has disappeared (and probably won't come back).
*/
- // XXX: does everybody always want this?
- /* XXX: there's a problem where many actions could build up in the file if multiple
- * full add/delete cycles are performed on the same objects, but assume that this is rare
- */
- if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
- id_us_min(&adt->action->id);
+ if ((act->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON) == 0) {
+ id_us_min(&act->id);
adt->action = NULL;
}
}
@@ -1137,6 +1151,218 @@ static void ANIM_OT_channels_move(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
}
+/* ******************** Group Channel Operator ************************ */
+
+static int animchannels_grouping_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ SpaceLink *sl;
+
+ /* channels region test */
+ /* TODO: could enhance with actually testing if channels region? */
+ if (ELEM(NULL, sa, CTX_wm_region(C)))
+ return 0;
+
+ /* animation editor test - must be suitable modes only */
+ sl = CTX_wm_space_data(C);
+
+ switch (sa->spacetype) {
+ /* supported... */
+ case SPACE_ACTION:
+ {
+ SpaceAction *saction = (SpaceAction *)sl;
+
+ /* dopesheet and action only - all others are for other datatypes or have no groups */
+ if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_DOPESHEET) == 0)
+ return 0;
+ }
+ break;
+
+ case SPACE_IPO:
+ {
+ SpaceIpo *sipo = (SpaceIpo *)sl;
+
+ /* drivers can't have groups... */
+ if (sipo->mode != SIPO_MODE_ANIMATION)
+ return 0;
+ }
+ break;
+
+ /* unsupported... */
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ----------------------------------------------------------- */
+
+static void animchannels_group_channels(bAnimContext *ac, bAnimListElem *adt_ref, const char name[])
+{
+ AnimData *adt = adt_ref->adt;
+ bAction *act = adt->action;
+
+ if (act) {
+ ListBase anim_data = {NULL, NULL};
+ int filter;
+
+ /* find selected F-Curves to re-group */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL);
+ ANIM_animdata_filter(ac, &anim_data, filter, adt_ref, ANIMCONT_CHANNEL);
+
+ if (anim_data.first) {
+ bActionGroup *agrp;
+ bAnimListElem *ale;
+
+ /* create new group, which should now be part of the action */
+ agrp = action_groups_add_new(act, name);
+ BLI_assert(agrp != NULL);
+
+ /* transfer selected F-Curves across to new group */
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bActionGroup *grp = fcu->grp;
+
+ /* remove F-Curve from group, then group too if it is now empty */
+ action_groups_remove_channel(act, fcu);
+
+ if ((grp) && (grp->channels.first == NULL)) {
+ BLI_freelinkN(&act->groups, grp);
+ }
+
+ /* add F-Curve to group */
+ action_groups_add_channel(act, agrp, fcu);
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+ }
+}
+
+static int animchannels_group_exec(bContext *C, wmOperator *op)
+{
+ bAnimContext ac;
+ char name[MAX_NAME];
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* get name for new group */
+ RNA_string_get(op->ptr, "name", name);
+
+ /* XXX: name for group should never be empty... */
+ if (name[0]) {
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* handle each animdata block separately, so that the regrouping doesn't flow into blocks */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ animchannels_group_channels(&ac, ale, name);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&anim_data);
+
+ /* updatss */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_group(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Group Channels";
+ ot->idname = "ANIM_OT_channels_group";
+ ot->description = "Add selected F-Curves to a new group";
+
+ /* callbacks */
+ ot->invoke = WM_operator_props_popup;
+ ot->exec = animchannels_group_exec;
+ ot->poll = animchannels_grouping_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_string(ot->srna, "name", "New Group",
+ sizeof(((bActionGroup *)NULL)->name),
+ "Name", "Name of newly created group");
+ /* RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); */ /* XXX: still not too sure about this - keeping same text is confusing... */
+}
+
+/* ----------------------------------------------------------- */
+
+static int animchannels_ungroup_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bAnimContext ac;
+
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ /* get editor data */
+ if (ANIM_animdata_get_context(C, &ac) == 0)
+ return OPERATOR_CANCELLED;
+
+ /* just selected F-Curves... */
+ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ /* find action for this F-Curve... */
+ if (ale->adt && ale->adt->action) {
+ FCurve *fcu = (FCurve *)ale->data;
+ bAction *act = ale->adt->action;
+
+ /* only proceed to remove if F-Curve is in a group... */
+ if (fcu->grp) {
+ bActionGroup *agrp = fcu->grp;
+
+ /* remove F-Curve from group and add at tail (ungrouped) */
+ action_groups_remove_channel(act, fcu);
+ BLI_addtail(&act->curves, fcu);
+
+ /* delete group if it is now empty */
+ if (agrp->channels.first == NULL) {
+ BLI_freelinkN(&act->groups, agrp);
+ }
+ }
+ }
+ }
+
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+
+ /* updates */
+ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ANIM_OT_channels_ungroup(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Ungroup Channels";
+ ot->idname = "ANIM_OT_channels_ungroup";
+ ot->description = "Remove selected F-Curves from their current groups";
+
+ /* callbacks */
+ ot->exec = animchannels_ungroup_exec;
+ ot->poll = animchannels_grouping_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/* ******************** Delete Channel Operator *********************** */
static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1223,13 +1449,13 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
BLI_freelinkN(&gpd->layers, gpl);
}
break;
-
+
case ANIMTYPE_MASKLAYER:
{
- /* Grease Pencil layer */
+ /* Mask layer */
Mask *mask = (Mask *)ale->id;
MaskLayer *masklay = (MaskLayer *)ale->data;
-
+
/* try to delete the layer's data and the layer itself */
BKE_mask_layer_remove(mask, masklay);
}
@@ -1320,10 +1546,10 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
/* 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_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, 1);
}
@@ -1397,10 +1623,10 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
/* 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_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, (vis == ACHANNEL_SETFLAG_ADD));
}
@@ -2038,7 +2264,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index)
ED_region_tag_redraw(ac->ar);
}
-static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *evt)
+static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
@@ -2059,7 +2285,7 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEve
* so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
* ACHANNEL_HEIGHT_HALF.
*/
- UI_view2d_region_to_view(v2d, evt->mval[0], evt->mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
if (ac.datatype == ANIMCONT_NLA) {
SpaceNla *snla = (SpaceNla *)ac.sl;
@@ -2197,6 +2423,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
case ANIMTYPE_DSNTREE:
case ANIMTYPE_DSTEX:
case ANIMTYPE_DSLAT:
+ case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
{
/* sanity checking... */
@@ -2218,7 +2445,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
}
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
- }
+ }
break;
case ANIMTYPE_GROUP:
@@ -2372,7 +2599,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
/* ------------------- */
/* handle clicking */
-static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
@@ -2430,7 +2657,7 @@ static void ANIM_OT_channels_click(wmOperatorType *ot)
ot->poll = animedit_poll_channels_active;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_UNDO;
/* properties */
/* NOTE: don't save settings, otherwise, can end up with some weird behaviour (sticky extend) */
@@ -2470,6 +2697,9 @@ void ED_operatortypes_animchannels(void)
WM_operatortype_append(ANIM_OT_channels_visibility_set);
WM_operatortype_append(ANIM_OT_channels_fcurves_enable);
+
+ WM_operatortype_append(ANIM_OT_channels_group);
+ WM_operatortype_append(ANIM_OT_channels_ungroup);
}
// TODO: check on a poll callback for this, to get hotkeys into menus
@@ -2523,6 +2753,10 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_TOP);
RNA_enum_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_move", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "direction", REARRANGE_ANIMCHAN_BOTTOM);
+ /* grouping */
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_group", GKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "ANIM_OT_channels_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
+
/* Graph Editor only */
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);