diff options
author | Ton Roosendaal <ton@blender.org> | 2009-05-24 17:29:29 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2009-05-24 17:29:29 +0400 |
commit | ab407f6ac748225386c5f09685490d6df67916f8 (patch) | |
tree | f66ec462386dbfcc847f690551866bf2a3630c14 | |
parent | ef01c5bf0abda3893b3a7f075a3ab20f164d5081 (diff) |
2.5
First version of region-scaling. WIP commit, so bear with me a while!
- All fixed sized regions have a small 'drag' widget, on the left or top.
(not yet for free-sized regions, like 4-split).
- Mouse-over on widget changes cursor and allows drag.
- Click on widget hides/reveals.
- Fun for test; 3d view header, if high enough, draws more rows of
buttons when width is too small.
The WIP stuff;
- It doesn't save yet in files, using the "minsize" variable of region
definitions, also means other similar areas show same sizes now.
- Definitions for pref size, min/max will be added.
- Properties panel in Fcurve window draws widget on wrong place when
hidden (subdiv system needs tweak)
- Widgets don't draw perfect yet, also needs further tweaks.
But, in general it's quite fun and usable. :) Many variatians are possible,
like for real tabs, or little icons, or just click-drag on edge.
The reason to first try the widget/tab variation:
- it re-uses the "Area Action Zone" code, widgets for layouting Screens
- it's visible, hotkey-only options for screen layouts are not preferred.
- distinguish clearly area-edges from region-edges this way. Having the
cursor change shape on every edge (and block input) is probably annoying
too... but that can be tested.
Later more!
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 16 | ||||
-rw-r--r-- | source/blender/blenlib/intern/rct.c | 41 | ||||
-rw-r--r-- | source/blender/editors/include/ED_screen_types.h | 27 | ||||
-rw-r--r-- | source/blender/editors/screen/area.c | 220 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_edit.c | 12 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 256 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_header.c | 76 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_types.h | 4 |
9 files changed, 504 insertions, 150 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 30bb4d11450..787579250ed 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -402,7 +402,7 @@ int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3] void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v); void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv); void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv); -int IsPointInTri2D(float v0[2], float v1[2], float v2[2], float pt[2]); +int IsPointInTri2D(float v1[2], float v2[2], float v3[2], float pt[2]); int IsPointInTri2DInts(int x1, int y1, int x2, int y2, int a, int b); int point_in_tri_prism(float p[3], float v1[3], float v2[3], float v3[3]); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 2368f0cd2ba..f111e94a141 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -4515,6 +4515,21 @@ void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3 } } +int IsPointInTri2D(float v1[2], float v2[2], float v3[2], float pt[2]) +{ + float inp1, inp2, inp3; + + inp1= (v2[0]-v1[0])*(v1[1]-pt[1]) + (v1[1]-v2[1])*(v1[0]-pt[0]); + inp2= (v3[0]-v2[0])*(v2[1]-pt[1]) + (v2[1]-v3[1])*(v2[0]-pt[0]); + inp3= (v1[0]-v3[0])*(v3[1]-pt[1]) + (v3[1]-v1[1])*(v3[0]-pt[0]); + + if(inp1<=0.0f && inp2<=0.0f && inp3<=0.0f) return 1; + if(inp1>=0.0f && inp2>=0.0f && inp3>=0.0f) return 1; + + return 0; +} + +#if 0 int IsPointInTri2D(float v0[2], float v1[2], float v2[2], float pt[2]) { /* not for quads, use for our abuse of LineIntersectsTriangleUV */ @@ -4542,6 +4557,7 @@ int IsPointInTri2D(float v0[2], float v1[2], float v2[2], float pt[2]) /* Doing this in 3D is not nice */ return LineIntersectsTriangle(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv); } +#endif /* diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 48ba18515de..915a93e8e0b 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -88,17 +88,42 @@ void BLI_union_rcti(rcti *rct1, rcti *rct2) void BLI_init_rctf(rctf *rect, float xmin, float xmax, float ymin, float ymax) { - rect->xmin= xmin; - rect->xmax= xmax; - rect->ymin= ymin; - rect->ymax= ymax; + if(xmin <= xmax) { + rect->xmin= xmin; + rect->xmax= xmax; + } + else { + rect->xmax= xmin; + rect->xmin= xmax; + } + if(ymin <= ymax) { + rect->ymin= ymin; + rect->ymax= ymax; + } + else { + rect->ymax= ymin; + rect->ymin= ymax; + } } + void BLI_init_rcti(rcti *rect, int xmin, int xmax, int ymin, int ymax) { - rect->xmin= xmin; - rect->xmax= xmax; - rect->ymin= ymin; - rect->ymax= ymax; + if(xmin <= xmax) { + rect->xmin= xmin; + rect->xmax= xmax; + } + else { + rect->xmax= xmin; + rect->xmin= xmax; + } + if(ymin <= ymax) { + rect->ymin= ymin; + rect->ymax= ymax; + } + else { + rect->ymax= ymin; + rect->ymin= ymax; + } } void BLI_translate_rcti(rcti *rect, int x, int y) diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 5a13e944d5c..37f2f4f051d 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -38,27 +38,20 @@ typedef struct ScreenAnimData { typedef struct AZone { struct AZone *next, *prev; + ARegion *ar; int type; - short flag; + /* region-azone, which of the edges */ + short edge; + /* internal */ short do_draw; - int pos; - short x1, y1, x2, y2; + /* for draw */ + short x1, y1, x2, y2, x3, y3; + /* for clip */ + rcti rect; } AZone; /* actionzone type */ -#define AZONE_TRI 1 -#define AZONE_QUAD 2 - -/* actionzone flag */ - -/* actionzone pos */ -#define AZONE_S 1 -#define AZONE_SW 2 -#define AZONE_W 3 -#define AZONE_NW 4 -#define AZONE_N 5 -#define AZONE_NE 6 -#define AZONE_E 7 -#define AZONE_SE 8 +#define AZONE_AREA 1 +#define AZONE_REGION 2 #endif /* ED_SCREEN_TYPES_H__ */ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 99ab7be7106..ad6b6e04b8e 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -157,7 +157,16 @@ void ED_area_overdraw_flush(bContext *C, ScrArea *sa, ARegion *ar) AZone *az; for(az= sa->actionzones.first; az; az= az->next) { - int xs= (az->x1+az->x2)/2, ys= (az->y1+az->y2)/2; + int xs, ys; + + if(az->type==AZONE_AREA) { + xs= (az->x1+az->x2)/2; + ys= (az->y1+az->y2)/2; + } + else { + xs= az->x3; + ys= az->y3; + } /* test if inside */ if(BLI_in_rcti(&ar->winrct, xs, ys)) { @@ -187,6 +196,28 @@ static void area_draw_azone(short x1, short y1, short x2, short y2) fdrawline(xmin, ymax-2*dy+1, xmax-2*dx+1, ymin); } +static void region_draw_azone(ScrArea *sa, AZone *az) +{ + if(az->ar==NULL) return; + + UI_SetTheme(sa->spacetype, az->ar->type->regionid); + + UI_ThemeColor(TH_BACK); + glBegin(GL_TRIANGLES); + glVertex2s(az->x1, az->y1); + glVertex2s(az->x2, az->y2); + glVertex2s(az->x3, az->y3); + glEnd(); + + UI_ThemeColorShade(TH_BACK, 50); + sdrawline(az->x1, az->y1, az->x3, az->y3); + + UI_ThemeColorShade(TH_BACK, -50); + sdrawline(az->x2, az->y2, az->x3, az->y3); + +} + + /* only exported for WM */ void ED_area_overdraw(bContext *C) { @@ -204,9 +235,11 @@ void ED_area_overdraw(bContext *C) AZone *az; for(az= sa->actionzones.first; az; az= az->next) { if(az->do_draw) { - if(az->type==AZONE_TRI) { + if(az->type==AZONE_AREA) area_draw_azone(az->x1, az->y1, az->x2, az->y2); - } + else if(az->type==AZONE_REGION) + region_draw_azone(sa, az); + az->do_draw= 0; } } @@ -360,8 +393,124 @@ void ED_area_headerprint(ScrArea *sa, const char *str) } } +/* ************************************************************ */ + + +#define AZONESPOT 12 +static void area_azone_initialize(ScrArea *sa) +{ + AZone *az; + + /* reinitalize entirely, regions add azones too */ + BLI_freelistN(&sa->actionzones); + + /* set area action zones */ + az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone"); + BLI_addtail(&(sa->actionzones), az); + az->type= AZONE_AREA; + az->x1= sa->totrct.xmin; + az->y1= sa->totrct.ymin; + az->x2= sa->totrct.xmin + AZONESPOT-1; + az->y2= sa->totrct.ymin + AZONESPOT-1; + BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2); + + az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone"); + BLI_addtail(&(sa->actionzones), az); + az->type= AZONE_AREA; + az->x1= sa->totrct.xmax+1; + az->y1= sa->totrct.ymax+1; + az->x2= sa->totrct.xmax-AZONESPOT+1; + az->y2= sa->totrct.ymax-AZONESPOT+1; + BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y2); +} + +static void region_azone_initialize(ScrArea *sa, ARegion *ar, char edge) +{ + AZone *az, *azt; + + az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone"); + BLI_addtail(&(sa->actionzones), az); + az->type= AZONE_REGION; + az->ar= ar; + az->edge= edge; + + if(edge=='t') { + az->x1= ar->winrct.xmin+AZONESPOT; + az->y1= ar->winrct.ymax; + az->x2= ar->winrct.xmin+2*AZONESPOT; + az->y2= ar->winrct.ymax; + az->x3= (az->x1+az->x2)/2; + az->y3= az->y2+AZONESPOT/2; + BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y3); + } + else if(edge=='b') { + az->x1= ar->winrct.xmin+AZONESPOT; + az->y1= ar->winrct.ymin; + az->x2= ar->winrct.xmin+2*AZONESPOT; + az->y2= ar->winrct.ymin; + az->x3= (az->x1+az->x2)/2; + az->y3= az->y2-AZONESPOT/2; + BLI_init_rcti(&az->rect, az->x1, az->x2, az->y3, az->y1); + } + else if(edge=='l') { + az->x1= ar->winrct.xmin; + az->y1= ar->winrct.ymax-AZONESPOT; + az->x2= ar->winrct.xmin; + az->y2= ar->winrct.ymax-2*AZONESPOT; + az->x3= az->x2-AZONESPOT/2; + az->y3= (az->y1+az->y2)/2; + BLI_init_rcti(&az->rect, az->x3, az->x1, az->y1, az->y2); + } + else { // if(edge=='r') { + az->x1= ar->winrct.xmax; + az->y1= ar->winrct.ymax-AZONESPOT; + az->x2= ar->winrct.xmax; + az->y2= ar->winrct.ymax-2*AZONESPOT; + az->x3= az->x2+AZONESPOT/2; + az->y3= (az->y1+az->y2)/2; + BLI_init_rcti(&az->rect, az->x1, az->x3, az->y1, az->y2); + } + + /* if more azones on 1 spot, set offset */ + for(azt= sa->actionzones.first; azt; azt= azt->next) { + if(az!=azt) { + if(az->x1==azt->x1 && az->y1==azt->y1) { + if(edge=='t' || edge=='b') { + az->x1+= AZONESPOT; + az->x2+= AZONESPOT; + az->x3+= AZONESPOT; + BLI_init_rcti(&az->rect, az->x1, az->x2, az->y1, az->y3); + } + else { + az->y1-= AZONESPOT; + az->y2-= AZONESPOT; + az->y3-= AZONESPOT; + BLI_init_rcti(&az->rect, az->x1, az->x3, az->y1, az->y2); + } + } + } + } + +} + + /* *************************************************************** */ +static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment) +{ + /* edge code (t b l r) is where azone will be drawn */ + + if(alignment==RGN_ALIGN_TOP) + region_azone_initialize(sa, ar, 'b'); + else if(alignment==RGN_ALIGN_BOTTOM) + region_azone_initialize(sa, ar, 't'); + else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) + region_azone_initialize(sa, ar, 'l'); + else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT)) + region_azone_initialize(sa, ar, 'r'); + +} + /* dir is direction to check, not the splitting edge direction! */ static int rct_fits(rcti *rect, char dir, int size) { @@ -373,7 +522,7 @@ static int rct_fits(rcti *rect, char dir, int size) } } -static void region_rect_recursive(ARegion *ar, rcti *remainder, int quad) +static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int quad) { rcti *remainder_prev= remainder; int prefsizex, prefsizey; @@ -382,6 +531,7 @@ static void region_rect_recursive(ARegion *ar, rcti *remainder, int quad) if(ar==NULL) return; + /* no returns in function, winrct gets set in the end again */ BLI_init_rcti(&ar->winrct, 0, 0, 0, 0); /* for test; allow split of previously defined region */ @@ -540,7 +690,27 @@ static void region_rect_recursive(ARegion *ar, rcti *remainder, int quad) ar->prev->winy= ar->prev->winrct.ymax - ar->prev->winrct.ymin + 1; } } - region_rect_recursive(ar->next, remainder, quad); + + /* set winrect for azones */ + if(ar->flag & (RGN_FLAG_HIDDEN|RGN_FLAG_TOO_SMALL)) { + ar->winrct= *remainder; + + if(alignment==RGN_ALIGN_TOP) + ar->winrct.ymin= ar->winrct.ymax; + else if(alignment==RGN_ALIGN_BOTTOM) + ar->winrct.ymax= ar->winrct.ymin; + else if(ELEM(alignment, RGN_ALIGN_RIGHT, RGN_OVERLAP_RIGHT)) + ar->winrct.xmin= ar->winrct.xmax; + else if(ELEM(alignment, RGN_ALIGN_LEFT, RGN_OVERLAP_LEFT)) + ar->winrct.xmax= ar->winrct.xmin; + else /* prevent winrct to be valid */ + ar->winrct.xmax= ar->winrct.xmin; + } + /* in end, add azones, where appropriate */ + region_azone_add(sa, ar, alignment); + + + region_rect_recursive(sa, ar->next, remainder, quad); } static void area_calc_totrct(ScrArea *sa, int sizex, int sizey) @@ -563,40 +733,6 @@ static void area_calc_totrct(ScrArea *sa, int sizex, int sizey) } -#define AZONESPOT 12 -void area_azone_initialize(ScrArea *sa) -{ - AZone *az; - if(sa->actionzones.first==NULL) { - /* set action zones - should these actually be ARegions? With these we can easier check area hotzones */ - /* (ton) for time being just area, ARegion split is not foreseen on user level */ - az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone"); - BLI_addtail(&(sa->actionzones), az); - az->type= AZONE_TRI; - az->pos= AZONE_SW; - - az= (AZone *)MEM_callocN(sizeof(AZone), "actionzone"); - BLI_addtail(&(sa->actionzones), az); - az->type= AZONE_TRI; - az->pos= AZONE_NE; - } - - for(az= sa->actionzones.first; az; az= az->next) { - if(az->pos==AZONE_SW) { - az->x1= sa->totrct.xmin; - az->y1= sa->totrct.ymin; - az->x2= sa->totrct.xmin + AZONESPOT-1; - az->y2= sa->totrct.ymin + AZONESPOT-1; - } - else if (az->pos==AZONE_NE) { - az->x1= sa->totrct.xmax+1; - az->y1= sa->totrct.ymax+1; - az->x2= sa->totrct.xmax-AZONESPOT+1; - az->y2= sa->totrct.ymax-AZONESPOT+1; - } - } -} - /* used for area initialize below */ static void region_subwindow(wmWindowManager *wm, wmWindow *win, ARegion *ar) { @@ -659,9 +795,12 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) /* area sizes */ area_calc_totrct(sa, win->sizex, win->sizey); + /* clear all azones, add the area triange widgets */ + area_azone_initialize(sa); + /* region rect sizes */ rect= sa->totrct; - region_rect_recursive(sa->regionbase.first, &rect, 0); + region_rect_recursive(sa, sa->regionbase.first, &rect, 0); /* default area handlers */ ed_default_handlers(wm, &sa->handlers, sa->type->keymapflag); @@ -686,7 +825,6 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } } - area_azone_initialize(sa); } /* externally called for floating regions like menus */ diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 1d131e5c103..93d2ec75e9d 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1135,14 +1135,22 @@ void ED_screen_exit(bContext *C, wmWindow *window, bScreen *screen) /* case when on area-edge or in azones, or outside window */ static void screen_cursor_set(wmWindow *win, wmEvent *event) { + AZone *az= NULL; ScrArea *sa; for(sa= win->screen->areabase.first; sa; sa= sa->next) - if(is_in_area_actionzone(sa, event->x, event->y)) + if((az=is_in_area_actionzone(sa, event->x, event->y))) break; if(sa) { - WM_cursor_set(win, CURSOR_EDIT); + if(az->type==AZONE_AREA) + WM_cursor_set(win, CURSOR_EDIT); + else if(az->type==AZONE_REGION) { + if(az->x1==az->x2) + WM_cursor_set(win, CURSOR_X_MOVE); + else + WM_cursor_set(win, CURSOR_Y_MOVE); + } } else { ScrEdge *actedge= screen_find_active_scredge(win->screen, event->x, event->y); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index aea27930c16..1a1a8bd8f9c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -323,46 +323,51 @@ static ScrArea *screen_areahascursor(bScreen *scr, int x, int y) return sa; } +/* quick poll to save operators to be created and handled */ +static int actionzone_area_poll(bContext *C) +{ + wmWindow *win= CTX_wm_window(C); + ScrArea *sa= CTX_wm_area(C); + + if(sa && win) { + AZone *az; + int x= win->eventstate->x; + int y= win->eventstate->y; + + for(az= sa->actionzones.first; az; az= az->next) + if(BLI_in_rcti(&az->rect, x, y)) + return 1; + } + return 0; +} AZone *is_in_area_actionzone(ScrArea *sa, int x, int y) { AZone *az= NULL; - int i= 0; - for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) { - if(az->type == AZONE_TRI) { - if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) - break; - } - if(az->type == AZONE_QUAD) { - if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2) - break; + for(az= sa->actionzones.first; az; az= az->next) { + if(BLI_in_rcti(&az->rect, x, y)) { + if(az->type == AZONE_AREA) { + if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) + break; + } + else if(az->type == AZONE_REGION) { + float v1[2], v2[2], v3[2], pt[2]; + + v1[0]= az->x1; v1[1]= az->y1; + v2[0]= az->x2; v2[1]= az->y2; + v3[0]= az->x3; v3[1]= az->y3; + pt[0]= x; pt[1]=y; + + if(IsPointInTri2D(v1, v2, v3, pt)) + break; + } } } return az; } -static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y); - sActionzoneData *sad; - - /* quick escape */ - if(az==NULL) - return OPERATOR_PASS_THROUGH; - - /* ok we do the actionzone */ - sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData"); - sad->sa1= CTX_wm_area(C); - sad->az= az; - sad->x= event->x; sad->y= event->y; - - /* add modal handler */ - WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); - - return OPERATOR_RUNNING_MODAL; -} static void actionzone_exit(bContext *C, wmOperator *op) { @@ -372,15 +377,19 @@ static void actionzone_exit(bContext *C, wmOperator *op) } /* send EVT_ACTIONZONE event */ -static void actionzone_apply(bContext *C, wmOperator *op) +static void actionzone_apply(bContext *C, wmOperator *op, int type) { wmEvent event; wmWindow *win= CTX_wm_window(C); sActionzoneData *sad= op->customdata; + sad->modifier= RNA_int_get(op->ptr, "modifier"); event= *(win->eventstate); /* XXX huh huh? make api call */ - event.type= EVT_ACTIONZONE; + if(type==AZONE_AREA) + event.type= EVT_ACTIONZONE_AREA; + else + event.type= EVT_ACTIONZONE_REGION; event.customdata= op->customdata; event.customdatafree= TRUE; op->customdata= NULL; @@ -388,10 +397,41 @@ static void actionzone_apply(bContext *C, wmOperator *op) wm_event_add(win, &event); } +static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y); + sActionzoneData *sad; + + /* quick escape */ + if(az==NULL) + return OPERATOR_PASS_THROUGH; + + /* ok we do the actionzone */ + sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData"); + sad->sa1= CTX_wm_area(C); + sad->az= az; + sad->x= event->x; sad->y= event->y; + + /* region azone directly reacts on mouse clicks */ + if(sad->az->type==AZONE_REGION) { + actionzone_apply(C, op, AZONE_REGION); + actionzone_exit(C, op); + return OPERATOR_FINISHED; + } + else { + /* add modal handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; + } +} + + static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) { sActionzoneData *sad= op->customdata; int deltax, deltay; + int mindelta= sad->az->type==AZONE_REGION?1:12; switch(event->type) { case MOUSEMOVE: @@ -400,30 +440,33 @@ static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) deltay= (event->y - sad->y); if(deltay > ABS(deltax)) - sad->gesture_dir= AZONE_N; + sad->gesture_dir= 'n'; else if(deltax > ABS(deltay)) - sad->gesture_dir= AZONE_E; + sad->gesture_dir= 'e'; else if(deltay < -ABS(deltax)) - sad->gesture_dir= AZONE_S; + sad->gesture_dir= 's'; else - sad->gesture_dir= AZONE_W; + sad->gesture_dir= 'w'; /* gesture is large enough? */ - if(ABS(deltax) > 12 || ABS(deltay) > 12) { + if(ABS(deltax) > mindelta || ABS(deltay) > mindelta) { /* second area, for join */ sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* apply sends event */ - actionzone_apply(C, op); + actionzone_apply(C, op, sad->az->type); actionzone_exit(C, op); return OPERATOR_FINISHED; } break; case ESCKEY: - case LEFTMOUSE: actionzone_exit(C, op); return OPERATOR_CANCELLED; + case LEFTMOUSE: + actionzone_exit(C, op); + return OPERATOR_CANCELLED; + } return OPERATOR_RUNNING_MODAL; @@ -438,7 +481,7 @@ void SCREEN_OT_actionzone(wmOperatorType *ot) ot->invoke= actionzone_invoke; ot->modal= actionzone_modal; - ot->poll= ED_operator_areaactive; + ot->poll= actionzone_area_poll; RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2); } @@ -544,7 +587,7 @@ static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -void SCREEN_OT_area_swap(wmOperatorType *ot) +static void SCREEN_OT_area_swap(wmOperatorType *ot) { ot->name= "Swap areas"; ot->idname= "SCREEN_OT_area_swap"; @@ -598,7 +641,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -void SCREEN_OT_area_dupli(wmOperatorType *ot) +static void SCREEN_OT_area_dupli(wmOperatorType *ot) { ot->name= "Duplicate Area into New Window"; ot->idname= "SCREEN_OT_area_dupli"; @@ -1015,7 +1058,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) { sAreaSplitData *sd; - if(event->type==EVT_ACTIONZONE) { + if(event->type==EVT_ACTIONZONE_AREA) { sActionzoneData *sad= event->customdata; int dir; @@ -1036,7 +1079,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_PASS_THROUGH; /* prepare operator state vars */ - if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) { + if(sad->gesture_dir=='n' || sad->gesture_dir=='s') { dir= 'h'; RNA_float_set(op->ptr, "factor", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx); } @@ -1160,6 +1203,119 @@ void SCREEN_OT_area_split(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0); } + + +/* ************** scale region edge operator *********************************** */ + +typedef struct RegionMoveData { + ARegion *ar; + int bigger, smaller, origval; + int origx, origy; + char edge; + +} RegionMoveData; + +static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + sActionzoneData *sad= event->customdata; + AZone *az= sad->az; + + if(az->ar) { + RegionMoveData *rmd= MEM_callocN(sizeof(RegionMoveData), "RegionMoveData"); + + op->customdata= rmd; + + rmd->ar= az->ar; + rmd->edge= az->edge; + rmd->origx= event->x; + rmd->origy= event->y; + if(rmd->edge=='l' || rmd->edge=='r') + rmd->origval= rmd->ar->type->minsizex; + else + rmd->origval= rmd->ar->type->minsizey; + + /* add temp handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; + } + + return OPERATOR_FINISHED; +} + +static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + RegionMoveData *rmd= op->customdata; + int delta; + + /* execute the events */ + switch(event->type) { + case MOUSEMOVE: + + if(rmd->edge=='l' || rmd->edge=='r') { + delta= event->x - rmd->origx; + if(rmd->edge=='l') delta= -delta; + rmd->ar->type->minsizex= rmd->origval + delta; + CLAMP(rmd->ar->type->minsizex, 0, 1000); + if(rmd->ar->type->minsizex < 10) { + rmd->ar->type->minsizex= 10; + rmd->ar->flag |= RGN_FLAG_HIDDEN; + } + else + rmd->ar->flag &= ~RGN_FLAG_HIDDEN; + } + else { + delta= event->y - rmd->origy; + if(rmd->edge=='b') delta= -delta; + rmd->ar->type->minsizey= rmd->origval + delta; + CLAMP(rmd->ar->type->minsizey, 0, 1000); + if(rmd->ar->type->minsizey < 10) { + rmd->ar->type->minsizey= 10; + rmd->ar->flag |= RGN_FLAG_HIDDEN; + } + else + rmd->ar->flag &= ~RGN_FLAG_HIDDEN; + } + + WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); + + break; + + case LEFTMOUSE: + if(event->val==0) { + + if(ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) { + rmd->ar->flag ^= RGN_FLAG_HIDDEN; + WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); + } + MEM_freeN(op->customdata); + op->customdata = NULL; + + return OPERATOR_FINISHED; + } + break; + + case ESCKEY: + ; + } + + return OPERATOR_RUNNING_MODAL; +} + + +static void SCREEN_OT_region_scale(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Scale Region Size"; + ot->idname= "SCREEN_OT_region_scale"; + + ot->invoke= region_scale_invoke; + ot->modal= region_scale_modal; + + ot->poll= ED_operator_areaactive; +} + + /* ************** frame change operator ***************************** */ @@ -1387,7 +1543,7 @@ static int area_join_exec(bContext *C, wmOperator *op) static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) { - if(event->type==EVT_ACTIONZONE) { + if(event->type==EVT_ACTIONZONE_AREA) { sActionzoneData *sad= event->customdata; if(sad->modifier>0) { @@ -2498,6 +2654,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_region_split); WM_operatortype_append(SCREEN_OT_region_foursplit); WM_operatortype_append(SCREEN_OT_region_flip); + WM_operatortype_append(SCREEN_OT_region_scale); WM_operatortype_append(SCREEN_OT_screen_set); WM_operatortype_append(SCREEN_OT_screen_full_area); WM_operatortype_append(SCREEN_OT_screenshot); @@ -2531,11 +2688,14 @@ void ED_keymap_screen(wmWindowManager *wm) RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2); /* screen tools */ + WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0); + WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0); + WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0); + WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_ALT, 0); + WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0); + /* area move after action zones */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, 0, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, 0, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE, 0, KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE, 0, KM_ALT, 0); + RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index da201195288..6f67d0076aa 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -5262,6 +5262,19 @@ static int view3d_layer_icon(int but_lay, int ob_lay, int used_lay) return ICON_BLANK1; } +static void header_xco_step(ARegion *ar, int *xco, int *yco, int *maxco, int step) +{ + *xco += step; + if(*maxco < *xco) *maxco = *xco; + + if(ar->winy > *yco + 44) { + if(*xco > ar->winrct.xmax) { + *xco= 8; + *yco+= 22; + } + } +} + void view3d_header_buttons(const bContext *C, ARegion *ar) { ScrArea *sa= CTX_wm_area(C); @@ -5270,7 +5283,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) Object *ob= OBACT; Object *obedit = CTX_data_edit_object(C); uiBlock *block; - int a, xco, yco= 3; + int a, xco, maxco=0, yco= 3; block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS); uiBlockSetHandleFunc(block, do_view3d_header_buttons, NULL); @@ -5307,14 +5320,12 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiDefIconTextButS(block, MENU, B_MODESELECT, (v3d->modeselect),view3d_modeselect_pup(scene) , xco,yco,126,20, &(v3d->modeselect), 0, 0, 0, 0, "Mode (Hotkeys: Tab, V, Ctrl Tab)"); - - xco+= 126+8; + header_xco_step(ar, &xco, &yco, &maxco, 126+8); /* DRAWTYPE */ uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_BBOX, drawtype_pup(), xco,yco,XIC+10,YIC, &(v3d->drawtype), 1.0, 5.0, 0, 0, "Viewport Shading (Hotkeys: Z, Shift Z, Alt Z)"); - /* around */ - xco+= XIC+18; + header_xco_step(ar, &xco, &yco, &maxco, XIC+18); uiBlockBeginAlign(block); @@ -5324,38 +5335,37 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) ToolSettings *ts= scene->toolsettings; uiDefButC(block,ROW,B_REDR,"Pen",xco,yco,40,20,&ts->retopo_paint_tool,6.0,RETOPO_PEN,0,0,""); - xco+=40; + xco+= 40; uiDefButC(block,ROW,B_REDR,"Line",xco,yco,40,20,&ts->retopo_paint_tool,6.0,RETOPO_LINE,0,0,""); - xco+=40; + xco+= 40; uiDefButC(block,ROW,B_REDR,"Ellipse",xco,yco,60,20,&ts->retopo_paint_tool,6.0,RETOPO_ELLIPSE,0,0,""); - xco+=65; + xco+= 65; uiBlockBeginAlign(block); if(ts->retopo_paint_tool == RETOPO_PEN) { uiDefButC(block,TOG,B_NOP,"Hotspot",xco,yco,60,20, &ts->retopo_hotspot, 0,0,0,0,"Show hotspots at line ends to allow line continuation"); - xco+=80; + xco+= 80; } else if(ts->retopo_paint_tool == RETOPO_LINE) { uiDefButC(block,NUM,B_NOP,"LineDiv",xco,yco,80,20,&ts->line_div,1,50,0,0,"Subdivisions per retopo line"); - xco+=80; + xco+= 80; } else if(ts->retopo_paint_tool == RETOPO_ELLIPSE) { uiDefButC(block,NUM,B_NOP,"EllDiv",xco,yco,80,20,&ts->ellipse_div,3,50,0,0,"Subdivisions per retopo ellipse"); - xco+=80; + xco+= 80; } - xco+=5; + header_xco_step(ar, &xco, &yco, &maxco, 5); uiBlockEndAlign(block); } } else { if (obedit==NULL && (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT))) { uiDefIconButBitI(block, TOG, G_FACESELECT, B_VIEW_BUTSEDIT, ICON_FACESEL_HLT,xco,yco,XIC,YIC, &G.f, 0, 0, 0, 0, "Painting Mask (FKey)"); - xco+= XIC+10; + header_xco_step(ar, &xco, &yco, &maxco, XIC+10); } else { - /* Manipulators arnt used in weight paint mode */ + /* Manipulators aren't used in weight paint mode */ char *str_menu; uiDefIconTextButS(block, ICONTEXTROW,B_AROUND, ICON_ROTATE, around_pup(C), xco,yco,XIC+10,YIC, &(v3d->around), 0, 3.0, 0, 0, "Rotation/Scaling Pivot (Hotkeys: Comma, Shift Comma, Period, Ctrl Period, Alt Period)"); - xco+= XIC+10; uiDefIconButBitS(block, TOG, V3D_ALIGN, B_AROUND, ICON_ALIGN, @@ -5363,14 +5373,13 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) &v3d->flag, 0, 0, 0, 0, "Move object centers only"); uiBlockEndAlign(block); - xco+= XIC+8; + header_xco_step(ar, &xco, &yco, &maxco, XIC+8); uiBlockBeginAlign(block); /* NDOF */ if (G.ndofdevice ==0 ) { uiDefIconTextButC(block, ICONTEXTROW,B_NDOF, ICON_NDOF_TURN, ndof_pup(), xco,yco,XIC+10,YIC, &(v3d->ndofmode), 0, 3.0, 0, 0, "Ndof mode"); - xco+= XIC+10; uiDefIconButC(block, TOG, B_NDOF, ICON_NDOF_DOM, @@ -5378,7 +5387,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) &v3d->ndoffilter, 0, 1, 0, 0, "dominant axis"); uiBlockEndAlign(block); - xco+= XIC+8; + header_xco_step(ar, &xco, &yco, &maxco, XIC+8); } uiBlockEndAlign(block); @@ -5386,7 +5395,6 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiBlockBeginAlign(block); uiDefIconButBitS(block, TOG, V3D_USE_MANIPULATOR, B_REDR, ICON_MANIPUL,xco,yco,XIC,YIC, &v3d->twflag, 0, 0, 0, 0, "Use 3d transform manipulator (Ctrl Space)"); xco+= XIC; - if(v3d->twflag & V3D_USE_MANIPULATOR) { uiDefIconButBitS(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, xco,yco,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Translate manipulator mode (Ctrl Alt G)"); @@ -5405,9 +5413,8 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiDefButS(block, MENU, B_MAN_MODE, str_menu,xco,yco,70,YIC, &v3d->twmode, 0, 0, 0, 0, "Transform Orientation (ALT+Space)"); MEM_freeN(str_menu); - xco+= 70; + header_xco_step(ar, &xco, &yco, &maxco, 78); uiBlockEndAlign(block); - xco+= 8; } /* LAYERS */ @@ -5434,7 +5441,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) /* LOCK */ uiDefIconButS(block, ICONTOG, B_SCENELOCK, ICON_LOCKVIEW_OFF, xco+=XIC,yco,XIC,YIC, &(v3d->scenelock), 0, 0, 0, 0, "Locks Active Camera and layers to Scene (Ctrl `)"); - xco+= XIC+10; + header_xco_step(ar, &xco, &yco, &maxco, XIC+10); } @@ -5450,7 +5457,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) xco+= XIC+10; } uiBlockEndAlign(block); - xco+= 10; + header_xco_step(ar, &xco, &yco, &maxco, XIC+10); } /* Snap */ @@ -5469,14 +5476,14 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(scene->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode"); xco+= XIC; uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &scene->snap_target, 0, 0, 0, 0, "Snap Target Mode"); - xco+= 70; + xco+= XIC+70; } else { uiDefIconButBitS(block, TOG, SCE_SNAP, B_REDR, ICON_SNAP_GEAR,xco,yco,XIC,YIC, &scene->snap_flag, 0, 0, 0, 0, "Snap while Ctrl is held during transform (Shift Tab)"); xco+= XIC; } uiBlockEndAlign(block); - xco+= 10; + header_xco_step(ar, &xco, &yco, &maxco, 10); } /* selection modus */ @@ -5496,7 +5503,7 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) xco+= XIC; } uiBlockEndAlign(block); - xco+= 20; + header_xco_step(ar, &xco, &yco, &maxco, XIC); BKE_mesh_end_editmesh(obedit->data, em); } @@ -5509,12 +5516,13 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,yco,XIC,YIC, &scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode"); xco+= XIC; uiBlockEndAlign(block); + if(v3d->drawtype > OB_WIRE) { uiDefIconButBitS(block, TOG, V3D_ZBUF_SELECT, B_REDR, ICON_ORTHO, xco,yco,XIC,YIC, &v3d->flag, 1.0, 0.0, 0, 0, "Limit selection to visible (clipped with depth buffer)"); xco+= XIC; } uiBlockEndAlign(block); - xco+= 20; + header_xco_step(ar, &xco, &yco, &maxco, XIC); } uiDefIconBut(block, BUT, B_VIEWRENDER, ICON_SCENE, xco,yco,XIC,YIC, NULL, 0, 1.0, 0, 0, "Render this window (Ctrl Click for anim)"); @@ -5525,22 +5533,26 @@ void view3d_header_buttons(const bContext *C, ARegion *ar) uiBlockBeginAlign(block); uiDefIconBut(block, BUT, B_ACTCOPY, ICON_COPYDOWN, - xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, + xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Copies the current pose to the buffer"); uiBlockSetButLock(block, object_data_is_libdata(ob), "Can't edit external libdata"); + xco+= XIC; + uiDefIconBut(block, BUT, B_ACTPASTE, ICON_PASTEDOWN, - xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, + xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the pose from the buffer"); + xco+= XIC; uiDefIconBut(block, BUT, B_ACTPASTEFLIP, ICON_PASTEFLIPDOWN, - xco+=XIC,yco,XIC,YIC, 0, 0, 0, 0, 0, + xco,yco,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the mirrored pose from the buffer"); - uiBlockEndAlign(block); + header_xco_step(ar, &xco, &yco, &maxco, XIC); + } } /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); + UI_view2d_totRect_set(&ar->v2d, maxco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 4ccfc7e8a81..4de7f645bfa 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -195,7 +195,9 @@ /* **************** BLENDER GESTURE EVENTS ********************* */ -#define EVT_ACTIONZONE 0x5001 +#define EVT_ACTIONZONE_AREA 0x5000 +#define EVT_ACTIONZONE_REGION 0x5001 + /* tweak events, for L M R mousebuttons */ #define EVT_TWEAK_L 0x5002 #define EVT_TWEAK_M 0x5003 |