svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / editnla.c
index 0361d5395c2fef4a52f234dbe2ad3b7b48e1e565..dbc0deecb2cae140def1e887f362347c3d67e03a 100644 (file)
@@ -188,21 +188,27 @@ void shift_nlastrips_down(void) {
 void synchronize_action_strips(void)
 {
        Base *base;
+       Object *ob;
        bActionStrip *strip;
        
        for (base=G.scene->base.first; base; base=base->next) {
+               /* get object first */
+               ob= base->object;
+               
                /* step 1: adjust strip-lengths */
-               for (strip = base->object->nlastrips.last; strip; strip=strip->prev) {
+               //      FIXME: this seems very buggy
+               for (strip = ob->nlastrips.last; strip; strip=strip->prev) {
                        if (strip->flag & ACTSTRIP_LOCK_ACTION) {
                                float actstart, actend;
                                
                                calc_action_range(strip->act, &actstart, &actend, 1);
                                
-                               if(strip->actstart!=actstart || strip->actend!=actend) {
-                                       float mapping= (strip->end - strip->start)/(strip->actend - strip->actstart);
+                               if ((strip->actstart!=actstart) || (strip->actend!=actend)) {           
+                                       float offset = strip->scale * (actstart - strip->actstart);
+                                       float actlen = actend - actstart;
                                        
-                                       strip->start+= mapping*(actstart - strip->actstart);
-                                       strip->end+= mapping*(actend - strip->actend);
+                                       strip->start += offset;
+                                       strip->end = (strip->scale * strip->repeat * actlen) + strip->start;
                                        
                                        strip->actstart= actstart;
                                        strip->actend= actend;
@@ -211,7 +217,7 @@ void synchronize_action_strips(void)
                }
                
                /* step 2: adjust blendin/out values for each strip if option is turned on */
-               for (strip= base->object->nlastrips.first; strip; strip=strip->next) {
+               for (strip= ob->nlastrips.first; strip; strip=strip->next) {
                        if (strip->flag & ACTSTRIP_AUTO_BLENDS) {
                                bActionStrip *prev= strip->prev;
                                bActionStrip *next= strip->next;
@@ -371,15 +377,41 @@ void reset_action_strips(int val)
                
                for (strip = base->object->nlastrips.last; strip; strip=strip->prev) {
                        if (strip->flag & ACTSTRIP_SELECT) {
-                               if(val==2) {
-                                       calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
-                               }
-                               else if(val==1) {
-                                       float mapping= (strip->actend - strip->actstart)/(strip->end - strip->start);
-                                       
-                                       strip->end= strip->start + mapping*(strip->end - strip->start);
+                               switch (val) {
+                                       case 1:
+                                       {
+                                               /* clear scaling - reset to 1.0 without touching keys */
+                                               float actlen= (strip->actend - strip->actstart);
+                                               
+                                               strip->scale= 1.0f;
+                                               strip->end= (strip->repeat * actlen) + strip->start;
+                                       }
+                                               break;
+                                       case 2:
+                                       {
+                                               /* reset action-range */
+                                               calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
+                                       }
+                                               break;
+                                       case 3:
+                                       {
+                                               /* apply scale to keys - scale is reset to 1.0f, but keys stay at the same times */
+                                               bActionChannel *achan;
+                                               
+                                               if (strip->act) {
+                                                       for (achan= strip->act->chanbase.first; achan; achan= achan->next) {
+                                                               actstrip_map_ipo_keys(base->object, achan->ipo, 0, 0);
+                                                       }
+                                                       
+                                                       /* now we can reset scale */
+                                                       calc_action_range(strip->act, &strip->actstart, &strip->actend, 1);
+                                                       strip->scale= 1.0f;
+                                                       strip->end = (strip->repeat * (strip->actend - strip->actstart)) + strip->start;
+                                               }
+                                       }
+                                               break;
                                }
-                               base->object->ctime= -1234567.0f;       // eveil! 
+                               base->object->ctime= -1234567.0f;       // evil! 
                                DAG_object_flush_update(G.scene, base->object, OB_RECALC_OB|OB_RECALC_DATA);
                        }
                }
@@ -429,7 +461,7 @@ void snap_action_strips(int snap_mode)
                                }
                                else if (snap_mode==3) {
                                        /* nearest second */
-                                       float secf = (float)(G.scene->r.frs_sec);
+                                       float secf = FPS;
                                        strip->start= (float)(floor(strip->start/secf + 0.5f) * secf);
                                        strip->end= (float)(floor(strip->end/secf + 0.5f) * secf);
                                }
@@ -469,26 +501,47 @@ static void set_active_strip(Object *ob, bActionStrip *act)
 {
        bActionStrip *strip;
        
+       /* make sure all other strips are not active */
        for (strip = ob->nlastrips.first; strip; strip=strip->next)
                strip->flag &= ~ACTSTRIP_ACTIVE;
        
-       if(act) {
+       /* act is new active strip */
+       if (act) {
+               /* set active flag for this strip */
                act->flag |= ACTSTRIP_ACTIVE;
-       
-               if(ob->action!=act->act) {
-                       if(ob->action) ob->action->id.us--;
-                       if(act->act->id.lib) {
+               
+               /* check if active action will still be the same one */
+               if (ob->action != act->act) {
+                       /* clear object's links with its current action (if present) */
+                       if (ob->action) {
+                               ob->action->id.us--;
+                       }
+                       
+                       /* only set object's action to active strip's action if possible */
+                       if (act->act->id.lib) {
                                ob->action= NULL;
                        }
                        else {
                                ob->action= act->act;
                                id_us_plus(&ob->action->id);
-                       }                       
+                       }       
+                       
+                       /* request redrawing in relevant spaces */
                        allqueue(REDRAWIPO, 0);
                        allqueue(REDRAWVIEW3D, 0);
                        allqueue(REDRAWACTION, 0);
                        allqueue(REDRAWNLA, 0);
-                       ob->ctime= -1234567.0f; // eveil! 
+                       
+                       /* when only showing action (i.e. nla-override off), 
+                        * reset pose to restpose for armatures 
+                        */
+                       if ((ob->nlaflag & OB_NLA_OVERRIDE)==0) {
+                               if (ob->type == OB_ARMATURE)
+                                       rest_pose(ob->pose);
+                       }
+                       
+                       /* flush depsgraph */
+                       ob->ctime= -1234567.0f; // evil! 
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
                }
        }       
@@ -554,7 +607,7 @@ static void add_nla_block(short event)
                /* simple prevention of zero strips */
        if(strip->start>strip->end-2) 
                strip->end= strip->start+100;
-       strip->repeat = 1.0;
+       strip->repeat = strip->scale= 1.0f;
        
        strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION;
        
@@ -593,6 +646,7 @@ static void add_nla_block_by_name(char name[32], Object *ob, short hold, short a
        
        /* Initialize the new action block */
        strip = MEM_callocN(sizeof(bActionStrip), "bActionStrip");
+       strip->scale= 1.0f;
        
        deselect_nlachannel_keys(0);
        
@@ -982,16 +1036,24 @@ static void recalc_all_ipos(void)
 
 void transform_nlachannel_keys(int mode, int dummy)
 {
+       short context = (U.flag & USER_DRAGIMMEDIATE)?CTX_TWEAK:CTX_NONE;
+
        switch (mode) {
                case 'g':
                {
-                       initTransform(TFM_TIME_TRANSLATE, CTX_NONE);
+                       initTransform(TFM_TIME_TRANSLATE, context);
                        Transform();
                }
                        break;
                case 's':
                {
-                       initTransform(TFM_TIME_SCALE, CTX_NONE);
+                       initTransform(TFM_TIME_SCALE, context);
+                       Transform();
+               }
+                       break;
+               case 'e':
+               {
+                       initTransform(TFM_TIME_EXTEND, context);
                        Transform();
                }
                        break;
@@ -1224,7 +1286,7 @@ static void mouse_nla(int selectmode)
        
        /* Try object ipo or ob-constraint ipo selection */
        base= get_nearest_nlachannel_ob_key(&selx, &sel);
-       marker=find_nearest_marker(1);
+       marker=find_nearest_marker(SCE_MARKERS, 1);
        if (base) {
                isdone= 1;
                
@@ -1684,7 +1746,7 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
        if (!snla) return;
        
        if(val) {
-               if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
+               if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
                
                /* swap mouse buttons based on user preference */
                if (U.flag & USER_LMOUSESELECT) {
@@ -1791,6 +1853,13 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                
                                break;
                                
+                       case EKEY:
+                               if (mval[0] >= NLAWIDTH) {
+                                       transform_nlachannel_keys ('e', 0);
+                                       update_for_newframe_muted();
+                               }
+                               break;
+                               
                        case GKEY:
                                if (mval[0]>=NLAWIDTH) {
                                        if (G.qual & LR_CTRLKEY) {
@@ -1836,14 +1905,12 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                break;
                                
                        case SKEY:
-                               if(G.qual==LR_ALTKEY) {
-                                       val= pupmenu("Action Strip Scale%t|Clear Strip Scale%x1|Remap Start/End%x2");
-                                       if(val==1)
-                                               reset_action_strips(1);
-                                       else if(val==2)
-                                               reset_action_strips(2);
+                               if (G.qual==LR_ALTKEY) {
+                                       val= pupmenu("Action Strip Scale%t|Reset Strip Scale%x1|Remap Action Start/End%x2|Apply Scale%x3");
+                                       if (val > 0)
+                                               reset_action_strips(val);
                                }
-                               else if(G.qual & LR_SHIFTKEY) {
+                               else if (G.qual & LR_SHIFTKEY) {
                                        if (snla->flag & SNLA_DRAWTIME)
                                                val= pupmenu("Snap To%t|Nearest Second%x3|Current Time%x2");
                                        else
@@ -1897,7 +1964,7 @@ void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                
                                                areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
                                                
-                                               cfra= (int)dx;
+                                               cfra= (int)(dx+0.5f);
                                                if(cfra< 1) cfra= 1;
                                                
                                                if( cfra!=CFRA ) {
@@ -2011,6 +2078,6 @@ void copy_action_modifiers(void)
        
        BIF_undo_push("Copy Action Modifiers");
        allqueue(REDRAWNLA, 0);
-       DAG_scene_flush_update(G.scene, screen_view3d_layers());
+       DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
 }