diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2014-03-14 15:45:22 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2014-03-14 15:48:15 +0400 |
commit | 1f3655d224196129fc6daf20e678199b95321bff (patch) | |
tree | 30ca82ce747f1634bdc1ccfb1b9fe26aecfbed30 /source/blender/editors/animation/anim_channels_edit.c | |
parent | ade6646755224ce9178d280738727c1a968b28b6 (diff) |
Fix T38897: Problems moving animation channels up and down in dope sheet/action editor.
Basic idea is to check whether an element is visible or not, and ignore those that are hidden, during move up/down.
Reviewers: aligorith
Reviewed By: aligorith
Differential Revision: https://developer.blender.org/D376
Diffstat (limited to 'source/blender/editors/animation/anim_channels_edit.c')
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 89 |
1 files changed, 74 insertions, 15 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index ee8b5dcee67..eb9881aa0b6 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -36,6 +36,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BKE_library.h" #include "DNA_anim_types.h" @@ -653,7 +654,8 @@ typedef struct tReorderChannelIsland { typedef enum eReorderIslandFlag { REORDER_ISLAND_SELECTED = (1 << 0), /* island is selected */ REORDER_ISLAND_UNTOUCHABLE = (1 << 1), /* island should be ignored */ - REORDER_ISLAND_MOVED = (1 << 2) /* island has already been moved */ + REORDER_ISLAND_MOVED = (1 << 2), /* island has already been moved */ + REORDER_ISLAND_HIDDEN = (1 << 3), /* island is not visible */ } eReorderIslandFlag; @@ -691,7 +693,12 @@ static bool rearrange_island_up(ListBase *list, tReorderChannelIsland *island) if (rearrange_island_ok(island)) { /* moving up = moving before the previous island, otherwise we're in the same place */ tReorderChannelIsland *prev = island->prev; - + + /* Skip hidden islands! */ + while (prev && prev->flag & REORDER_ISLAND_HIDDEN) { + prev = prev->prev; + } + if (prev) { /* remove from current position */ BLI_remlink(list, island); @@ -711,7 +718,12 @@ static bool rearrange_island_down(ListBase *list, tReorderChannelIsland *island) if (rearrange_island_ok(island)) { /* moving down = moving after the next island, otherwise we're in the same place */ tReorderChannelIsland *next = island->next; - + + /* Skip hidden islands! */ + while (next && next->flag & REORDER_ISLAND_HIDDEN) { + next = next->next; + } + if (next) { /* can only move past if next is not untouchable (i.e. nothing can go after it) */ if ((next->flag & REORDER_ISLAND_UNTOUCHABLE) == 0) { @@ -784,7 +796,7 @@ static AnimChanRearrangeFp rearrange_get_mode_func(short mode) /* Rearrange Islands Generics ------------------------------------- */ /* add channel into list of islands */ -static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList, Link *channel, short type) +static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *srcList, Link *channel, short type, const bool is_hidden) { tReorderChannelIsland *island = islands->last; /* always try to add to last island if possible */ bool is_sel = false, is_untouchable = false; @@ -819,9 +831,15 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr } /* do we need to add to a new island? */ - if ((island == NULL) || /* 1) no islands yet */ - ((island->flag & REORDER_ISLAND_SELECTED) == 0) || /* 2) unselected islands have single channels only - to allow up/down movement */ - (is_sel == 0)) /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */ + if (/* 1) no islands yet */ + (island == NULL) || + /* 2) unselected islands have single channels only - to allow up/down movement */ + ((island->flag & REORDER_ISLAND_SELECTED) == 0) || + /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */ + (is_sel == 0) || + /* 4) hidden status changes */ + ((island->flag & REORDER_ISLAND_HIDDEN) != is_hidden) + ) { /* create a new island now */ island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland"); @@ -831,6 +849,8 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr island->flag |= REORDER_ISLAND_SELECTED; if (is_untouchable) island->flag |= REORDER_ISLAND_UNTOUCHABLE; + if (is_hidden) + island->flag |= REORDER_ISLAND_HIDDEN; } /* add channel to island - need to remove it from its existing list first though */ @@ -858,8 +878,16 @@ static void rearrange_animchannel_flatten_islands(ListBase *islands, ListBase *s /* ............................. */ +static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, bAnimContext *ac, short type) +{ + int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + + ANIM_animdata_filter(ac, anim_data_visible, filter, ac->data, type); +} + /* performing rearranging of channels using islands */ -static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type) +static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp rearrange_func, + short mode, short type, ListBase *anim_data_visible) { ListBase islands = {NULL, NULL}; Link *channel, *chanNext = NULL; @@ -871,8 +899,10 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re /* group channels into islands */ for (channel = list->first; channel; channel = chanNext) { + /* find out whether this channel is present in anim_data_visible or not! */ + const bool is_hidden = (BLI_findptr(anim_data_visible, channel, offsetof(bAnimListElem, data)) == NULL); chanNext = channel->next; - rearrange_animchannel_add_to_islands(&islands, list, channel, type); + rearrange_animchannel_add_to_islands(&islands, list, channel, type, is_hidden); } /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen @@ -907,9 +937,10 @@ static bool rearrange_animchannel_islands(ListBase *list, AnimChanRearrangeFp re * ! NLA tracks are displayed in opposite order, so directions need care * mode: REARRANGE_ANIMCHAN_* */ -static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, short mode) +static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, short mode) { AnimChanRearrangeFp rearrange_func; + ListBase anim_data_visible = {NULL, NULL}; /* hack: invert mode so that functions will work in right order */ mode *= -1; @@ -923,8 +954,14 @@ static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, shor //if (EXPANDED_DRVD(adt) == 0) // return; + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_NLATRACK); + /* perform rearranging on tracks list */ - rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK); + rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); + + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* Drivers Specific Stuff ------------------------------------------------- */ @@ -932,10 +969,11 @@ static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, shor /* Change the order drivers within AnimData block * mode: REARRANGE_ANIMCHAN_* */ -static void rearrange_driver_channels(bAnimContext *UNUSED(ac), AnimData *adt, short mode) +static void rearrange_driver_channels(bAnimContext *ac, AnimData *adt, short mode) { /* get rearranging function */ AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode); + ListBase anim_data_visible = {NULL, NULL}; if (rearrange_func == NULL) return; @@ -944,8 +982,14 @@ static void rearrange_driver_channels(bAnimContext *UNUSED(ac), AnimData *adt, s if (EXPANDED_DRVD(adt) == 0) return; + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); + /* perform rearranging on drivers list (drivers are really just F-Curves) */ - rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE); + rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE, &anim_data_visible); + + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* Action Specific Stuff ------------------------------------------------- */ @@ -1027,6 +1071,7 @@ static void join_groups_action_temp(bAction *act) static void rearrange_action_channels(bAnimContext *ac, bAction *act, short mode) { bActionGroup tgrp; + ListBase anim_data_visible = {NULL, NULL}; bool do_channels; /* get rearranging function */ @@ -1038,21 +1083,35 @@ static void rearrange_action_channels(bAnimContext *ac, bAction *act, short mode /* make sure we're only operating with groups (vs a mixture of groups+curves) */ split_groups_action_temp(act, &tgrp); + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_GROUP); + /* rearrange groups first * - the group's channels will only get considered if nothing happened when rearranging the groups * i.e. the rearrange function returned 0 */ - do_channels = rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP) == 0; + do_channels = (rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP, + &anim_data_visible) == 0); + + /* free temp data */ + BLI_freelistN(&anim_data_visible); if (do_channels) { bActionGroup *agrp; + /* Filter visible data. */ + rearrange_animchannels_filter_visible(&anim_data_visible, ac, ANIMTYPE_FCURVE); + for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* only consider F-Curves if they're visible (group expanded) */ if (EXPANDED_AGRP(ac, agrp)) { - rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE); + rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE, + &anim_data_visible); } } + + /* free temp data */ + BLI_freelistN(&anim_data_visible); } /* assemble lists into one list (and clear moved tags) */ |