View2D - Bugfixes
authorJoshua Leung <aligorith@gmail.com>
Wed, 10 Dec 2008 09:07:15 +0000 (09:07 +0000)
committerJoshua Leung <aligorith@gmail.com>
Wed, 10 Dec 2008 09:07:15 +0000 (09:07 +0000)
Fixed a few typos in View2D code, which included the zoom-locking flags not being checked for correctly by the zoom operators.

This commit does NOT fix the problems with the Outliner 'cur' rect expanding/contracting as the view changes size. I still haven't found the cause of this, but it might be related to the off-by-1 errors with UI-widgets that brecht noted in TimeLine header...

source/blender/editors/include/UI_view2d.h
source/blender/editors/interface/view2d.c
source/blender/editors/interface/view2d_ops.c

index a8640bcc1d226f8e032f16a80edd97bca2f947c9..757f38aba1eb671d9d0e513677d5efc21ca4e3e4 100644 (file)
@@ -89,10 +89,9 @@ typedef struct View2DScrollers View2DScrollers;
 
 /* refresh and validation (of view rects) */
 void UI_view2d_size_update(struct View2D *v2d, int winx, int winy);
-void UI_view2d_status_enforce(struct View2D *v2d);
-
-void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
+void UI_view2d_curRect_validate(struct View2D *v2d);
 void UI_view2d_curRect_reset(struct View2D *v2d);
+void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
 
 /* view matrix operations */
 void UI_view2d_view_ortho(const struct bContext *C, struct View2D *v2d);
index 379716a03dbef49a68fee2ae4274aec7693957d3..c3544f20a1559c3f4c6707ff2d9d078015f0d9d8 100644 (file)
@@ -78,7 +78,7 @@ void UI_view2d_size_update(View2D *v2d, int winx, int winy)
                else if (v2d->scroll & V2D_SCROLL_RIGHT) {
                        /* on right-hand edge of region */
                        v2d->vert= v2d->mask;
-                       v2d->vert.xmin= v2d->vert.xmax-V2D_SCROLL_WIDTH;
+                       v2d->vert.xmin= v2d->vert.xmax - V2D_SCROLL_WIDTH;
                        v2d->mask.xmax= v2d->vert.xmin;
                }
                
@@ -92,7 +92,7 @@ void UI_view2d_size_update(View2D *v2d, int winx, int winy)
                else if (v2d->scroll & V2D_SCROLL_TOP) {
                        /* on upper edge of region */
                        v2d->hor= v2d->mask;
-                       v2d->hor.ymin= v2d->hor.ymax-V2D_SCROLL_HEIGHT;
+                       v2d->hor.ymin= v2d->hor.ymax - V2D_SCROLL_HEIGHT;
                        v2d->mask.ymax= v2d->hor.ymin;
                }
        }
@@ -102,17 +102,16 @@ void UI_view2d_size_update(View2D *v2d, int winx, int winy)
  *     - cur is not allowed to be: larger than max, smaller than min, or outside of tot
  */
 // XXX pre2.5 -> this used to be called  test_view2d()
-// XXX FIXME - this is an old mess function... let's rewrite!
-void UI_view2d_status_enforce(View2D *v2d)
+void UI_view2d_curRect_validate(View2D *v2d)
 {
        /* cur is not allowed to be larger than max, smaller than min, or outside of tot */
        float totwidth, totheight, curwidth, curheight, width, height;
-       int winx, winy;
+       float winx, winy;
        rctf *cur, *tot;
        
        /* use mask as size of region that View2D resides in, as it takes into account scrollbars already  */
-       winx= v2d->mask.xmax - v2d->mask.xmin + 1;
-       winy= v2d->mask.ymax - v2d->mask.ymin + 1;
+       winx= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
+       winy= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
        
        /* get pointers to rcts for less typing */
        cur= &v2d->cur;
@@ -122,7 +121,7 @@ void UI_view2d_status_enforce(View2D *v2d)
         *      - cur must not fall outside of tot
         *      - axis locks (zoom and offset) must be maintained
         *      - zoom must not be excessive (check either sizes or zoom values)
-        *      - aspect ratio should be respected
+        *      - aspect ratio should be respected (NOTE: this is quite closely realted to zoom too)
         */
        
        /* Step 1: if keepzoom, adjust the sizes of the rects only
@@ -136,9 +135,9 @@ void UI_view2d_status_enforce(View2D *v2d)
        
        /* if zoom is locked, size on the appropriate axis is reset to mask size */
        if (v2d->keepzoom & V2D_LOCKZOOM_X)
-               width= (float)winy;
+               width= winx;
        if (v2d->keepzoom & V2D_LOCKZOOM_Y)
-               height= (float)winx;
+               height= winy;
                
        /* keepzoom (V2D_KEEPZOOM set), indicates that zoom level on each axis must not exceed limits 
         * NOTE: in general, it is not expected that the lock-zoom will be used in conjunction with this
@@ -147,14 +146,14 @@ void UI_view2d_status_enforce(View2D *v2d)
                float zoom, fac;
                
                /* check if excessive zoom on x-axis */
-               zoom= (float)winx / width;
+               zoom= winx / width;
                if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
                        fac= (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
                        width *= fac;
                }
                
                /* check if excessive zoom on y-axis */
-               zoom= (float)winy / height;
+               zoom= winy / height;
                if ((zoom < v2d->minzoom) || (zoom > v2d->maxzoom)) {
                        fac= (zoom < v2d->minzoom) ? (zoom / v2d->minzoom) : (zoom / v2d->maxzoom);
                        height *= fac;
@@ -171,16 +170,14 @@ void UI_view2d_status_enforce(View2D *v2d)
                short do_x=0, do_y=0, do_cur, do_win;
                float curRatio, winRatio;
                
-                       // XXX this is old code here to be cleaned up still
                /* when a window edge changes, the aspect ratio can't be used to
                 * find which is the best new 'cur' rect. thats why it stores 'old' 
                 */
                if (winx != v2d->oldwinx) do_x= 1;
                if (winy != v2d->oldwiny) do_y= 1;
                
-               /* here dx is cur ratio, while dy is win ratio */
                curRatio= height / width;
-               winRatio= ((float)winy) / ((float)winx);
+               winRatio= winy / winx;
                
                /* both sizes change (area/region maximised)  */
                if (do_x == do_y) {
@@ -233,20 +230,19 @@ void UI_view2d_status_enforce(View2D *v2d)
                float temp, dh;
                
                /* resize around 'center' of frame */
-               // FIXME: maybe we should just scale down on min?
                if (width != curwidth) {
-                       temp= (cur->xmax + cur->xmin) / 2.0f;
-                       dh= (width - curwidth) * 0.5f;
+                       temp= (cur->xmax + cur->xmin) * 0.5f;
+                       dh= width * 0.5f;
                        
-                       cur->xmin -= dh;
-                       cur->xmax += dh;
+                       cur->xmin = temp - dh;
+                       cur->xmax = temp + dh;
                }
                if (height != curheight) {
-                       temp= (cur->ymax + cur->ymin) / 2.0f;
-                       dh= (height - curheight) * 0.5f;
+                       temp= (cur->ymax + cur->ymin) * 0.5f;
+                       dh= height * 0.5f;
                        
-                       cur->ymin -= dh;
-                       cur->ymax += dh;
+                       cur->ymin = temp - dh;
+                       cur->ymax = temp + dh;
                }
        }
        
@@ -284,6 +280,7 @@ void UI_view2d_status_enforce(View2D *v2d)
                                temp= cur->xmax - tot->xmax;
                                
                                if ((cur->xmin - temp) < tot->xmin) {
+                                       /* only offset by difference from cur-min and tot-min */
                                        temp= cur->xmin - tot->xmin;
                                        
                                        cur->xmin -= temp;
@@ -342,7 +339,7 @@ void UI_view2d_status_enforce(View2D *v2d)
                                cur->ymax += temp;
                        }
                        else if (cur->ymax > tot->ymax) {
-                               /* there's still space remaining, so shift up */
+                               /* there's still space remaining, so shift down */
                                temp= cur->ymax - tot->ymax;
                                
                                cur->ymin -= temp;
@@ -354,101 +351,101 @@ void UI_view2d_status_enforce(View2D *v2d)
 
 /* ------------------ */
 
-/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
-void UI_view2d_totRect_set(View2D *v2d, int width, int height)
+/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot) */
+void UI_view2d_curRect_reset (View2D *v2d)
 {
-       /* don't do anything if either value is 0 */
-       if (ELEM3(0, v2d, width, height))
-               return;
-               
+       float width, height;
+       
+       /* assume width and height of 'cur' rect by default, should be same size as mask */
+       width= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
+       height= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
+       
        /* handle width - posx and negx flags are mutually exclusive, so watch out */
        if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
                /* width is in negative-x half */
-               v2d->tot.xmin= (float)-width;
-               v2d->tot.xmax= 0.0f;
+               v2d->cur.xmin= (float)-width;
+               v2d->cur.xmax= 0.0f;
        }
        else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
                /* width is in positive-x half */
-               v2d->tot.xmin= 0.0f;
-               v2d->tot.xmax= (float)width;
+               v2d->cur.xmin= 0.0f;
+               v2d->cur.xmax= (float)width;
        }
        else {
                /* width is centered around x==0 */
                const float dx= (float)width / 2.0f;
                
-               v2d->tot.xmin= -dx;
-               v2d->tot.xmax= dx;
+               v2d->cur.xmin= -dx;
+               v2d->cur.xmax= dx;
        }
        
        /* handle height - posx and negx flags are mutually exclusive, so watch out */
        if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
                /* height is in negative-y half */
-               v2d->tot.ymin= (float)-height;
-               v2d->tot.ymax= 0.0f;
+               v2d->cur.ymin= (float)-height;
+               v2d->cur.ymax= 0.0f;
        }
        else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
                /* height is in positive-y half */
-               v2d->tot.ymin= 0.0f;
-               v2d->tot.ymax= (float)height;
+               v2d->cur.ymin= 0.0f;
+               v2d->cur.ymax= (float)height;
        }
        else {
                /* height is centered around y==0 */
                const float dy= (float)height / 2.0f;
                
-               v2d->tot.ymin= -dy;
-               v2d->tot.ymax= dy;
+               v2d->cur.ymin= -dy;
+               v2d->cur.ymax= dy;
        }
-       
-       /* make sure that 'cur' rect is in a valid state as a result of these changes */
-       UI_view2d_status_enforce(v2d);
 }
 
-/* Restore 'cur' rect to standard orientation (i.e. optimal maximum view of tot) */
-void UI_view2d_curRect_reset (View2D *v2d)
+/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
+void UI_view2d_totRect_set (View2D *v2d, int width, int height)
 {
-       float width, height;
-       
-       /* assume width and height of 'cur' rect by default, should be same size as mask */
-       width= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
-       height= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
+       /* don't do anything if either value is 0 */
+       if (ELEM3(0, v2d, width, height))
+               return;
        
        /* handle width - posx and negx flags are mutually exclusive, so watch out */
        if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
                /* width is in negative-x half */
-               v2d->cur.xmin= (float)-width;
-               v2d->cur.xmax= 0.0f;
+               v2d->tot.xmin= (float)-width;
+               v2d->tot.xmax= 0.0f;
        }
        else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
                /* width is in positive-x half */
-               v2d->cur.xmin= 0.0f;
-               v2d->cur.xmax= (float)width;
+               v2d->tot.xmin= 0.0f;
+               v2d->tot.xmax= (float)width;
        }
        else {
                /* width is centered around x==0 */
                const float dx= (float)width / 2.0f;
                
-               v2d->cur.xmin= -dx;
-               v2d->cur.xmax= dx;
+               v2d->tot.xmin= -dx;
+               v2d->tot.xmax= dx;
        }
        
        /* handle height - posx and negx flags are mutually exclusive, so watch out */
        if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
                /* height is in negative-y half */
-               v2d->cur.ymin= (float)-height;
-               v2d->cur.ymax= 0.0f;
+               v2d->tot.ymin= (float)-height;
+               v2d->tot.ymax= 0.0f;
        }
        else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
                /* height is in positive-y half */
-               v2d->cur.ymin= 0.0f;
-               v2d->cur.ymax= (float)height;
+               v2d->tot.ymin= 0.0f;
+               v2d->tot.ymax= (float)height;
        }
        else {
                /* height is centered around y==0 */
                const float dy= (float)height / 2.0f;
                
-               v2d->cur.ymin= -dy;
-               v2d->cur.ymax= dy;
+               v2d->tot.ymin= -dy;
+               v2d->tot.ymax= dy;
        }
+       
+       /* make sure that 'cur' rect is in a valid state as a result of these changes */
+       UI_view2d_curRect_validate(v2d);
 }
 
 /* *********************************************************************** */
index 1951fc3ecd6c7aff5a10979171b59247710e6963..42b7515e2075ce0ab5af71fb4ce8f673792c8383 100644 (file)
@@ -161,7 +161,7 @@ static void view_pan_apply(bContext *C, wmOperator *op)
        }
        
        /* validate that view is in valid configuration after this operation */
-       UI_view2d_status_enforce(v2d);
+       UI_view2d_curRect_validate(v2d);
        
        /* request updates to be done... */
        WM_event_add_notifier(C, WM_NOTE_AREA_REDRAW, 0, NULL);
@@ -452,6 +452,24 @@ void ED_View2D_OT_view_scrollup(wmOperatorType *ot)
 
 /* ------------------ 'Shared' stuff ------------------------ */
  
+/* check if step-zoom can be applied */
+static short view_zoomstep_ok(bContext *C)
+{
+       View2D *v2d;
+       
+       /* check if there's a region in context to work with */
+       if (C->region == NULL)
+               return 0;
+       v2d= &C->region->v2d;
+       
+       /* check that 2d-view is zoomable */
+       if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
+               return 0;
+               
+       /* view is zoomable */
+       return 1;
+}
 /* apply transform to view (i.e. adjust 'cur' rect) */
 static void view_zoomstep_apply(bContext *C, wmOperator *op)
 {
@@ -463,17 +481,17 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
        dy= (v2d->cur.ymax - v2d->cur.ymin) * (float)RNA_float_get(op->ptr, "zoomfacy");
        
        /* only move view on an axis if change is allowed */
-       if ((v2d->keepofs & V2D_LOCKOFS_X)==0) {
+       if ((v2d->keepzoom & V2D_LOCKOFS_X)==0) {
                v2d->cur.xmin += dx;
                v2d->cur.xmax -= dx;
        }
-       if ((v2d->keepofs & V2D_LOCKOFS_Y)==0) {
+       if ((v2d->keepzoom & V2D_LOCKOFS_Y)==0) {
                v2d->cur.ymin += dy;
                v2d->cur.ymax -= dy;
        }
        
        /* validate that view is in valid configuration after this operation */
-       UI_view2d_status_enforce(v2d);
+       UI_view2d_curRect_validate(v2d);
        
        /* request updates to be done... */
        WM_event_add_notifier(C, WM_NOTE_AREA_REDRAW, 0, NULL);
@@ -486,7 +504,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
 static int view_zoomin_exec(bContext *C, wmOperator *op)
 {
        /* check that there's an active region, as View2D data resides there */
-       if (C->region == NULL)
+       if (!view_zoomstep_ok(C))
                return OPERATOR_CANCELLED;
        
        /* set RNA-Props - zooming in by uniform factor */
@@ -524,7 +542,7 @@ void ED_View2D_OT_view_zoomin(wmOperatorType *ot)
 static int view_zoomout_exec(bContext *C, wmOperator *op)
 {
        /* check that there's an active region, as View2D data resides there */
-       if (C->region == NULL)
+       if (!view_zoomstep_ok(C))
                return OPERATOR_CANCELLED;
        
        /* set RNA-Props - zooming in by uniform factor */
@@ -582,20 +600,23 @@ typedef struct v2dViewZoomData {
 static int view_zoomdrag_init(bContext *C, wmOperator *op)
 {
        v2dViewZoomData *vzd;
-       ARegion *ar;
        View2D *v2d;
        
        /* regions now have v2d-data by default, so check for region */
        if (C->region == NULL)
                return 0;
-       ar= C->region;
+       v2d= &C->region->v2d;
+       
+       /* check that 2d-view is zoomable */
+       if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
+               return 0;
        
        /* set custom-data for operator */
        vzd= MEM_callocN(sizeof(v2dViewZoomData), "v2dViewZoomData");
        op->customdata= vzd;
        
        /* set pointers to owners */
-       vzd->v2d= v2d= &ar->v2d;
+       vzd->v2d= v2d;
        
        return 1;
 }
@@ -612,17 +633,17 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
        dy= RNA_float_get(op->ptr, "deltay");
        
        /* only move view on an axis if change is allowed */
-       if ((v2d->keepofs & V2D_LOCKZOOM_X)==0) {
+       if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
                v2d->cur.xmin += dx;
                v2d->cur.xmax -= dx;
        }
-       if ((v2d->keepofs & V2D_LOCKZOOM_Y)==0) {
+       if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
                v2d->cur.ymin += dy;
                v2d->cur.ymax -= dy;
        }
        
        /* validate that view is in valid configuration after this operation */
-       UI_view2d_status_enforce(v2d);
+       UI_view2d_curRect_validate(v2d);
        
        /* request updates to be done... */
        WM_event_add_notifier(C, WM_NOTE_AREA_REDRAW, 0, NULL);
@@ -993,7 +1014,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
        }
        
        /* validate that view is in valid configuration after this operation */
-       UI_view2d_status_enforce(v2d);
+       UI_view2d_curRect_validate(v2d);
        
        /* request updates to be done... */
        WM_event_add_notifier(C, WM_NOTE_AREA_REDRAW, 0, NULL);