Final merge of HEAD (bf-blender) into the orange branch.
[blender.git] / source / blender / src / drawoops.c
index a0ea01ff770710bef43773a24daeeeae2fd6e2fd..dbf245179dfc91f14b46c6be6621dfb69d87c561 100644 (file)
 #include <config.h>
 #endif
 
-#ifdef _WIN32
-#include "BLI_winstuff.h"
-#endif
-
 #include "BMF_Api.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
-#include "BLI_editVert.h"
 
 #include "DNA_ID.h"
-#include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
 #include "DNA_oops_types.h"
 #include "DNA_scene_types.h"
 #include "BKE_utildefines.h"
 #include "BKE_global.h"
 
-#include "BIF_gl.h"
 #include "BIF_interface.h"
+#include "BIF_interface_icons.h"
+#include "BIF_gl.h"
 #include "BIF_glutil.h"
-#include "BIF_resources.h"
-#include "BIF_screen.h"
 #include "BIF_mywindow.h"
+#include "BIF_outliner.h"
 #include "BIF_resources.h"
+#include "BIF_screen.h"
 
 /*  #include "BIF_drawoops.h" bad name :(*/
 #include "BIF_oops.h"
@@ -75,8 +70,9 @@
 #include "BSE_drawoops.h"
 
 float oopscalex;
+struct BMF_Font *font; /* for using different sized fonts */
 
-void boundbox_oops()
+void boundbox_oops(short sel)
 {
        Oops *oops;
        float min[2], max[2];
@@ -85,13 +81,13 @@ void boundbox_oops()
        if(G.soops==0) return;
        
        min[0]= 1000.0;
-       max[0]= -10000.0;
+       max[0]= -1000.0;
        min[1]= 1000.0;
        max[1]= -1000.0;
        
        oops= G.soops->oops.first;
        while(oops) {
-               if(oops->hide==0) {
+               if ((oops->hide==0 && !sel) || (sel && oops->flag & SELECT )) {
                        ok= 1;
                        
                        min[0]= MIN2(min[0], oops->x);
@@ -131,33 +127,74 @@ void give_oopslink_line(Oops *oops, OopsLink *ol, float *v1, float *v2)
 void draw_oopslink(Oops *oops)
 {
        OopsLink *ol;
-       float vec[4];
+       float vec[4][3], dist, spline_step;
+       short curve_res;
        
        if(oops->type==ID_SCE) {
                if(oops->flag & SELECT) {
-                       if(oops->id->lib) cpack(0x4080A0);
+                       /* when using python Mesh to make meshes a file was saved
+                       that had an oops with no ID, stops a segfault when looking for lib */
+                       if(oops->id && oops->id->lib) cpack(0x4080A0);
                        else cpack(0x808080);
                }
                else cpack(0x606060);
        }
        else {
                if(oops->flag & SELECT) {
-                       if(oops->id->lib) cpack(0x11AAFF);
+                       if(oops->id && oops->id->lib) cpack(0x11AAFF);
                        else cpack(0xFFFFFF);
                }
                else cpack(0x0);
        }
        
+       glEnable(GL_MAP1_VERTEX_3);
+       vec[0][2]= vec[1][2]= vec[2][2]= vec[3][2]= 0.0; /* only 2d spline, set the Z to 0*/
+       
        ol= oops->link.first;
        while(ol) {
                if(ol->to && ol->to->hide==0) {
                        
-                       give_oopslink_line(oops, ol, vec, vec+2);
+                       give_oopslink_line(oops, ol, vec[0], vec[3]);
+                       
+                       dist= 0.5*VecLenf(vec[0], vec[3]);
+
+                       /* check ol->xof and yof for direction */
+                       if(ol->xof == 0.0) {
+                               vec[1][0]= vec[0][0]-dist;
+                               vec[1][1]= vec[0][1];
+                       }
+                       else if(ol->xof==OOPSX) {
+                               vec[1][0]= vec[0][0]+dist;
+                               vec[1][1]= vec[0][1];
+                       }
+                       else {
+                               vec[1][0]= vec[0][0];
+                               vec[1][1]= vec[0][1]+dist;
+                       }
+                       
+                       /* v3 is always pointing down */
+                       vec[2][0]= vec[3][0];
+                       vec[2][1]= vec[3][1] - dist;
+                       
+                       if( MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > G.v2d->cur.xmax); /* clipped */  
+                               else if ( MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < G.v2d->cur.xmin); /* clipped */
+                                       else {
+                                               /* calculate a curve resolution to use based on the length of the curve.*/
+                                               curve_res = MIN2(40, MAX2(2, (short)((dist*2) * (oopscalex))));
+                                               
+                                               /* we can reuse the dist variable here to increment the GL curve eval amount*/
+                                               dist = (float)1/curve_res;
+                                               spline_step = 0.0;
+                                               
+                                               glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
+                                               glBegin(GL_LINE_STRIP);
+                                               while (spline_step < 1.000001) {
+                                                       glEvalCoord1f(spline_step);
+                                                       spline_step += dist;
+                                               }
+                                               glEnd();
+                                       }
                        
-                       glBegin(GL_LINE_STRIP);
-                       glVertex2fv(vec);
-                       glVertex2fv(vec+2);
-                       glEnd();
                }
                ol= ol->next;
        }
@@ -186,8 +223,7 @@ void draw_icon_oops(float *co, short type)
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA); 
 
-       glRasterPos2f(co[0],  co[1]-0.2);
-       BIF_draw_icon(icon);
+       BIF_icon_draw(co[0], co[1]-0.2, icon);
 
        glBlendFunc(GL_ONE,  GL_ZERO); 
        glDisable(GL_BLEND);
@@ -247,7 +283,7 @@ unsigned int give_oops_color(short type, short sel, unsigned int *border)
 
 void calc_oopstext(char *str, float *v1)
 {
-       float f1, f2, size;
+       float f1, f2, size; /* f1 is the lhs of the oops block, f2 is the rhs */
        short mval[2], len, flen;
        
        ipoco_to_areaco_noclip(G.v2d, v1, mval);
@@ -255,7 +291,12 @@ void calc_oopstext(char *str, float *v1)
        v1[0]+= OOPSX;
        ipoco_to_areaco_noclip(G.v2d, v1, mval);
        f2= mval[0];
-       size= f2-f1;
+       
+       if (oopscalex>1.1) { /* Make text area wider if we have no icon.*/
+               size= f2-f1;
+       } else {
+               size= (f2-f1)*1.7; 
+       }
 
        len= strlen(str);
        
@@ -265,7 +306,16 @@ void calc_oopstext(char *str, float *v1)
                str[len]= 0;
        }
        
-       mval[0]= (f1+f2-flen+1)/2;
+       flen= BMF_GetStringWidth(font, str);
+       
+       /* calc centred location for icon and text,
+       else if were zoomed too far out, just push text to the left of the oops block. */
+       if (oopscalex>1.1) { 
+               mval[0]= (f1+f2-flen+1)/2;
+       } else {
+               mval[0]=  f1; 
+       }
+       
        mval[1]= 1;
        areamouseco_to_ipoco(G.v2d, mval, &f1, &f2);
        
@@ -298,7 +348,10 @@ void draw_oops(Oops *oops)
 
                glRectf(x1,  y1,  x2,  y2);
        }
-       if(oops->id->lib) {
+       
+       /* it has never happened that an oops was missing an ID at
+       this point but has occured elseware so lets be safe */
+       if(oops->id && oops->id->lib) { 
                if(oops->id->flag & LIB_INDIRECT) cpack(0x1144FF);
                else cpack(0x11AAFF);
 
@@ -316,13 +369,15 @@ void draw_oops(Oops *oops)
        calc_oopstext(str, v1);
 
        /* ICON */
-       if(str[1] && oopscalex>1.1) {
+       if(str[1] && oopscalex>1.1) { /* HAS ICON */
                draw_icon_oops(v1, oops->type);
-       }
-       if(oops->flag & SELECT) cpack(0xFFFFFF); 
-       else cpack(0x0);
+       } else { /* NO ICON, UNINDENT*/
+               v1[0] -= 1.3 / oopscalex;
+       }
+       if(oops->flag & SELECT) BIF_ThemeColor(TH_TEXT_HI);
+       else BIF_ThemeColor(TH_TEXT);
        glRasterPos3f(v1[0],  v1[1], 0.0);
-       BMF_DrawString(G.fonts, str);
+       BMF_DrawString(font, str);
 
        if(line) setlinestyle(2);
        cpack(border);
@@ -368,64 +423,97 @@ void draw_oops(Oops *oops)
 
 void drawoopsspace(ScrArea *sa, void *spacedata)
 {
+       SpaceOops *soops= spacedata;
        Oops *oops;
        float col[3];
-       int ofsx, ofsy;
        
        BIF_GetThemeColor3fv(TH_BACK, col);
+       
+       /* darker background for oops */
+       if(soops->type!=SO_OUTLINER) {
+               col[0] = col[0] * 0.75; col[1] = col[1] * 0.75; col[2] = col[2] * 0.75;
+       }
+       
        glClearColor(col[0], col[1], col[2], 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
-       if(G.soops==0) return;  
-
-       boundbox_oops();
-       calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
-
-       if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
-               if(G.v2d->scroll) {     
-                       ofsx= curarea->winrct.xmin;     /* because of mywin */
-                       ofsy= curarea->winrct.ymin;
-
-                       glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
-                       glScissor(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
-               }
-       }
-
-       myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
-
-       oopscalex= .14*((float)curarea->winx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
-       calc_ipogrid(); /* for scrollvariables */
-       build_oops();
-
-       oops= G.soops->oops.first;
-       while(oops) {
-               if(oops->hide==0) {
-                       draw_oopslink(oops);
+       if(soops==0) return;    
+       
+       if(soops->type==SO_OUTLINER) draw_outliner(sa, soops);
+       else {
+               build_oops();   /* changed to become first call... */
+               
+               boundbox_oops(0);
+               calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
+
+               myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
+
+               oopscalex= .14*((float)curarea->winx)/(G.v2d->cur.xmax-G.v2d->cur.xmin);
+               calc_ipogrid(); /* for scrollvariables */
+               
+               
+               /* Draw a page about the oops */
+               BIF_GetThemeColor3fv(TH_BACK, col);
+               glColor3fv(col);
+               glRectf(G.v2d->tot.xmin-2, G.v2d->tot.ymin-2,  G.v2d->tot.xmax+2, G.v2d->tot.ymax+2); /* light square in the centre */
+               BIF_ThemeColorShade(TH_BACK, -96); /* drop shadow color */
+               glRectf(G.v2d->tot.xmin-1, G.v2d->tot.ymin-2,  G.v2d->tot.xmax+3, G.v2d->tot.ymin-3); /* bottom dropshadow */
+               glRectf(G.v2d->tot.xmax+2, G.v2d->tot.ymin-2,  G.v2d->tot.xmax+3, G.v2d->tot.ymax+1); /* right hand dropshadow */
+               /* box around the oops. */
+               cpack(0x0);
+               mysbox(G.v2d->tot.xmin-2, G.v2d->tot.ymin-2,  G.v2d->tot.xmax+2, G.v2d->tot.ymax+2);
+               
+               
+               /* Set the font size for the oops based on the zoom level */
+               if (oopscalex > 6.0) font = BMF_GetFont(BMF_kScreen15);
+               else if (oopscalex > 3.5) font = G.font;
+               else if (oopscalex > 2.5) font = G.fonts;
+               else font = G.fontss;           
+               
+               /* Draw unselected oops links */
+               oops= soops->oops.first;
+               while(oops) {
+                       if(oops->hide==0 && (oops->flag & SELECT)); else {
+                               draw_oopslink(oops);
+                       }
+                       oops= oops->next;
                }
-               oops= oops->next;
-       }
-       oops= G.soops->oops.first;
-       while(oops) {
-               if(oops->hide==0) {
-                       if(oops->flag & SELECT); else draw_oops(oops);
+               
+               /* Draw selected oops links */
+               oops= soops->oops.first;
+               while(oops) {
+                       if(oops->hide==0 && (oops->flag & SELECT)) {
+                               draw_oopslink(oops);
+                       }
+                       oops= oops->next;
+               }                       
+               
+               oops= soops->oops.first;
+               while(oops) {
+                       if(oops->hide==0) {
+                               if(oops->flag & SELECT); else draw_oops(oops);
+                       }
+                       oops= oops->next;
                }
-               oops= oops->next;
-       }
-       oops= G.soops->oops.first;
-       while(oops) {
-               if(oops->hide==0) {
-                       if(oops->flag & SELECT) draw_oops(oops);
+               
+               oops= soops->oops.first;
+               while(oops) {
+                       if(oops->hide==0) {
+                               if(oops->flag & SELECT) draw_oops(oops);
+                       }
+                       oops= oops->next;
                }
-               oops= oops->next;
        }
        
        /* restore viewport */
        mywinset(curarea->win);
-
        
        /* ortho at pixel level curarea */
-       myortho2(-0.5, sa->winx-0.5, -0.5, sa->winy-0.5);
-       if(G.v2d->scroll) {     
-               drawscroll(0);          
+       myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
+
+       if(soops->type==SO_OUTLINER) {
+               if(sa->winx>SCROLLB+10 && sa->winy>SCROLLH+10) {
+                       if(G.v2d->scroll) drawscroll(0);                
+               }
        }
        draw_area_emboss(sa);