diff options
author | Ton Roosendaal <ton@blender.org> | 2004-10-03 17:49:54 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-10-03 17:49:54 +0400 |
commit | 3a840670a52701e8690a5d201bcb57eac45e2c8a (patch) | |
tree | 0341f7c09a337d8d43d0fca51376314476ac2905 /source/blender/src/interface.c | |
parent | 6e4b9ad96b3894e432a1561d1902f656aaa799c0 (diff) |
Lots of small changes, all for UI in Blender;
----- Killed UI frontbuffer draw
The interface toolkit was drawing all live updates (while using menus/buttons)
in the frontbuffer. This isn't well supported cross-platform, so time to be
killed once. Now it uses *only* glReadPixels and glCopyPixels for frontbuffer
access.
Live updates or menus now are drawn in backbuffer always, and copied to
front when needed.
NOTE: it was tested, but needs thorough review! On PC systems I suspects
backbuffer selection to screw up (check!). On SGI/SUN workstations it
should work smooth; but I need evidence
----- Smaller fixes;
- AA fonts were garbled on ATI systems. Now the AA fonts are drawn exact
on pixel positions. Needs the new FTGL libb too, patch is on maillist
- Rounded theme uses antialiased outlines
- Pulldown and popup menus have nice softshadow now
- New button type 'PULLDOWN', thats the one that callsup a pulldown menu.
Should be added to themes, as is the full menu/pulldown drawing
- Screendump for 1 window does the full window now, including header
- Empty pulldowns (for example running blender without scripts) give no
drawing error anymore
For review & fun;
- added curved lines as connectors, for Oops window
Diffstat (limited to 'source/blender/src/interface.c')
-rw-r--r-- | source/blender/src/interface.c | 442 |
1 files changed, 260 insertions, 182 deletions
diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 635df026e11..3e791702958 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -146,8 +146,8 @@ void ui_graphics_to_window(int win, float *x, float *y) /* for rectwrite */ gx= *x; gy= *y; - *x= sx + getsizex*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0])); - *y= sy + getsizey*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1])); + *x= ((float)sx) + ((float)getsizex)*(0.5+ 0.5*(gx*UIwinmat[0][0]+ gy*UIwinmat[1][0]+ UIwinmat[3][0])); + *y= ((float)sy) + ((float)getsizey)*(0.5+ 0.5*(gx*UIwinmat[0][1]+ gy*UIwinmat[1][1]+ UIwinmat[3][1])); } @@ -159,13 +159,13 @@ void ui_window_to_graphics(int win, float *x, float *y) /* for mouse cursor */ bwin_getsize(win, &getsizex, &getsizey); - a= .5*getsizex*UIwinmat[0][0]; - b= .5*getsizex*UIwinmat[1][0]; - c= .5*getsizex*(1.0+UIwinmat[3][0]); + a= .5*((float)getsizex)*UIwinmat[0][0]; + b= .5*((float)getsizex)*UIwinmat[1][0]; + c= .5*((float)getsizex)*(1.0+UIwinmat[3][0]); - d= .5*getsizey*UIwinmat[0][1]; - e= .5*getsizey*UIwinmat[1][1]; - f= .5*getsizey*(1.0+UIwinmat[3][1]); + d= .5*((float)getsizey)*UIwinmat[0][1]; + e= .5*((float)getsizey)*UIwinmat[1][1]; + f= .5*((float)getsizey)*(1.0+UIwinmat[3][1]); px= *x; py= *y; @@ -178,107 +178,193 @@ void ui_window_to_graphics(int win, float *x, float *y) /* for mouse cursor */ /* ************* SAVE UNDER ************ */ +/* new method: + +OverDraw *ui_begin_overdraw(int minx, int miny, int maxx, int maxy); +- enforces mainwindow to become active +- grabs copy from frontbuffer, pastes in back + +void ui_flush_overdraw(OverDraw *od); +- copies backbuffer to front + +void ui_refresh_overdraw(Overdraw *od); +- pastes in back copy of frontbuffer again for fresh drawing + +void ui_end_overdraw(OverDraw *od); +- puts back on frontbuffer saved image +- frees copy +- sets back active blender area +- signals backbuffer to be corrupt (sel buffer!) + +*/ + +/* frontbuffer updates now glCopyPixels too, with block->flush rect */ + +/* new idea for frontbuffer updates: + +- hilites: with blended poly? + +- full updates... thats harder, but: + - copy original + - before draw, always paste to backbuf + - flush + - always end with redraw event for full update + +*/ + typedef struct { short x, y, sx, sy, oldwin; - int oldcursor; unsigned int *rect; -} uiSaveUnder; +} uiOverDraw; -static void ui_paste_under(uiSaveUnder *su) +static uiOverDraw *ui_begin_overdraw(int minx, int miny, int maxx, int maxy) { + uiOverDraw *od=NULL; - if(su) { - glDisable(GL_DITHER); - glRasterPos2f( su->x, su->y ); - glDrawPixels(su->sx, su->sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect); - glEnable(GL_DITHER); + // dirty patch removed for sun and sgi to mywindow.c commented out + + /* clip with actual window size */ + if(minx < 0) minx= 0; + if(miny < 0) miny= 0; + if(maxx >= G.curscreen->sizex) maxx= G.curscreen->sizex-1; + if(maxy >= G.curscreen->sizey) maxy= G.curscreen->sizey-1; - if(su->oldwin) { - mywinset(su->oldwin); - if (su->oldcursor) { - set_cursor(su->oldcursor); - } - } + if(minx<maxx && miny<maxy) { + od= MEM_callocN(sizeof(uiOverDraw), "overdraw"); - MEM_freeN(su->rect); - MEM_freeN(su); + od->x= minx; + od->y= miny; + od->sx= maxx-minx; + od->sy= maxy-miny; + od->rect= MEM_mallocN(od->sx*od->sy*4, "temp_frontbuffer_image"); + + od->oldwin= mywinget(); + mywinset(G.curscreen->mainwin); + /* grab front */ + glReadBuffer(GL_FRONT); + glReadPixels(od->x, od->y, od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect); + glReadBuffer(GL_BACK); + /* paste in back */ + glDisable(GL_DITHER); + glRasterPos2f(od->x, od->y); + glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect); + glEnable(GL_DITHER); } + + return od; } - -static uiSaveUnder *ui_save_under(int x, int y, int sx, int sy) +static void ui_flush_overdraw(uiOverDraw *od) { - uiSaveUnder *su=NULL; - - if(sx>1 && sy>1) { - - su= MEM_callocN(sizeof(uiSaveUnder), "save under"); - - su->rect= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image"); - su->x= x; - su->y= y; - su->sx= sx; - su->sy= sy; - glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, su->rect); - } - - return su; -} + if(od==NULL) return; + glDisable(GL_DITHER); + glDrawBuffer(GL_FRONT); + glRasterPos2s(od->x, od->y); + glCopyPixels(od->x, od->y, od->sx, od->sy, GL_COLOR); + glEnable(GL_DITHER); + glFlush(); + glDrawBuffer(GL_BACK); +} -static uiSaveUnder *ui_bgnpupdraw(int startx, int starty, int endx, int endy, int cursor) +static void ui_end_overdraw(uiOverDraw *od) { - uiSaveUnder *su; - short oldwin; + if(od==NULL) return; - #if defined(__sgi) || defined(__sun) || defined(__sun__) || defined (__sparc) || defined (__sparc__) + glDisable(GL_DITHER); - /* this is a dirty patch: gets sometimes the backbuffer */ - my_get_frontbuffer_image(0, 0, 1, 1); - my_put_frontbuffer_image(); - #endif + // clear in back + glRasterPos2s(od->x, od->y); + glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect); - oldwin= mywinget(); + // clear in front + glDrawBuffer(GL_FRONT); + glRasterPos2s(od->x, od->y); + glDrawPixels(od->sx, od->sy, GL_RGBA, GL_UNSIGNED_BYTE, od->rect); - mywinset(G.curscreen->mainwin); - - /* tinsy bit larger, 1 pixel on the edge */ + glFlush(); + glDrawBuffer(GL_BACK); + glEnable(GL_DITHER); - glReadBuffer(GL_FRONT); - glDrawBuffer(GL_FRONT); + if(od->oldwin) mywinset(od->oldwin); - /* for geforce and other cards */ - glFlush(); + MEM_freeN(od->rect); + MEM_freeN(od); - su= ui_save_under(startx-1, starty-1, endx-startx+2, endy-starty+6); - if(su) su->oldwin= oldwin; - - if(su && cursor) { - su->oldcursor= get_cursor(); - set_cursor(CURSOR_STD); - } + markdirty_all_back(); // sets flags only - return su; + /* todo; backbuffer selection redraw */ } -static void ui_endpupdraw(uiSaveUnder *su) +/* ****************** live updates for hilites and button presses *********** */ + +void ui_block_flush_back(uiBlock *block) { + int minx, miny, sizex, sizey; + + /* note; this routine also has to work for block loop */ + if(block->frontbuf==0) return; - /* for geforce and other cards */ + /* copy pixels works on window coords, so we move to window space */ - glReadBuffer(GL_FRONT); - glDrawBuffer(GL_FRONT); - - glFlush(); + ui_graphics_to_window(block->win, &block->flush.xmin, &block->flush.ymin); + ui_graphics_to_window(block->win, &block->flush.xmax, &block->flush.ymax); + minx= floor(block->flush.xmin); + miny= floor(block->flush.ymin); + sizex= ceil(block->flush.xmax-block->flush.xmin); + sizey= ceil(block->flush.ymax-block->flush.ymin); - if(su) { - ui_paste_under(su); + if(sizex>0 && sizey>0) { + glPushMatrix(); + mywinset(G.curscreen->mainwin); + + glDisable(GL_DITHER); + glDrawBuffer(GL_FRONT); + glRasterPos2i(minx, miny); + glCopyPixels(minx, miny, sizex, sizey, GL_COLOR); + glEnable(GL_DITHER); + glFlush(); + glDrawBuffer(GL_BACK); + + mywinset(block->win); + glPopMatrix(); + + markdirty_win_back(block->win); } - glReadBuffer(GL_BACK); - glDrawBuffer(GL_BACK); + + block->frontbuf= 0; } +/* merge info for live updates in frontbuf */ +void ui_block_set_flush(uiBlock *block, uiBut *but) +{ + /* clear signal */ + if(but==NULL) { + block->frontbuf= 0; + + block->flush.xmin= 0.0; + block->flush.xmax= 0.0; + } + else { + if(block->frontbuf==0) { + /* first rect */ + block->flush.xmin= but->x1; + block->flush.xmax= but->x2; + block->flush.ymin= but->y1; + block->flush.ymax= but->y2; + } + else { + /* union of rects */ + if(block->flush.xmin > but->x1) block->flush.xmin= but->x1; + if(block->flush.xmax < but->x2) block->flush.xmax= but->x2; + if(block->flush.ymin > but->y1) block->flush.ymin= but->y1; + if(block->flush.ymax < but->y2) block->flush.ymax= but->y2; + } + block->frontbuf= UI_HAS_DRAWN; + + } +} /* ******************* block calc ************************* */ @@ -365,20 +451,27 @@ static void ui_positionblock(uiBlock *block, uiBut *but) block->parentrct= butrct; // will use that for pulldowns later /* calc block rect */ - block->minx= block->miny= 10000; - block->maxx= block->maxy= -10000; - - bt= block->buttons.first; - while(bt) { - if(bt->x1 < block->minx) block->minx= bt->x1; - if(bt->y1 < block->miny) block->miny= bt->y1; - - if(bt->x2 > block->maxx) block->maxx= bt->x2; - if(bt->y2 > block->maxy) block->maxy= bt->y2; + if(block->buttons.first) { + block->minx= block->miny= 10000; + block->maxx= block->maxy= -10000; - bt= bt->next; + bt= block->buttons.first; + while(bt) { + if(bt->x1 < block->minx) block->minx= bt->x1; + if(bt->y1 < block->miny) block->miny= bt->y1; + + if(bt->x2 > block->maxx) block->maxx= bt->x2; + if(bt->y2 > block->maxy) block->maxy= bt->y2; + + bt= bt->next; + } } - + else { + /* we're nice and allow empty blocks too */ + block->minx= block->miny= 0; + block->maxx= block->maxy= 20; + } + ui_graphics_to_window(block->win, &block->minx, &block->miny); ui_graphics_to_window(block->win, &block->maxx, &block->maxy); @@ -599,14 +692,6 @@ static void ui_draw_linkline(uiBut *but, uiLinkLine *line) if(line->from==NULL || line->to==NULL) return; - if(but->block->frontbuf==UI_NEED_DRAW_FRONT) { - but->block->frontbuf= UI_HAS_DRAW_FRONT; - - glDrawBuffer(GL_FRONT); - if(but->win==curarea->headwin) curarea->head_swap= WIN_FRONT_OK; - else curarea->win_swap= WIN_FRONT_OK; - } - vec1[0]= (line->from->x1+line->from->x2)/2.0; vec1[1]= (line->from->y1+line->from->y2)/2.0; vec2[0]= (line->to->x1+line->to->x2)/2.0; @@ -926,7 +1011,12 @@ static int ui_do_but_MENU(uiBut *but) /* and lets go */ block->direction= UI_TOP; ui_positionblock(block, but); + + /* blocks can come (and get scaled) from a normal window, now we go to screenspace */ block->win= G.curscreen->mainwin; + for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win; + bwin_getsinglematrix(block->win, block->winmat); + event= uiDoBlocks(&listb, 0); menudata_free(md); @@ -1032,7 +1122,7 @@ static int ui_do_but_BUT(uiBut *but) if (but->flag != oflag) { ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); } PIL_sleep_ms(10); @@ -1181,7 +1271,7 @@ static int ui_do_but_TEX(uiBut *but) BLI_strncpy(backstr, but->poin, UI_MAX_DRAW_STR); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); while (get_mbut() & L_MOUSE) BIF_wait_for_statechange(); len= strlen(str); @@ -1274,10 +1364,11 @@ static int ui_do_but_TEX(uiBut *but) } } + if(dodraw) { ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); } } @@ -1364,7 +1455,7 @@ static int ui_do_but_NUM(uiBut *but) but->flag |= UI_SELECT; ui_draw_but(but); - glFlush(); // flush display before subloop + ui_block_flush_back(but->block); uiGetMouse(mywinget(), mval); value= ui_get_but_val(but); @@ -1422,8 +1513,8 @@ static int ui_do_but_NUM(uiBut *but) ui_set_but_val(but, (double)temp); ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops - + ui_block_flush_back(but->block); + uibut_do_func(but); } } @@ -1446,7 +1537,7 @@ static int ui_do_but_NUM(uiBut *but) ui_set_but_val(but, tempf); ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); } } @@ -1494,7 +1585,7 @@ static int ui_do_but_NUM(uiBut *but) but->flag &= ~UI_SELECT; ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); uibut_do_func(but); @@ -1724,7 +1815,7 @@ static int ui_do_but_SLI(uiBut *but) ui_set_but_val(but, tempf); ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); if(but->a1) { /* color number */ uiBut *bt= but->prev; @@ -1776,7 +1867,7 @@ static int ui_do_but_SLI(uiBut *but) } ui_check_but(but); ui_draw_but(but); - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); return but->retval; } @@ -1847,7 +1938,7 @@ static int ui_do_but_BLOCK(uiBut *but) ui_positionblock(block, but); block->flag |= UI_BLOCK_LOOP; - /* blocks can come from a normal window, but we go to screenspace */ + /* blocks can come (and get scaled) from a normal window, now we go to screenspace */ block->win= G.curscreen->mainwin; for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win; bwin_getsinglematrix(block->win, block->winmat); @@ -2150,7 +2241,8 @@ static void do_palette_cb(void *bt1, void *col1) for (but= but1->block->buttons.first; but; but= but->next) { ui_draw_but(but); } - glFlush(); // flush display in subloops + but= but1->block->buttons.first; + ui_block_flush_back(but->block); } /* bt1 is num but, col1 is pointer to original color */ @@ -2175,8 +2267,10 @@ static void do_palette1_cb(void *bt1, void *col1) for (but= but1->block->buttons.first; but; but= but->next) { ui_draw_but(but); } + + but= but1->block->buttons.first; + ui_block_flush_back(but->block); - glFlush(); // flush display in subloops } /* color picker, Gimp version. mode: 'f' = floating panel, 'p' = popup */ @@ -2249,6 +2343,7 @@ void uiBlockPickerButtons(uiBlock *block, float *col, float *hsv, float *old, ch static int ui_do_but_COL(uiBut *but) { uiBlock *block; + uiBut *bt; ListBase listb={NULL, NULL}; float hsv[3], old[3], *poin= NULL, colstore[3]; short event; @@ -2278,7 +2373,12 @@ static int ui_do_but_COL(uiBut *but) /* and lets go */ block->direction= UI_TOP; ui_positionblock(block, but); + + /* blocks can come from a normal window, but we go to screenspace */ block->win= G.curscreen->mainwin; + for(bt= block->buttons.first; bt; bt= bt->next) bt->win= block->win; + bwin_getsinglematrix(block->win, block->winmat); + event= uiDoBlocks(&listb, 0); if(but->pointype==CHA) ui_set_but_vectorf(but, colstore); @@ -2338,7 +2438,7 @@ static int ui_do_but_HSVCUBE(uiBut *but) for (bt= but->block->buttons.first; bt; bt= bt->next) { ui_draw_but(bt); } - glFlush(); // flush display in subloops + ui_block_flush_back(but->block); } else BIF_wait_for_statechange(); } @@ -2455,7 +2555,7 @@ static void edit_but(uiBlock *block, uiBut *but, uiEvent *uevent) but->y2 += dy; ui_draw_but(but); - glFlush(); + ui_block_flush_back(but->block); didit= 1; but->rt[3]= 1; @@ -2563,6 +2663,7 @@ static int ui_do_button(uiBlock *block, uiBut *but, uiEvent *uevent) break; case BLOCK: + case PULLDOWN: if(uevent->val) { retval= ui_do_but_BLOCK(but); if(block->auto_open==0) block->auto_open= 1; @@ -2683,31 +2784,9 @@ static void ui_do_active_linklines(uiBlock *block, short *mval) } } - /* check for a 'found one' to prevent going to 'frontbuffer' mode. - this slows done gfx quite some, and at OSX the 'finish' forces a swapbuffer */ + /* no frontbuffer draw anymore, redraw is fast enuf */ if(foundone) { - - /* draw */ - but= block->buttons.first; - while(but) { - if(but->type==LINK && but->link) { - line= but->link->lines.first; - while(line) { - if(line==act) { - if((line->flag & UI_SELECT)==0) { - line->flag |= UI_SELECT; - ui_draw_linkline(but, line); - } - } - else if(line->flag & UI_SELECT) { - line->flag &= ~UI_SELECT; - ui_draw_linkline(but, line); - } - line= line->next; - } - } - but= but->next; - } + addqueue(block->win, REDRAW, 1); } } @@ -3044,7 +3123,7 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent) if(but->type != LABEL && (but->flag & UI_NO_HILITE)==0) ui_draw_but(but); } } - else if(but->type==BLOCK || but->type==MENU) { // automatic opens block button (pulldown) + else if(but->type==BLOCK || but->type==MENU || but->type==PULLDOWN || but->type==ICONTEXTROW) { // automatic opens block button (pulldown) int time; if(uevent->event!=LEFTMOUSE ) { if(block->auto_open==2) time= 1; // test for toolbox @@ -3112,9 +3191,15 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent) but= but->next; } + /* flush to frontbuffer */ + if((block->flag & UI_BLOCK_LOOP)==0) { + ui_block_flush_back(block); + } + uiPanelPop(block); // pop matrix; no return without pop! - /* the linkines... why not make buttons from it? Speed? Memory? */ + +/* the linkines... why not make buttons from it? Speed? Memory? */ if(uevent->val && (uevent->event==XKEY || uevent->event==DELKEY)) ui_delete_active_linkline(block); @@ -3144,9 +3229,9 @@ static int ui_do_block(uiBlock *block, uiEvent *uevent) return retval; } -static uiSaveUnder *ui_draw_but_tip(uiBut *but) +static uiOverDraw *ui_draw_but_tip(uiBut *but) { - uiSaveUnder *su; + uiOverDraw *od; float x1, x2, y1, y2; @@ -3197,7 +3282,7 @@ static uiSaveUnder *ui_draw_but_tip(uiBut *but) y2 -= G.ui_international ? 5:1; //tip is from a windowheader // else y2 += 1; //tip is from button area - su= ui_bgnpupdraw((int)(x1-1), (int)(y1-2), (int)(x2+4), (int)(y2+4), 0); + od= ui_begin_overdraw((int)(x1-1), (int)(y1-2), (int)(x2+4), (int)(y2+4)); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); @@ -3218,17 +3303,17 @@ static uiSaveUnder *ui_draw_but_tip(uiBut *but) glRectf(x1, y1, x2, y2); glColor3ub(0,0,0); - glRasterPos2f( x1+3, y1+5.0/but->aspect); + ui_rasterpos_safe( x1+3, y1+5.0/but->aspect, but->aspect); BIF_DrawString(but->font, but->tip, (U.transopts & USER_TR_TOOLTIPS)); - glFlush(); /* to show it in the frontbuffer */ - return su; + ui_flush_overdraw(od); /* to show it in the frontbuffer */ + return od; } /* inside this function no global UIbuttip... qread is not safe */ static void ui_do_but_tip(uiBut *buttip) { - uiSaveUnder *su; + uiOverDraw *od; int time; if (buttip && buttip->tip && buttip->tip[0]) { @@ -3249,7 +3334,7 @@ static void ui_do_but_tip(uiBut *buttip) * of the button that owns it. */ uiPanelPush(buttip->block); // panel matrix - su= ui_draw_but_tip(buttip); + od= ui_draw_but_tip(buttip); while (1) { char ascii; @@ -3258,7 +3343,7 @@ static void ui_do_but_tip(uiBut *buttip) if (evt==MOUSEX || evt==MOUSEY) { short mouse[2]; - uiGetMouse(su->oldwin, mouse); + uiGetMouse(od->oldwin, mouse); if (!uibut_contains_pt(buttip, mouse)) break; @@ -3268,7 +3353,7 @@ static void ui_do_but_tip(uiBut *buttip) } } - ui_endpupdraw(su); + ui_end_overdraw(od); uiPanelPop(buttip->block); // panel matrix /* still the evil global.... */ UIbuttip= NULL; @@ -3303,7 +3388,7 @@ int uiDoBlocks(ListBase *lb, int event) /* this is a caching mechanism, to prevent too many calls to glFrontBuffer and glFlush, which slows down interface */ block= lb->first; while(block) { - block->frontbuf= UI_NEED_DRAW_FRONT; // signal + ui_block_set_flush(block, NULL); // clears all flushing info block= block->next; } @@ -3321,8 +3406,7 @@ int uiDoBlocks(ListBase *lb, int event) */ if(block->flag & UI_BLOCK_REDRAW) { if( block->flag & UI_BLOCK_LOOP) { - block->saveunder= ui_bgnpupdraw((int)block->minx-1, (int)block->miny-6, (int)block->maxx+6, (int)block->maxy+1, 1); - block->frontbuf= UI_HAS_DRAW_FRONT; + block->overdraw= ui_begin_overdraw((int)block->minx-1, (int)block->miny-6, (int)block->maxx+6, (int)block->maxy+1); } uiDrawBlock(block); block->flag &= ~UI_BLOCK_REDRAW; @@ -3334,11 +3418,10 @@ int uiDoBlocks(ListBase *lb, int event) /* now a new block could be created for menus, this is inserted in the beginning of a list */ - /* is there a glfinish cached? */ - if(block->frontbuf == UI_HAS_DRAW_FRONT) { - glFlush(); - glDrawBuffer(GL_BACK); - block->frontbuf= UI_NEED_DRAW_FRONT; + /* is there a flush cached? */ + if(block->frontbuf == UI_HAS_DRAWN) { + ui_flush_overdraw(block->overdraw); + block->frontbuf= 0; } /* to make sure the matrix of the panel works for menus too */ @@ -3359,36 +3442,33 @@ int uiDoBlocks(ListBase *lb, int event) if(block->flag & UI_BLOCK_REDRAW) { if( block->flag & UI_BLOCK_LOOP) { - block->saveunder= ui_bgnpupdraw((int)block->minx-1, (int)block->miny-6, (int)block->maxx+6, (int)block->maxy+1, 1); - block->frontbuf= UI_HAS_DRAW_FRONT; + block->overdraw= ui_begin_overdraw((int)block->minx-1, (int)block->miny-6, (int)block->maxx+6, (int)block->maxy+1); } uiDrawBlock(block); block->flag &= ~UI_BLOCK_REDRAW; + ui_flush_overdraw(block->overdraw); + block->frontbuf= 0; } - - /* need to reveil drawing? (not in end of loop, because of free block */ - if(block->frontbuf == UI_HAS_DRAW_FRONT) { - glFlush(); - block->frontbuf= UI_NEED_DRAW_FRONT; - } - + uevent.event= extern_qread(&uevent.val); if(uevent.event) { - retval= ui_do_block(block, &uevent); + if(block->frontbuf == UI_HAS_DRAWN) { // flush now, maybe new menu was opened + ui_flush_overdraw(block->overdraw); + block->frontbuf= 0; + } + if(retval & UI_RETURN) { - /* free this block */ - ui_endpupdraw(block->saveunder); - + ui_end_overdraw(block->overdraw); BLI_remlink(lb, block); uiFreeBlock(block); } if(retval & (UI_RETURN_OK|UI_RETURN_CANCEL)) { /* free other menus */ while( (block= lb->first) && (block->flag & UI_BLOCK_LOOP)) { - ui_endpupdraw(block->saveunder); + ui_end_overdraw(block->overdraw); BLI_remlink(lb, block); uiFreeBlock(block); } @@ -3405,28 +3485,17 @@ int uiDoBlocks(ListBase *lb, int event) if(retval==UI_CONT || (retval & UI_RETURN_OK)) cont= 0; } - /* cleanup frontbuffer & flags */ - block= lb->first; - while(block) { - if(block->frontbuf==UI_HAS_DRAW_FRONT) glFlush(); - block->frontbuf= 0; - block= block->next; - } - /* afterfunc is used for fileloading too, so after this call, the blocks pointers are invalid */ if(retval & UI_RETURN_OK) { if(UIafterfunc) UIafterfunc(UIafterfunc_arg, UIafterval); UIafterfunc= NULL; } - + /* tooltip */ if(retval==UI_NOTHING && (uevent.event==MOUSEX || uevent.event==MOUSEY)) { if(U.flag & USER_TOOLTIPS) ui_do_but_tip(UIbuttip); } - /* doesnt harm :-) */ - glDrawBuffer(GL_BACK); - return retval; } @@ -3925,6 +3994,7 @@ static int ui_auto_themecol(uiBut *but) return TH_BUT_NUM; case TEX: return TH_BUT_TEXTFIELD; + case PULLDOWN: case BLOCK: case MENU: case BUTM: @@ -4157,7 +4227,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short but->aspect= block->aspect; but->win= block->win; - but->block= block; // pointer back, used for frontbuffer status + but->block= block; // pointer back, used for frontbuffer status, and picker if(block->themecol==TH_AUTO) but->themecol= ui_auto_themecol(but); else but->themecol= block->themecol; @@ -4532,6 +4602,14 @@ uiBut *uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, s return but; } +uiBut *uiDefPulldownBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip) +{ + uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip); + but->block_func= func; + ui_check_but(but); + return but; +} + /* Block button containing both string label and icon */ uiBut *uiDefIconTextBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip) { |