NLA and IPO now have the "AfterTrans Keyframe" option that prevents the creation...
authorJoshua Leung <aligorith@gmail.com>
Wed, 14 May 2008 09:00:22 +0000 (09:00 +0000)
committerJoshua Leung <aligorith@gmail.com>
Wed, 14 May 2008 09:00:22 +0000 (09:00 +0000)
source/blender/makesdna/DNA_space_types.h
source/blender/src/header_ipo.c
source/blender/src/header_nla.c
source/blender/src/transform_conversions.c

index 86f6e4bcbe4ed151548b3d27dc4d7dc86143d99b..619dfbb43a057e14d94321922348f48d430374c8 100644 (file)
@@ -524,7 +524,8 @@ typedef struct SpaceImaSel {
 #define SI_DRAW_STRETCH        1<<21
 
 /* SpaceIpo->flag */
-#define SIPO_LOCK_VIEW 1<<0
+#define SIPO_LOCK_VIEW                 1<<0
+#define SIPO_NOTRANSKEYCULL            1<<1
 
 /* SpaceText flags (moved from DNA_text_types.h) */
 
@@ -616,6 +617,7 @@ typedef struct SpaceImaSel {
 #define SNLA_ALLKEYED          1
 #define SNLA_ACTIVELAYERS      2
 #define SNLA_DRAWTIME          4
+#define SNLA_NOTRANSKEYCULL    8
 
 /* time->flag */
        /* show timing in frames instead of in seconds */
index 81d94725a904cdeb89b05a053df72cf8d069f604..15caf325ec60ad4b32329e45e63d09dffb6a57cf 100644 (file)
@@ -751,6 +751,9 @@ static void do_ipo_viewmenu(void *arg, int event)
        case 14: /* Clear Preview Range */
                anim_previewrange_clear();
                break;
+       case 15: /* AutoMerge Keyframes */
+               G.sipo->flag ^= SIPO_NOTRANSKEYCULL;
+               break;
        }
 }
 
@@ -772,6 +775,9 @@ static uiBlock *ipo_viewmenu(void *arg_unused)
        else
                uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
        
+       uiDefIconTextBut(block, BUTM, 1, (G.sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, 
+                                        "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
+       
        uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
 
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
index ef4b79c0537fa6757aee33caf8de00fd76393943..13bbf0a399973fb4104e7196644b9e94be8c834f 100644 (file)
@@ -128,6 +128,9 @@ static void do_nla_viewmenu(void *arg, int event)
        case 9: /* Clear Preview Range */
                anim_previewrange_clear();
                break;
+       case 10: /* AutoMerge Keyframes */
+               G.snla->flag ^= SNLA_NOTRANSKEYCULL;
+               break;
        }
 }
 
@@ -148,6 +151,9 @@ static uiBlock *nla_viewmenu(void *arg_unused)
        } else {
                uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
        }
+       
+       uiDefIconTextBut(block, BUTM, 1, (G.snla->flag & SNLA_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, 
+                                        "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
                
        uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
                
index 6636c435b8c20fa249d673e56b978d2b0703b60c..e42eedee1f72a0446e1db82e128fd45a75a65802 100644 (file)
@@ -144,6 +144,8 @@ extern ListBase editelems;
 
 /* local function prototype - for Object/Bone Constraints */
 static short constraints_list_needinv(TransInfo *t, ListBase *list);
+/* local function prototype - for finding number of keyframes that are selected for editing */
+static int count_ipo_keys(Ipo *ipo, char side, float cfra);
 
 /* ************************** Functions *************************** */
 
@@ -2490,6 +2492,93 @@ static void posttrans_action_clean (bAction *act)
        BLI_freelistN(&act_data);
 }
 
+/* Called by special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ * remake_all_ipos should have already been called 
+ */
+static void posttrans_nla_clean (TransInfo *t)
+{
+       Base *base;
+       Object *ob;
+       bActionStrip *strip;
+       bActionChannel *achan;
+       bConstraintChannel *conchan;
+       float cfra;
+       char side;
+       int i;
+       
+       /* which side of the current frame should be allowed */
+       if (t->mode == TFM_TIME_EXTEND) {
+               /* only side on which mouse is gets transformed */
+               float xmouse, ymouse;
+               
+               areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
+               side = (xmouse > CFRA) ? 'R' : 'L';
+       }
+       else {
+               /* normal transform - both sides of current frame are considered */
+               side = 'B';
+       }
+       
+       /* only affect keyframes */
+       for (base=G.scene->base.first; base; base=base->next) {
+               ob= base->object;
+               
+               /* Check object ipos */
+               i= count_ipo_keys(ob->ipo, side, CFRA);
+               if (i) posttrans_ipo_clean(ob->ipo);
+               
+               /* Check object constraint ipos */
+               for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
+                       i= count_ipo_keys(conchan->ipo, side, CFRA);    
+                       if (i) posttrans_ipo_clean(ob->ipo);
+               }
+               
+               /* skip actions and nlastrips if object is collapsed */
+               if (ob->nlaflag & OB_NLA_COLLAPSED)
+                       continue;
+               
+               /* Check action ipos */
+               if (ob->action) {
+                       /* exclude if strip is selected too */
+                       for (strip=ob->nlastrips.first; strip; strip=strip->next) {
+                               if (strip->flag & ACTSTRIP_SELECT) {
+                                       if (strip->act == ob->action)
+                                               break;
+                               }
+                       }
+                       if (strip==NULL) {
+                               cfra = get_action_frame(ob, CFRA);
+                               
+                               for (achan=ob->action->chanbase.first; achan; achan=achan->next) {
+                                       if (EDITABLE_ACHAN(achan)) {
+                                               i= count_ipo_keys(achan->ipo, side, cfra);
+                                               if (i) {
+                                                       actstrip_map_ipo_keys(ob, achan->ipo, 0, 1); 
+                                                       posttrans_ipo_clean(achan->ipo);
+                                                       actstrip_map_ipo_keys(ob, achan->ipo, 1, 1);
+                                               }
+                                               
+                                               /* Check action constraint ipos */
+                                               if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
+                                                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
+                                                               if (EDITABLE_CONCHAN(conchan)) {
+                                                                       i = count_ipo_keys(conchan->ipo, side, cfra);
+                                                                       if (i) {
+                                                                               actstrip_map_ipo_keys(ob, conchan->ipo, 0, 1); 
+                                                                               posttrans_ipo_clean(conchan->ipo);
+                                                                               actstrip_map_ipo_keys(ob, conchan->ipo, 1, 1);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }               
+               }
+       }
+}
+
 /* ----------------------------- */
 
 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
@@ -3487,8 +3576,6 @@ void special_aftertrans_update(TransInfo *t)
                        if (key->ipo) {
                                IpoCurve *icu;
                                
-                               
-                               
                                if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 && 
                                     (cancelled == 0) )
                                {
@@ -3507,17 +3594,39 @@ void special_aftertrans_update(TransInfo *t)
                G.saction->flag &= ~SACTION_MOVING;
        }
        else if (t->spacetype == SPACE_NLA) {
+               recalc_all_ipos();      // bad
                synchronize_action_strips();
                
                /* cleanup */
                for (base=G.scene->base.first; base; base=base->next)
                        base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA);
                
-               recalc_all_ipos();      // bad
+               /* after transform, remove duplicate keyframes on a frame that resulted from transform */
+               if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 && 
+                        (cancelled == 0) )
+               {
+                       posttrans_nla_clean(t);
+               }
        }
        else if (t->spacetype == SPACE_IPO) {
                // FIXME! is there any code from the old transform_ipo that needs to be added back? 
                
+               /* after transform, remove duplicate keyframes on a frame that resulted from transform */
+               if (G.sipo->ipo) 
+               {
+                       if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && 
+                                (cancelled == 0) )
+                       {
+                               if (NLA_IPO_SCALED) {
+                                       actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); 
+                                       posttrans_ipo_clean(G.sipo->ipo);
+                                       actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1);
+                               }
+                               else 
+                                       posttrans_ipo_clean(G.sipo->ipo);
+                       }
+               }
+               
                /* resetting slow-parents isn't really necessary when editing sequence ipo's */
                if (G.sipo->blocktype==ID_SEQ)
                        resetslowpar= 0;