diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 5c4dd92eea3..b298c306699 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -986,8 +986,9 @@ void ED_screen_do_listen(wmWindow *win, wmNotifier *note) void ED_screen_draw(wmWindow *win) { ScrArea *sa; - ScrArea *sa1=NULL; - ScrArea *sa2=NULL; + ScrArea *sa1= NULL; + ScrArea *sa2= NULL; + ScrArea *sa3= NULL; int dir = -1; int dira = -1; @@ -996,6 +997,7 @@ void ED_screen_draw(wmWindow *win) for(sa= win->screen->areabase.first; sa; sa= sa->next) { if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa; if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa; + if (sa->flag & (AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V)) sa3 = sa; drawscredge_area(sa, win->sizex, win->sizey, 0); } for(sa= win->screen->areabase.first; sa; sa= sa->next) @@ -1028,7 +1030,25 @@ void ED_screen_draw(wmWindow *win) scrarea_draw_shape_light(sa1, dira); } -// if(G.f & G_DEBUG) printf("draw screen\n"); + /* splitpoint */ + if(sa3) { + glEnable(GL_BLEND); + glColor4ub(255, 255, 255, 100); + + if(sa3->flag & AREA_FLAG_DRAWSPLIT_H) { + sdrawline(sa3->totrct.xmin, win->eventstate->y, sa3->totrct.xmax, win->eventstate->y); + glColor4ub(0, 0, 0, 100); + sdrawline(sa3->totrct.xmin, win->eventstate->y+1, sa3->totrct.xmax, win->eventstate->y+1); + } + else { + sdrawline(win->eventstate->x, sa3->totrct.ymin, win->eventstate->x, sa3->totrct.ymax); + glColor4ub(0, 0, 0, 100); + sdrawline(win->eventstate->x+1, sa3->totrct.ymin, win->eventstate->x+1, sa3->totrct.ymax); + } + + glDisable(GL_BLEND); + } + win->screen->do_draw= 0; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 4c423ef4451..e7368e075f9 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1094,21 +1094,44 @@ static void SCREEN_OT_area_move(wmOperatorType *ot) #define SPLIT_STARTED 1 #define SPLIT_PROGRESS 2 -typedef struct sAreaSplitData - { - int x, y; /* last used mouse position */ - - int origval; /* for move areas */ - int bigger, smaller; /* constraints for moving new edge */ - int delta; /* delta move edge */ - int origmin, origsize; /* to calculate fac, for property storage */ - - ScrEdge *nedge; /* new edge */ - ScrArea *sarea; /* start area */ - ScrArea *narea; /* new area */ - } sAreaSplitData; +typedef struct sAreaSplitData { + int x, y; /* last used mouse position */ + + int origval; /* for move areas */ + int bigger, smaller; /* constraints for moving new edge */ + int delta; /* delta move edge */ + int origmin, origsize; /* to calculate fac, for property storage */ + int previewmode; /* draw previewline, then split */ + + ScrEdge *nedge; /* new edge */ + ScrArea *sarea; /* start area */ + ScrArea *narea; /* new area */ + +} sAreaSplitData; -/* generic init, no UI stuff here */ +/* generic init, menu case, doesn't need active area */ +static int area_split_menu_init(bContext *C, wmOperator *op) +{ + sAreaSplitData *sd; + + /* custom data */ + sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split"); + op->customdata= sd; + + sd->sarea= CTX_wm_area(C); + + if(sd->sarea) { + int dir= RNA_enum_get(op->ptr, "direction"); + + if(dir=='h') + sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_H; + else + sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_V; + } + return 1; +} + +/* generic init, no UI stuff here, assumes active area */ static int area_split_init(bContext *C, wmOperator *op) { ScrArea *sa= CTX_wm_area(C); @@ -1212,6 +1235,9 @@ static void area_split_exit(bContext *C, wmOperator *op) if(sd->sarea) ED_area_tag_redraw(sd->sarea); if(sd->narea) ED_area_tag_redraw(sd->narea); + if(sd->sarea) + sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V); + MEM_freeN(op->customdata); op->customdata = NULL; } @@ -1228,18 +1254,15 @@ static void area_split_exit(bContext *C, wmOperator *op) static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) { sAreaSplitData *sd; + int dir; if(event->type==EVT_ACTIONZONE_AREA) { sActionzoneData *sad= event->customdata; - int dir; if(sad->modifier>0) { return OPERATOR_PASS_THROUGH; } - /* no full window splitting allowed */ - if(CTX_wm_area(C)->full) - return OPERATOR_PASS_THROUGH; /* verify *sad itself */ if(sad==NULL || sad->sa1==NULL || sad->az==NULL) @@ -1264,10 +1287,46 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) if(!area_split_init(C, op)) return OPERATOR_PASS_THROUGH; - sd= (sAreaSplitData *)op->customdata; + } + else { + ScrEdge *actedge; + int x, y; - sd->x= event->x; - sd->y= event->y; + /* no full window splitting allowed */ + if(CTX_wm_area(C) && CTX_wm_area(C)->full) + return OPERATOR_CANCELLED; + + /* retrieve initial mouse coord, so we can find the active edge */ + if(RNA_property_is_set(op->ptr, "mouse_x")) + x= RNA_int_get(op->ptr, "mouse_x"); + else + x= event->x; + + if(RNA_property_is_set(op->ptr, "mouse_y")) + y= RNA_int_get(op->ptr, "mouse_y"); + else + y= event->x; + + actedge= screen_find_active_scredge(CTX_wm_screen(C), x, y); + if(actedge==NULL) + return OPERATOR_CANCELLED; + + dir= scredge_is_horizontal(actedge)?'v':'h'; + + RNA_enum_set(op->ptr, "direction", dir); + + /* special case, adds customdata, sets defaults */ + if(!area_split_menu_init(C, op)) + return OPERATOR_CANCELLED; + + } + + sd= (sAreaSplitData *)op->customdata; + + sd->x= event->x; + sd->y= event->y; + + if(event->type==EVT_ACTIONZONE_AREA) { /* do the split */ if(area_split_apply(C, op)) { @@ -1278,11 +1337,14 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } - } else { - /* nonmodal for now */ - return op->type->exec(C, op); + sd->previewmode= 1; + /* add temp handler for edge move or cancel */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } return OPERATOR_PASS_THROUGH; @@ -1306,12 +1368,16 @@ static int area_split_cancel(bContext *C, wmOperator *op) { sAreaSplitData *sd= (sAreaSplitData *)op->customdata; - if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) { - if (CTX_wm_area(C) == sd->narea) { - CTX_wm_area_set(C, NULL); - CTX_wm_region_set(C, NULL); + if(sd->previewmode) { + } + else { + if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) { + if (CTX_wm_area(C) == sd->narea) { + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); + } + sd->narea = NULL; } - sd->narea = NULL; } area_split_exit(C, op); @@ -1330,17 +1396,47 @@ static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event) dir= RNA_enum_get(op->ptr, "direction"); sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval; - area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller); + if(sd->previewmode==0) + area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller); + else { + if(sd->sarea) { + sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V); + ED_area_tag_redraw(sd->sarea); + } + sd->sarea= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* area context not set */ + + if(sd->sarea) { + ED_area_tag_redraw(sd->sarea); + if (dir=='v') { + sd->origsize= sd->sarea->winx; + sd->origmin= sd->sarea->totrct.xmin; + sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_V; + } + else { + sd->origsize= sd->sarea->winy; + sd->origmin= sd->sarea->totrct.ymin; + sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_H; + } + } + } fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin; RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize); + break; case LEFTMOUSE: - if(event->val==KM_RELEASE) { /* mouse up */ + if(sd->previewmode) { + area_split_apply(C, op); area_split_exit(C, op); return OPERATOR_FINISHED; } + else { + if(event->val==KM_RELEASE) { /* mouse up */ + area_split_exit(C, op); + return OPERATOR_FINISHED; + } + } break; case RIGHTMOUSE: /* cancel operation */ case ESCKEY: @@ -1365,12 +1461,14 @@ static void SCREEN_OT_area_split(wmOperatorType *ot) ot->invoke= area_split_invoke; ot->modal= area_split_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_screenactive; ot->flag= OPTYPE_BLOCKING; /* rna */ RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", ""); RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0); + RNA_def_int(ot->srna, "mouse_x", -100, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "mouse_y", -100, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX); } @@ -1866,6 +1964,7 @@ static int area_join_init(bContext *C, wmOperator *op) sAreaJoinData* jd= NULL; int x1, y1; int x2, y2; + int shared= 0; /* required properties, make negative to get return 0 if not set by caller */ x1= RNA_int_get(op->ptr, "min_x"); @@ -1878,6 +1977,16 @@ static int area_join_init(bContext *C, wmOperator *op) if(sa1==NULL || sa2==NULL || sa1==sa2) return 0; + /* do areas share an edge? */ + if(sa1->v1==sa2->v1 || sa1->v1==sa2->v2 || sa1->v1==sa2->v3 || sa1->v1==sa2->v4) shared++; + if(sa1->v2==sa2->v1 || sa1->v2==sa2->v2 || sa1->v2==sa2->v3 || sa1->v2==sa2->v4) shared++; + if(sa1->v3==sa2->v1 || sa1->v3==sa2->v2 || sa1->v3==sa2->v3 || sa1->v3==sa2->v4) shared++; + if(sa1->v4==sa2->v1 || sa1->v4==sa2->v2 || sa1->v4==sa2->v3 || sa1->v4==sa2->v4) shared++; + if(shared!=2) { + printf("areas don't share edge\n"); + return 0; + } + jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join"); jd->sa1 = sa1; @@ -1956,17 +2065,16 @@ static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) RNA_int_set(op->ptr, "min_y", sad->y); RNA_int_set(op->ptr, "max_x", event->x); RNA_int_set(op->ptr, "max_y", event->y); - - if(!area_join_init(C, op)) - return OPERATOR_PASS_THROUGH; - - /* add temp handler */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; } - return OPERATOR_PASS_THROUGH; + + if(!area_join_init(C, op)) + return OPERATOR_PASS_THROUGH; + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; } static int area_join_cancel(bContext *C, wmOperator *op) @@ -2092,7 +2200,7 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) ot->exec= area_join_exec; ot->invoke= area_join_invoke; ot->modal= area_join_modal; - ot->poll= ED_operator_areaactive; + ot->poll= ED_operator_screenactive; ot->flag= OPTYPE_BLOCKING; @@ -2103,6 +2211,58 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX); } +/* ******************************* */ + +static int screen_area_options_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + uiPopupMenu *pup; + uiLayout *layout; + PointerRNA ptr1, ptr2; + ScrEdge *actedge= screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y); + + if(actedge==NULL) return OPERATOR_CANCELLED; + + pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); + layout= uiPupMenuLayout(pup); + + WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join"); + + /* mouse cursor on edge, '4' can fail on wide edges... */ + RNA_int_set(&ptr1, "min_x", event->x+4); + RNA_int_set(&ptr1, "min_y", event->y+4); + RNA_int_set(&ptr1, "max_x", event->x-4); + RNA_int_set(&ptr1, "max_y", event->y-4); + + WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split"); + + /* store initial mouse cursor position */ + RNA_int_set(&ptr2, "mouse_x", event->x); + RNA_int_set(&ptr2, "mouse_y", event->y); + + uiItemFullO(layout, "SCREEN_OT_area_split", "Split Area", ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(layout, "SCREEN_OT_area_join", "Join Area", ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0); + + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + +static void SCREEN_OT_area_options(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Area Options"; + ot->description= "Operations for splitting and merging"; + ot->idname= "SCREEN_OT_area_options"; + + /* api callbacks */ + ot->invoke= screen_area_options_invoke; + + ot->poll= ED_operator_screen_mainwinactive; +} + + +/* ******************************* */ + static int spacedata_cleanup(bContext *C, wmOperator *op) { @@ -3048,6 +3208,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_area_move); WM_operatortype_append(SCREEN_OT_area_split); WM_operatortype_append(SCREEN_OT_area_join); + WM_operatortype_append(SCREEN_OT_area_options); WM_operatortype_append(SCREEN_OT_area_dupli); WM_operatortype_append(SCREEN_OT_area_swap); WM_operatortype_append(SCREEN_OT_region_quadview); @@ -3150,6 +3311,9 @@ void ED_keymap_screen(wmKeyConfig *keyconf) /* 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_options", RIGHTMOUSE, KM_PRESS, 0, 0); + + /* Header Editing ------------------------------------------------ */ keymap= WM_keymap_find(keyconf, "Header", 0, 0); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 381046daedc..cd19f4cb3de 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -184,6 +184,8 @@ typedef struct ARegion { #define AREA_FLAG_DRAWJOINTO 2 #define AREA_FLAG_DRAWJOINFROM 4 #define AREA_TEMP_INFO 8 +#define AREA_FLAG_DRAWSPLIT_H 16 +#define AREA_FLAG_DRAWSPLIT_V 32 /* If you change EDGEWIDTH, also do the global arrat edcol[] */ #define EDGEWIDTH 1