== NLA - Scale Setting for Strips ==
authorJoshua Leung <aligorith@gmail.com>
Fri, 7 Dec 2007 04:24:02 +0000 (04:24 +0000)
committerJoshua Leung <aligorith@gmail.com>
Fri, 7 Dec 2007 04:24:02 +0000 (04:24 +0000)
NLA-Strips now have a new setting: Scale.

It determines how much the action-range is scaled for each repeat, instead of the scaling being implicitly determined based on repeats + strip-length.

One of the instant benefits of this, is that when increasing the number of repeats, the strip length increases by the right amount. Thus, increasing the number of repeats retains a constant speed.

Hopefully we can prevent weirdly scaled actions this way. (i.e.  0.00001 frames long action * 10000 or so)

Todo:
- Transform code needs to be able to set the scale setting (it doesn't yet)
- Add a new option to "apply scaling", to fix up problems with old files that have really bad scaling. Situations when this is needed could get indicated in the interface too... (red background for "Scale" field?)

source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/action.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_nla_types.h
source/blender/src/drawnla.c
source/blender/src/editnla.c

index 1f8d5e44c965489e0a2f7ba82108a02da2bde768..730be30a42721595db12cf9a12ced3383610636f 100644 (file)
@@ -44,7 +44,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        245
-#define BLENDER_SUBVERSION             10
+#define BLENDER_SUBVERSION             11
 
 #define BLENDER_MINVERSION             240
 #define BLENDER_MINSUBVERSION  0
index e30d7dd4ac9dc8615a73b59daa21b5fcc41f34d8..7731eea36946b2818fd0565c662d08f90e15fc5d 100644 (file)
@@ -433,21 +433,18 @@ static bActionStrip *get_active_strip(Object *ob)
 /* non clipped mapping of strip */
 static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert)
 {
-       float length, actlength, repeat;
+       float length, actlength, repeat, scale;
        
-       if (strip->flag & ACTSTRIP_USESTRIDE)
-               repeat= 1.0f;
-       else
-               repeat= strip->repeat;
+       repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat);
+       scale = abs(strip->scale); /* scale must be positive (for now) */
        
-       length = strip->end-strip->start;
-       if(length==0.0f)
-               length= 1.0f;
        actlength = strip->actend-strip->actstart;
+       if (actlength == 0.0f) actlength = 1.0f;
+       length = repeat * scale * actlength;
        
-       
-       
-       if(invert)
+       /* invert = convert action-strip time to global time */
+       // FIXME?
+       if (invert)
                return length*(cframe - strip->actstart)/(repeat*actlength) + strip->start;
        else
                return repeat*actlength*(cframe - strip->start)/length + strip->actstart;
index 43bddc275b7ce48951d824ea4f3a0701efa69873..f6b0c4cb4dc562c0b0afc933402d9f82858a8e04 100644 (file)
@@ -7187,11 +7187,36 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) {
                Object *ob;
-
+               
                /* dupliface scale */
                for(ob= main->object.first; ob; ob= ob->id.next)
                        ob->dupfacesca = 1.0f;
        }
+       
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
+               Object *ob;
+               bActionStrip *strip;
+               
+               /* nla-strips - scale */                
+               for (ob= main->object.first; ob; ob= ob->id.next) {
+                       for (strip= ob->nlastrips.first; strip; strip= strip->next) {
+                               float length, actlength, repeat;
+                               
+                               if (strip->flag & ACTSTRIP_USESTRIDE)
+                                       repeat= 1.0f;
+                               else
+                                       repeat= strip->repeat;
+                               
+                               length = strip->end-strip->start;
+                               if (length == 0.0f) length= 1.0f;
+                               actlength = strip->actend-strip->actstart;
+                               
+                               // right calculation? 
+                               strip->scale = actlength / (length * repeat);
+                               if (strip->scale == 0.0f) strip->scale= 1.0f;
+                       }       
+               }
+       }
 
        
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
index d7ccfe010859b5c02697af809c97a62e765bf230..e9a0a3d060265c3ae60f717622aba43310a49c1a 100644 (file)
@@ -70,17 +70,17 @@ typedef struct bActionStrip {
        struct  Object *object;         /* For groups, the actual object being nla'ed */
        float   start, end;                     /* The range of frames covered by this strip */
        float   actstart, actend;       /* The range of frames taken from the action */
-       float   actoffs, padf;          /* Offset within action, for cycles and striding */
+       float   actoffs;                        /* Offset within action, for cycles and striding */
        float   stridelen;                      /* The stridelength (considered when flag & ACT_USESTRIDE) */
        float   repeat;                         /* The number of times to repeat the action range */
+       float   scale;                          /* The amount the action range is scaled by */
 
        float   blendin, blendout;      /* The number of frames on either end of the strip's length to fade in/out */
        
        char    stridechannel[32];      /* Instead of stridelen, it uses an action channel */
        char    offs_bone[32];          /* if repeat, use this bone/channel for defining offset */
        
-       struct ListBase modifiers;      /* modifier stack */
-       
+       ListBase modifiers;                     /* modifier stack */
 } bActionStrip;
 
 /* strip->mode (these defines aren't really used, but are here for reference) */
@@ -88,18 +88,20 @@ typedef struct bActionStrip {
 #define ACTSTRIPMODE_ADD               1
 
 /* strip->flag */
-#define ACTSTRIP_SELECT                        0x01
-#define ACTSTRIP_USESTRIDE             0x02
-#define ACTSTRIP_BLENDTONEXT   0x04    /* Not implemented. Is not used anywhere */
-#define ACTSTRIP_HOLDLASTFRAME 0x08
-#define ACTSTRIP_ACTIVE                        0x10
-#define ACTSTRIP_LOCK_ACTION   0x20
-#define ACTSTRIP_MUTE                  0x40
-#define ACTSTRIP_REVERSE               0x80    /* This has yet to be implemented. To indicate that a strip should be played backwards */
-#define ACTSTRIP_CYCLIC_USEX   0x100
-#define ACTSTRIP_CYCLIC_USEY   0x200
-#define ACTSTRIP_CYCLIC_USEZ   0x400
-#define ACTSTRIP_AUTO_BLENDS   0x800
+typedef enum eActStrip_Flag {
+       ACTSTRIP_SELECT                 = (1<<0),
+       ACTSTRIP_USESTRIDE              = (1<<1),
+       ACTSTRIP_BLENDTONEXT    = (1<<2),       /* Not implemented. Is not used anywhere */
+       ACTSTRIP_HOLDLASTFRAME  = (1<<3),
+       ACTSTRIP_ACTIVE                 = (1<<4),
+       ACTSTRIP_LOCK_ACTION    = (1<<5),
+       ACTSTRIP_MUTE                   = (1<<6),
+       ACTSTRIP_REVERSE                = (1<<7),       /* This has yet to be implemented. To indicate that a strip should be played backwards */
+       ACTSTRIP_CYCLIC_USEX    = (1<<8),
+       ACTSTRIP_CYCLIC_USEY    = (1<<9),
+       ACTSTRIP_CYCLIC_USEZ    = (1<<10),
+       ACTSTRIP_AUTO_BLENDS    = (1<<11)
+} eActStrip_Flag;
 
 #endif
 
index 0394fcce80b4e3ff9f98c3ed060ba9e25a176e83..c1a45ff42f3657818a63a8e0a2447f36c63b74f9 100644 (file)
@@ -446,11 +446,13 @@ static void draw_nla_strips_keys(SpaceNla *snla)
 
 #define B_NLA_PANEL            121
 #define B_NLA_LOCK             122
-#define B_NLA_MOD_ADD  123
-#define B_NLA_MOD_NEXT 124
-#define B_NLA_MOD_PREV 125
-#define B_NLA_MOD_DEL  126
-#define B_NLA_MOD_DEPS 127
+#define B_NLA_SCALE            123
+#define B_NLA_SCALE2   124
+#define B_NLA_MOD_ADD  125
+#define B_NLA_MOD_NEXT 126
+#define B_NLA_MOD_PREV 127
+#define B_NLA_MOD_DEL  128
+#define B_NLA_MOD_DEPS 129
 
 /* For now just returns the first selected strip */
 bActionStrip *get_active_nlastrip(Object **obpp)
@@ -491,9 +493,37 @@ void do_nlabuts(unsigned short event)
                allqueue (REDRAWNLA, 0);
                allqueue (REDRAWVIEW3D, 0);
                break;
+       case B_NLA_SCALE:
+               {
+                       float actlen= strip->actend - strip->actstart;
+                       float mapping= strip->scale * strip->repeat;
+                       
+                       strip->end = (actlen * mapping) + strip->start; 
+                       
+                       allqueue (REDRAWNLA, 0);
+                       allqueue (REDRAWIPO, 0);
+                       allqueue (REDRAWACTION, 0);
+                       allqueue (REDRAWVIEW3D, 0);
+               }
+               break;
+       case B_NLA_SCALE2:
+               {
+                       float actlen= strip->actend - strip->actstart;
+                       float len= strip->end - strip->start;
+                       
+                       strip->scale= len / (actlen * strip->repeat);
+                       
+                       allqueue (REDRAWNLA, 0);
+                       allqueue (REDRAWIPO, 0);
+                       allqueue (REDRAWACTION, 0);
+                       allqueue (REDRAWVIEW3D, 0);
+               }
+               break;
        case B_NLA_LOCK:
                synchronize_action_strips();
+               
                allqueue (REDRAWNLA, 0);
+               allqueue (REDRAWIPO, 0);
                allqueue (REDRAWACTION, 0);
                allqueue (REDRAWVIEW3D, 0);
                break;
@@ -576,7 +606,7 @@ static void nla_panel_properties(short cntrl)       // NLA_HANDLER_PROPERTIES
 
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, B_NLA_PANEL, "Strip Start:",      10,160,150,19, &strip->start, -1000.0, strip->end-1, 100, 0, "First frame in the timeline");
-       uiDefButF(block, NUM, B_NLA_PANEL, "Strip End:",        160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline");
+       uiDefButF(block, NUM, B_NLA_SCALE2, "Strip End:",       160,160,150,19, &strip->end, strip->start+1, MAXFRAMEF, 100, 0, "Last frame in the timeline");
 
        uiDefIconButBitS(block, ICONTOG, ACTSTRIP_LOCK_ACTION, B_NLA_LOCK, ICON_UNLOCKED,       10,140,20,19, &(strip->flag), 0, 0, 0, 0, "Toggles Action end/start to be automatic mapped to strip duration");
        if(strip->flag & ACTSTRIP_LOCK_ACTION) {
@@ -607,7 +637,9 @@ static void nla_panel_properties(short cntrl)       // NLA_HANDLER_PROPERTIES
        uiDefButBitS(block, TOG, ACTSTRIP_MUTE, B_NLA_PANEL, "Mute", 10,60,145,19, &strip->flag, 0, 0, 0, 0, "Toggles whether the strip contributes to the NLA solution");
        
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:",   160,100,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat");
+               // FIXME: repeat and scale are too cramped!
+       uiDefButF(block, NUM, B_NLA_SCALE, "Repeat:",   160,100,75,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat");
+       uiDefButF(block, NUM, B_NLA_SCALE, "Scale:",    235,100,75,19, &strip->scale, 0.001, 10000.0f, 100, 0, "Amount the action should be scaled by");
        but= uiDefButC(block, TEX, B_NLA_PANEL, "OffsBone:", 160,80,150,19, strip->offs_bone, 0, 31.0f, 0, 0, "Name of Bone that defines offset for repeat");
        uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
        uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold",   160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
index ec3b1c834e5b395f161401627f64fac0257e8065..34b60e3e820bb74086a383db93d15306752cd1e4 100644 (file)
@@ -198,11 +198,12 @@ void synchronize_action_strips(void)
                                
                                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->start+= mapping*(actstart - strip->actstart);
-                                       strip->end+= mapping*(actend - strip->actend);
+                                       offset= strip->scale * (actstart - strip->actstart);
+                                       strip->start += offset;
+                                       strip->end = strip->scale * strip->repeat * (actend-actstart) + strip->start;
                                        
                                        strip->actstart= actstart;
                                        strip->actend= actend;