NLA SoC: Bugfixes + Improvements to 'Push Down' track-selection
authorJoshua Leung <aligorith@gmail.com>
Sun, 31 May 2009 04:52:20 +0000 (04:52 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 31 May 2009 04:52:20 +0000 (04:52 +0000)
* Trying to save no longer crashes in some cases when the NLA Editor was open with some data. The sanity check added in filesel.c might be able to be backported to 2.5? (Elubie, please check)

* NLA-track names now get drawn with the correct colours for identifying themselves as being selected or not selected.

* Now the 'push down' functionality for actions will try to add the new strip to the last NLA track, provided it has space in the range required.
* When new strips are added, they will only be allowed to extrapolate before/after if they are the first (time-wise) strip for the set of NLA data per AnimData block. This stops layered strips overriding strips that occurred in earlier tracks at earlier times.

source/blender/blenkernel/BKE_nla.h
source/blender/blenkernel/intern/nla.c
source/blender/editors/animation/anim_channels.c
source/blender/editors/space_file/filesel.c
source/blender/editors/space_nla/nla_draw.c

index 49796250633aec6d7986c90102ed67a98fe4dadc..ededd77a92ff77adee694f4179ceab04cd1068c9 100644 (file)
@@ -46,8 +46,9 @@ struct NlaStrip *copy_nlastrip(struct NlaStrip *strip);
 struct NlaTrack *copy_nlatrack(struct NlaTrack *nlt);
 void copy_nladata(ListBase *dst, ListBase *src);
 
-struct NlaStrip *add_nlastrip(struct NlaTrack *nlt, struct bAction *act);
 struct NlaTrack *add_nlatrack(struct AnimData *adt);
+struct NlaStrip *add_nlastrip(struct bAction *act);
+struct NlaStrip *add_nlastrip_to_stack(struct AnimData *adt, struct bAction *act);
 
 /* ----------------------------- */
 /* API */
index 62500af85ffe63064b981471e390f6381ab88661..3efa823f9fee20e9a2dca2ea6f5afff4c2e8ddd2 100644 (file)
@@ -215,19 +215,45 @@ void copy_nladata (ListBase *dst, ListBase *src)
 
 /* Adding ------------------------------------------- */
 
-/* Add a NLA Strip referencing the given Action, to the given NLA Track */
-// TODO: any extra parameters to control how this is done?
-NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act)
+/* Add a NLA Track to the given AnimData */
+NlaTrack *add_nlatrack (AnimData *adt)
+{
+       NlaTrack *nlt;
+       
+       /* sanity checks */
+       if (adt == NULL)
+               return NULL;
+               
+       /* allocate new track */
+       nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
+       
+       /* set settings requiring the track to not be part of the stack yet */
+       nlt->flag = NLATRACK_SELECTED;
+       nlt->index= BLI_countlist(&adt->nla_tracks);
+       
+       /* add track to stack, and make it the active one */
+       BLI_addtail(&adt->nla_tracks, nlt);
+       BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
+       
+       /* must have unique name, but we need to seed this */
+       sprintf(nlt->name, "NlaTrack");
+       BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
+       
+       /* return the new track */
+       return nlt;
+}
+
+/* Add a NLA Strip referencing the given Action */
+NlaStrip *add_nlastrip (bAction *act)
 {
        NlaStrip *strip;
        
        /* sanity checks */
-       if ELEM(NULL, nlt, act)
+       if (act == NULL)
                return NULL;
                
        /* allocate new strip */
        strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
-       BLI_addtail(&nlt->strips, strip);
        
        /* generic settings 
         *      - selected flag to highlight this to the user
@@ -259,32 +285,54 @@ NlaStrip *add_nlastrip (NlaTrack *nlt, bAction *act)
        return strip;
 }
 
-/* Add a NLA Track to the given AnimData */
-NlaTrack *add_nlatrack (AnimData *adt)
+/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
+NlaStrip *add_nlastrip_to_stack (AnimData *adt, bAction *act)
 {
+       NlaStrip *strip, *ns;
        NlaTrack *nlt;
+       short not_added = 1;
        
        /* sanity checks */
-       if (adt == NULL)
+       if ELEM(NULL, adt, act)
                return NULL;
-               
-       /* allocate new track */
-       nlt= MEM_callocN(sizeof(NlaTrack), "NlaTrack");
        
-       /* set settings requiring the track to not be part of the stack yet */
-       nlt->flag = NLATRACK_SELECTED;
-       nlt->index= BLI_countlist(&adt->nla_tracks);
+       /* create a new NLA strip */
+       strip= add_nlastrip(act);
+       if (strip == NULL)
+               return NULL;
        
-       /* add track to stack, and make it the active one */
-       BLI_addtail(&adt->nla_tracks, nlt);
-       BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
+       /* check if the last NLA-track (if it exists) has any space for this strip:
+        *      - if so, add this strip to that track
+        */
+       if ( (adt->nla_tracks.last == NULL) || 
+                (BKE_nlatrack_has_space(adt->nla_tracks.last, strip->start, strip->end)==0) ) 
+       {
+               /* no space, so add to a new track... */
+               nlt= add_nlatrack(adt);
+       }
+       else 
+       {
+               /* there's some space, so add to this track... */
+               nlt= adt->nla_tracks.last;
+       }
        
-       /* must have unique name, but we need to seed this */
-       sprintf(nlt->name, "NlaTrack");
-       BLI_uniquename(&adt->nla_tracks, nlt, "NlaTrack", '.', offsetof(NlaTrack, name), 64);
+       /* find the right place to add the strip to the nominated track */
+       for (ns= nlt->strips.first; ns; ns= ns->next) {
+               /* if current strip occurs after the new strip, add it before */
+               if (ns->start > strip->end) {
+                       BLI_insertlinkbefore(&nlt->strips, ns, strip);
+                       not_added= 0;
+                       break;
+               }
+       }
+       if (not_added) {
+               /* just add to the end of the list of the strips then... */
+               BLI_addtail(&nlt->strips, strip);
+       }
        
-       /* return the new track */
-       return nlt;
+       
+       /* returns the strip added */
+       return strip;
 }
 
 /* *************************************************** */
@@ -404,7 +452,39 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt)
        nlt->strips.first= tmp.first;
        nlt->strips.last= tmp.last;
 }
+
+/* NLA Strips -------------------------------------- */
+
+/* Is the given NLA-strip the first one to occur for the given AnimData block */
+// TODO: make this an api method if necesary, but need to add prefix first
+short nlastrip_is_first (AnimData *adt, NlaStrip *strip)
+{
+       NlaTrack *nlt;
+       NlaStrip *ns;
+       
+       /* sanity checks */
+       if ELEM(NULL, adt, strip)
+               return 0;
+               
+       /* check if strip has any strips before it */
+       if (strip->prev)
+               return 0;
+               
+       /* check other tracks to see if they have a strip that's earlier */
+       // TODO: or should we check that the strip's track is also the first?
+       for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+               /* only check the first strip, assuming that they're all in order */
+               ns= nlt->strips.first;
+               if (ns) {
+                       if (ns->start < strip->start)
+                               return 0;
+               }
+       }       
+       
+       /* should be first now */
+       return 1;
+}
+
 /* Tools ------------------------------------------- */
 
 /* For the given AnimData block, add the active action to the NLA
@@ -415,7 +495,6 @@ void BKE_nlatrack_sort_strips (NlaTrack *nlt)
 // TODO: maybe we should have checks for this too...
 void BKE_nla_action_pushdown (AnimData *adt)
 {
-       NlaTrack *nlt;
        NlaStrip *strip;
        
        /* sanity checks */
@@ -431,28 +510,27 @@ void BKE_nla_action_pushdown (AnimData *adt)
                printf("BKE_nla_action_pushdown(): action has no data \n");
                return;
        }
-               
-       /* add a new NLA track to house this action 
-        *      - we could investigate trying to fit the action into an appropriately
-        *        sized gap in the existing tracks, however, this may result in unexpected 
-        *        changes in blending behaviour...
-        */
-       nlt= add_nlatrack(adt);
-       if (nlt == NULL) {
-               printf("BKE_nla_action_pushdown(): no NLA-track added \n");
-               return;
-       }
        
        /* add a new NLA strip to the track, which references the active action */
-       strip= add_nlastrip(nlt, adt->action);
+       strip= add_nlastrip_to_stack(adt, adt->action);
        
-       /* clear reference to action now that we've pushed it onto the stack */
+       /* do other necessary work on strip */  
        if (strip) {
+               /* clear reference to action now that we've pushed it onto the stack */
                adt->action->id.us--;
                adt->action= NULL;
+               
+               /* if the strip is the first one in the track it lives in, check if there
+                * are strips in any other tracks that may be before this, and set the extend
+                * mode accordingly
+                */
+               if (nlastrip_is_first(adt, strip) == 0) {
+                       /* not first, so extend mode can only be NLASTRIP_EXTEND_HOLD_FORWARD not NLASTRIP_EXTEND_HOLD,
+                        * so that it doesn't override strips in previous tracks
+                        */
+                       strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
+               }
        }
-       
-       // TODO: set any other flags necessary here...
 }
 
 /* *************************************************** */
index a5f2acb591c17dee202f17e035be540941a46908..5d5be87801b02e3455713e343df60a22cc7010ee 100644 (file)
@@ -149,6 +149,13 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
                                ACHANNEL_SET_FLAG(fcu, ACHANNEL_SETFLAG_CLEAR, FCURVE_ACTIVE);
                        }
                                break;
+                       case ANIMTYPE_NLATRACK:
+                       {
+                               NlaTrack *nlt= (NlaTrack *)ale->data;
+                               
+                               ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
+                       }
+                               break;
                }
        }
        
@@ -167,6 +174,13 @@ void ANIM_set_active_channel (void *data, short datatype, int filter, void *chan
                                fcu->flag |= FCURVE_ACTIVE;
                        }
                                break;
+                       case ANIMTYPE_NLATRACK:
+                       {
+                               NlaTrack *nlt= (NlaTrack *)channel_data;
+                               
+                               ACHANNEL_SET_FLAG(nlt, ACHANNEL_SETFLAG_CLEAR, NLATRACK_ACTIVE);
+                       }
+                               break;
                }
        }
        
index cbd1457e5621a7546cae1e6e90b54d3bb9578c53..091319cd4020276ea69f21ac98f63c122c8a35c8 100644 (file)
@@ -144,6 +144,9 @@ int ED_fileselect_layout_offset(FileLayout* layout, int x, int y)
        int offsetx, offsety;
        int active_file;
 
+       if (layout == NULL)
+               return NULL;
+       
        offsetx = (x)/(layout->tile_w + 2*layout->tile_border_x);
        offsety = (y)/(layout->tile_h + 2*layout->tile_border_y);
        
index 285727043021e920be2e643ec2a356fffa93cb2d..1a289d8436b5e06a120a12469e596423bc70c7bb 100644 (file)
@@ -296,7 +296,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
                                        indent= 0;
                                        
                                        special= ICON_SCENE_DATA;
-                                               
+                                       
                                        /* only show expand if there are any channels */
                                        if (EXPANDED_SCEC(sce))
                                                expand= ICON_TRIA_UP;
@@ -484,6 +484,7 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
                                        else
                                                protect = ICON_LOCKED;
                                                
+                                       sel = SEL_NLT(nlt);
                                        strcpy(name, nlt->name);
                                }
                                        break;
@@ -621,10 +622,10 @@ void draw_nla_channel_list (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
                                
                                /* XXX firstly draw a little rect to help identify that it's different from the toggles */
                                glBegin(GL_LINE_LOOP);
-                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-8);
-                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+8);
-                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-8);
-                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+8);
+                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y-7);
+                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-offset-1, y+9);
+                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y+9);
+                                       glVertex2f((float)NLACHANNEL_NAMEWIDTH-1, y-7);
                                glEnd(); // GL_LINES
                                
                                /* now draw the icon */