Graph editor:
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 13 Apr 2015 13:57:46 +0000 (15:57 +0200)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 13 Apr 2015 13:57:57 +0000 (15:57 +0200)
Normalization feature now uses the full range of the data instead of
just one semiaxis for the maximum size.

source/blender/editors/animation/anim_draw.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_select.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_anim_types.h

index ed294d7208f47b82358ce9eb40bba768b2d844f7..6d0086ca4593bb84f2eb95f9553846559588eed2 100644 (file)
@@ -267,19 +267,26 @@ short ANIM_get_normalization_flags(bAnimContext *ac)
        return 0;
 }
 
-static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag)
+static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, float *r_offset)
 {
-       float factor = 1.0f;
+       float factor = 1.0f, offset = 0.0f;
 
        if (flag & ANIM_UNITCONV_RESTORE) {
+               if (r_offset)
+                       *r_offset = fcu->prev_offset;
+
                return 1.0f / fcu->prev_norm_factor;
        }
 
        if (flag & ANIM_UNITCONV_NORMALIZE_FREEZE) {
+               if (r_offset)
+                       *r_offset = fcu->prev_offset;
                return fcu->prev_norm_factor;
        }
 
        if (G.moving & G_TRANSFORM_FCURVES) {
+               if (r_offset)
+                       *r_offset = fcu->prev_offset;
                return fcu->prev_norm_factor;
        }
 
@@ -288,6 +295,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag)
                BezTriple *bezt;
                int i;
                float max_coord = -FLT_MAX;
+               float min_coord = FLT_MAX;
+               float range;
 
                if (fcu->totvert < 1) {
                        return 1.0f;
@@ -296,35 +305,55 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag)
                if (PRVRANGEON) {
                        for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
                                if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
-                                       max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1]));
-                                       max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1]));
-                                       max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1]));
+                                       max_coord = max_ff(max_coord, bezt->vec[0][1]);
+                                       max_coord = max_ff(max_coord, bezt->vec[1][1]);
+                                       max_coord = max_ff(max_coord, bezt->vec[2][1]);
+
+                                       min_coord = min_ff(min_coord, bezt->vec[0][1]);
+                                       min_coord = min_ff(min_coord, bezt->vec[1][1]);
+                                       min_coord = min_ff(min_coord, bezt->vec[2][1]);
                                }
                        }
                }
                else {
                        for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
-                               max_coord = max_ff(max_coord, fabsf(bezt->vec[0][1]));
-                               max_coord = max_ff(max_coord, fabsf(bezt->vec[1][1]));
-                               max_coord = max_ff(max_coord, fabsf(bezt->vec[2][1]));
+                               max_coord = max_ff(max_coord, bezt->vec[0][1]);
+                               max_coord = max_ff(max_coord, bezt->vec[1][1]);
+                               max_coord = max_ff(max_coord, bezt->vec[2][1]);
+
+                               min_coord = min_ff(min_coord, bezt->vec[0][1]);
+                               min_coord = min_ff(min_coord, bezt->vec[1][1]);
+                               min_coord = min_ff(min_coord, bezt->vec[2][1]);
                        }
                }
 
-               if (max_coord > FLT_EPSILON) {
-                       factor = 1.0f / max_coord;
+               range = max_coord - min_coord;
+
+               if (range > FLT_EPSILON) {
+                       factor = 1.0f / range;
                }
+               offset = -min_coord - range / 2.0f;
        }
+
+       if (r_offset) {
+               *r_offset = offset;
+       }
+
        fcu->prev_norm_factor = factor;
+       fcu->prev_offset = offset;
        return factor;
 }
 
 /* Get unit conversion factor for given ID + F-Curve */
-float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag)
+float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
 {
        if (flag & ANIM_UNITCONV_NORMALIZE) {
-               return normalization_factor_get(scene, fcu, flag);
+               return normalization_factor_get(scene, fcu, flag, r_offset);
        }
 
+       if (r_offset)
+               *r_offset = 0.0f;
+
        /* sanity checks */
        if (id && fcu && fcu->rna_path) {
                PointerRNA ptr, id_ptr;
index 9dea66adc7c49ab1e9032f992f45a11dd736874c..73f28986375bc09ee501db08bcafb9646a6a4979 100644 (file)
@@ -617,7 +617,7 @@ typedef enum eAnimUnitConv_Flags {
 short ANIM_get_normalization_flags(bAnimContext *ac);
 
 /* Get unit conversion factor for given ID + F-Curve */
-float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag);
+float ANIM_unit_mapping_get_factor(struct Scene *scene, struct ID *id, struct FCurve *fcu, short flag, float *r_offset);
 
 /* ------------- Utility macros ----------------------- */
 
index 0313ce4b1d4b2e997abe96748b82bbed9b1d3c3f..87e7cab4d1575b2b10712f12eec32f667c230083 100644 (file)
@@ -481,7 +481,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
        ChannelDriver *driver;
        float samplefreq;
        float stime, etime;
-       float unitFac;
+       float unitFac, offset;
        float dx, dy;
        short mapping_flag = ANIM_get_normalization_flags(ac);
        int i, n;
@@ -498,7 +498,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
        fcu->driver = NULL;
        
        /* compute unit correction factor */
-       unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+       unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
        
        /* Note about sampling frequency:
         *  Ideally, this is chosen such that we have 1-2 pixels = 1 segment
@@ -550,7 +550,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
        n = (etime - stime) / samplefreq + 0.5f;
        for (i = 0; i <= n; i++) {
                float ctime = stime + i * samplefreq;
-               glVertex2f(ctime, evaluate_fcurve(fcu, ctime) * unitFac);
+               glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
        }
        
        glEnd();
@@ -566,13 +566,14 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
        FPoint *fpt = prevfpt + 1;
        float fac, v[2];
        int b = fcu->totvert - 1;
-       float unit_scale;
+       float unit_scale, offset;
        short mapping_flag = ANIM_get_normalization_flags(ac);
 
        /* apply unit mapping */
        glPushMatrix();
-       unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+       unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
        glScalef(1.0f, unit_scale, 1.0f);
+       glTranslatef(0.0f, offset, 0.0f);
 
        glBegin(GL_LINE_STRIP);
        
@@ -665,14 +666,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
        float fac = 0.0f;
        int b = fcu->totvert - 1;
        int resol;
-       float unit_scale;
+       float unit_scale, offset;
        short mapping_flag = ANIM_get_normalization_flags(ac);
        
        /* apply unit mapping */
        glPushMatrix();
-       unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+       unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
        glScalef(1.0f, unit_scale, 1.0f);
-       
+       glTranslatef(0.0f, offset, 0.0f);
+
        glBegin(GL_LINE_STRIP);
        
        /* extrapolate to left? */
@@ -826,7 +828,8 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
        ChannelDriver *driver = fcu->driver;
        View2D *v2d = &ac->ar->v2d;
        short mapping_flag = ANIM_get_normalization_flags(ac);
-       float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
+       float offset;
+       float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
        
        /* for now, only show when debugging driver... */
        //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
@@ -850,10 +853,10 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
                glBegin(GL_LINES);
                {
                        t = v2d->cur.xmin;
-                       glVertex2f(t, t * unitfac);
+                       glVertex2f(t, (t + offset) * unitfac);
                        
                        t = v2d->cur.xmax;
-                       glVertex2f(t, t * unitfac); 
+                       glVertex2f(t, (t + offset) * unitfac);
                }
                glEnd();
                
@@ -1067,10 +1070,12 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
                        }
                        else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
                                short mapping_flag = ANIM_get_normalization_flags(ac);
-                               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+                               float offset;
+                               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
 
                                glPushMatrix();
                                glScalef(1.0f, unit_scale, 1.0f);
+                               glTranslatef(0.0f, offset, 0.0f);
 
                                if (fcu->bezt) {
                                        bool do_handles = draw_fcurve_handles_check(sipo, fcu);
index 0dba9ccfbae67f0c67bf0d6279742f63d82de455..80503a7897c4c6d2ce3a7fa3b928710998b6b6be 100644 (file)
@@ -109,7 +109,7 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
                        AnimData *adt = ANIM_nla_mapping_get(ac, ale);
                        FCurve *fcu = (FCurve *)ale->key_data;
                        float txmin, txmax, tymin, tymax;
-                       float unitFac;
+                       float unitFac, offset;
                        
                        /* get range */
                        if (calc_fcurve_bounds(fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles)) {
@@ -122,7 +122,9 @@ void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, floa
                                }
                                
                                /* apply unit corrections */
-                               unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+                               unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
+                               tymin += offset;
+                               tymax += offset;
                                tymin *= unitFac;
                                tymax *= unitFac;
                                
@@ -350,7 +352,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
                AnimData *adt = ANIM_nla_mapping_get(ac, ale);
                ChannelDriver *driver = fcu->driver;
                FPoint *fpt;
-               float unitFac;
+               float unitFac, offset;
                int cfra;
                SpaceIpo *sipo = (SpaceIpo *) ac->sl;
                short mapping_flag = ANIM_get_normalization_flags(ac);
@@ -359,7 +361,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
                fcu->driver = NULL;
                
                /* calculate unit-mapping factor */
-               unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+               unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
                
                /* create samples, but store them in a new curve 
                 *      - we cannot use fcurve_store_samples() as that will only overwrite the original curve 
@@ -372,7 +374,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end)
                        float cfrae = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP);
                        
                        fpt->vec[0] = cfrae;
-                       fpt->vec[1] = fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) * unitFac;
+                       fpt->vec[1] = (fcurve_samplingcb_evalcurve(fcu, NULL, cfrae) + offset) * unitFac;
                }
                
                /* set color of ghost curve 
@@ -610,7 +612,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
                ListBase anim_data;
 
                short mapping_flag = ANIM_get_normalization_flags(&ac);
-
+               float scale, offset;
                /* get frame and value from props */
                frame = RNA_float_get(op->ptr, "frame");
                val = RNA_float_get(op->ptr, "value");
@@ -620,8 +622,10 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
                frame = BKE_nla_tweakedit_remap(adt, frame, NLATIME_CONVERT_UNMAP);
                
                /* apply inverse unit-mapping to value to get correct value for F-Curves */
-               val *= ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE);
-               
+               scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, fcu, mapping_flag | ANIM_UNITCONV_RESTORE, &offset);
+
+               val = val * scale - offset;
+
                /* insert keyframe on the specified frame + value */
                insert_vert_fcurve(fcu, frame, val, 0);
                
@@ -1905,7 +1909,8 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
                AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
                short mapping_flag = ANIM_get_normalization_flags(&ac);
                KeyframeEditData current_ked;
-               float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS);
+               float offset;
+               float unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
 
                memset(&current_ked, 0, sizeof(current_ked));
 
@@ -1919,7 +1924,7 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
 
                ked.f1 += current_ked.f1;
                ked.i1 += current_ked.i1;
-               ked.f2 += current_ked.f2 * unit_scale;
+               ked.f2 += (current_ked.f2 + offset) * unit_scale;
                ked.i2 += current_ked.i2;
        }
        
@@ -2012,9 +2017,10 @@ static void snap_graph_keys(bAnimContext *ac, short mode)
                /* normalise cursor value (for normalised F-Curves display) */
                if (mode == GRAPHKEYS_SNAP_VALUE) {
                        short mapping_flag = ANIM_get_normalization_flags(ac);
-                       float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag);
+                       float offset;
+                       float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
                        
-                       ked.f1 = cursor_value / unit_scale;
+                       ked.f1 = (cursor_value / unit_scale) - offset;
                }
                
                /* perform snapping */
@@ -2139,9 +2145,10 @@ static void mirror_graph_keys(bAnimContext *ac, short mode)
                /* apply unit corrections */
                if (mode == GRAPHKEYS_MIRROR_VALUE) {
                        short mapping_flag = ANIM_get_normalization_flags(ac);
-                       float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS);
+                       float offset;
+                       float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag | ANIM_UNITCONV_ONLYKEYS, &offset);
                        
-                       ked.f1 = cursor_value * unit_scale;
+                       ked.f1 = (cursor_value + offset) * unit_scale;
                }
                
                /* perform actual mirroring */
index 2810733708455d907498ac2cd0d7f64f73237ae6..4cf8a1de7ab477e8e68ce7b033f7a05e1e22d05e 100644 (file)
@@ -272,7 +272,8 @@ static void borderselect_graphkeys(
        for (ale = anim_data.first; ale; ale = ale->next) {
                AnimData *adt = ANIM_nla_mapping_get(ac, ale);
                FCurve *fcu = (FCurve *)ale->key_data;
-               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+               float offset;
+               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
 
                /* apply NLA mapping to all the keyframes, since it's easier than trying to
                 * guess when a callback might use something different
@@ -282,8 +283,8 @@ static void borderselect_graphkeys(
 
                scaled_rectf.xmin = rectf.xmin;
                scaled_rectf.xmax = rectf.xmax;
-               scaled_rectf.ymin = rectf.ymin / unit_scale;
-               scaled_rectf.ymax = rectf.ymax / unit_scale;
+               scaled_rectf.ymin = rectf.ymin / unit_scale - offset;
+               scaled_rectf.ymax = rectf.ymax / unit_scale - offset;
 
                /* set horizontal range (if applicable) 
                 * NOTE: these values are only used for x-range and y-range but not region 
@@ -1119,7 +1120,7 @@ static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt)
 // TODO: should we return if we hit something?
 static void nearest_fcurve_vert_store(
         ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype,
-        BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale)
+        BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale, float offset)
 {
        /* Keyframes or Samples? */
        if (bezt) {
@@ -1131,7 +1132,7 @@ static void nearest_fcurve_vert_store(
                 *  'vec' matrix
                 */
                if (UI_view2d_view_to_region_clip(v2d,
-                                                 bezt->vec[hpoint + 1][0], bezt->vec[hpoint + 1][1] * unit_scale,
+                                                 bezt->vec[hpoint + 1][0], (bezt->vec[hpoint + 1][1] + offset) * unit_scale,
                                                  &screen_co[0], &screen_co[1]) &&
                    /* check if distance from mouse cursor to vert in screen space is within tolerance */
                    ((dist = len_v2v2_int(mval, screen_co)) <= GVERTSEL_TOL))
@@ -1193,7 +1194,8 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
        for (ale = anim_data.first; ale; ale = ale->next) {
                FCurve *fcu = (FCurve *)ale->key_data;
                AnimData *adt = ANIM_nla_mapping_get(ac, ale);
-               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
+               float offset;
+               float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
                
                /* apply NLA mapping to all the keyframes */
                if (adt)
@@ -1205,18 +1207,18 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
                        
                        for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
                                /* keyframe */
-                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale);
+                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale, offset);
                                
                                /* handles - only do them if they're visible */
                                if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
                                        /* first handle only visible if previous segment had handles */
                                        if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
-                                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale);
+                                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale, offset);
                                        }
                                        
                                        /* second handle only visible if this segment is bezier */
                                        if (bezt1->ipo == BEZT_IPO_BEZ) {
-                                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale);
+                                               nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale, offset);
                                        }
                                }
                        }
index 1af214b8c77cfbdd9216a0f17659b5744893cc05..f21685551a8f87513310780c1be8ea02650211d8 100644 (file)
@@ -3836,6 +3836,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
 
 typedef struct TransDataGraph {
        float unit_scale;
+       float offset;
 } TransDataGraph;
 
 /* Helper function for createTransGraphEditData, which is responsible for associating
@@ -3844,7 +3845,7 @@ typedef struct TransDataGraph {
 static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg,
                               AnimData *adt, BezTriple *bezt,
                               int bi, bool selected, bool ishandle, bool intvals,
-                              float mtx[3][3], float smtx[3][3], float unit_scale)
+                              float mtx[3][3], float smtx[3][3], float unit_scale, float offset)
 {
        float *loc = bezt->vec[bi];
        const float *cent = bezt->vec[1];
@@ -3858,26 +3859,26 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
        
        if (adt) {
                td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
-               td2d->loc[1] = loc[1] * unit_scale;
+               td2d->loc[1] = (loc[1] + offset) * unit_scale;
                td2d->loc[2] = 0.0f;
                td2d->loc2d = loc;
                
                td->loc = td2d->loc;
                td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
-               td->center[1] = cent[1] * unit_scale;
+               td->center[1] = (cent[1] + offset) * unit_scale;
                td->center[2] = 0.0f;
                
                copy_v3_v3(td->iloc, td->loc);
        }
        else {
                td2d->loc[0] = loc[0];
-               td2d->loc[1] = loc[1] * unit_scale;
+               td2d->loc[1] = (loc[1] + offset) * unit_scale;
                td2d->loc[2] = 0.0f;
                td2d->loc2d = loc;
                
                td->loc = td2d->loc;
                copy_v3_v3(td->center, cent);
-               td->center[1] *= unit_scale;
+               td->center[1] = (td->center[1] + offset) * unit_scale;
                copy_v3_v3(td->iloc, td->loc);
        }
 
@@ -3917,6 +3918,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
        copy_m3_m3(td->smtx, smtx);
 
        tdg->unit_scale = unit_scale;
+       tdg->offset = offset;
 }
 
 static bool graph_edit_is_translation_mode(TransInfo *t)
@@ -4104,7 +4106,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
                FCurve *fcu = (FCurve *)ale->key_data;
                bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
-               float unit_scale;
+               float unit_scale, offset;
                float cfra;
 
                /* F-Curve may not have any keyframes */
@@ -4119,7 +4121,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                else
                        cfra = (float)CFRA;
 
-               unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag);
+               unit_scale = ANIM_unit_mapping_get_factor(ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
 
                /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */
                for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
@@ -4135,11 +4137,11 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                        bool is_sel = (sel2 || sel1 || sel3);
                                        /* we always select all handles for proportional editing if central handle is selected */
                                        initTransDataCurveHandles(td, bezt);
-                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale);
+                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
                                        initTransDataCurveHandles(td, bezt);
-                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale);
+                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, is_sel, false, intvals, mtx, smtx, unit_scale, offset);
                                        initTransDataCurveHandles(td, bezt);
-                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale);
+                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, is_sel, true, intvals, mtx, smtx, unit_scale, offset);
                                }
                                else {
                                        /* only include handles if selected, irrespective of the interpolation modes.
@@ -4148,7 +4150,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                        if (!is_translation_mode || !(sel2)) {
                                                if (sel1) {
                                                        hdata = initTransDataCurveHandles(td, bezt);
-                                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale);
+                                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 0, sel1, true, intvals, mtx, smtx, unit_scale, offset);
                                                }
                                                else {
                                                        /* h1 = 0; */ /* UNUSED */
@@ -4157,7 +4159,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                                if (sel3) {
                                                        if (hdata == NULL)
                                                                hdata = initTransDataCurveHandles(td, bezt);
-                                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale);
+                                                       bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 2, sel3, true, intvals, mtx, smtx, unit_scale, offset);
                                                }
                                                else {
                                                        /* h2 = 0; */ /* UNUSED */
@@ -4178,7 +4180,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t)
                                                                hdata = initTransDataCurveHandles(td, bezt);
                                                }
 
-                                               bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale);
+                                               bezt_to_transdata(td++, td2d++, tdg++, adt, bezt, 1, sel2, false, intvals, mtx, smtx, unit_scale, offset);
 
                                        }
                                        /* special hack (must be done after initTransDataCurveHandles(), as that stores handle settings to restore...):
@@ -4543,16 +4545,16 @@ void flushTransGraphData(TransInfo *t)
                if (td->flag & TD_INTVALUES)
                        td2d->loc2d[1] = floorf(td2d->loc[1] + 0.5f);
                else
-                       td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale;
+                       td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
                
                if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
                        td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0];
-                       td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+                       td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset;
                }
                
                if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
                        td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0];
-                       td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale;
+                       td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale - tdg->offset;
                }
        }
 }
index 9e6b71fcbacce7798762e13f2d76f86424b1e703..693e0fc12939113a95ad0deb22ac6f8179c3f693 100644 (file)
@@ -459,7 +459,7 @@ typedef struct FCurve {
        int color_mode;                 /* coloring method to use (eFCurve_Coloring) */
        float color[3];                 /* the last-color this curve took */
 
-       float prev_norm_factor, pad;
+       float prev_norm_factor, prev_offset;
 } FCurve;