diff options
author | mano-wii <germano.costa@ig.com.br> | 2018-01-18 03:22:58 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-01-18 03:33:51 +0300 |
commit | 7ffe838473a7f0b4ac4e85b5e004e9e218a3769e (patch) | |
tree | e6d6e86929b6bc13d5c4edaf4545545a853dbebe /source/blender/editors/screen/screen_ops.c | |
parent | e6df02861e17f75d4dd243776f35208681b78465 (diff) |
WM: improved area resize snapping
Instead of 10px steps, snap to mid-point & adjacent edges.
Not yet implemented for split preview.
Diffstat (limited to 'source/blender/editors/screen/screen_ops.c')
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 157 |
1 files changed, 104 insertions, 53 deletions
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 908d218d353..176bdc764a2 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -87,8 +87,8 @@ #define KM_MODAL_CANCEL 1 #define KM_MODAL_APPLY 2 -#define KM_MODAL_STEP10 3 -#define KM_MODAL_STEP10_OFF 4 +#define KM_MODAL_SNAP_ON 3 +#define KM_MODAL_SNAP_OFF 4 /* ************** Exported Poll tests ********************** */ @@ -1077,8 +1077,9 @@ static void SCREEN_OT_area_dupli(wmOperatorType *ot) */ typedef struct sAreaMoveData { - int bigger, smaller, origval, step; + int bigger, smaller, origval; char dir; + bool do_snap; } sAreaMoveData; /* helper call to move area-edge, sets limits @@ -1170,55 +1171,101 @@ static int area_move_init(bContext *C, wmOperator *op) return 1; } +static int area_snap_calc_location( + const bScreen *sc, const int delta, + const int origval, const int dir, + const int bigger, const int smaller) +{ + int final_loc = -1; + + const int m_loc = origval + delta; + const int axis = (dir == 'v') ? 0 : 1; + int snap_dist = INT_MAX; + int dist; + { + /* Test the snap to middle. */ + int middle = origval + (bigger - smaller) / 2; + middle -= (middle % AREAGRID); + + dist = abs(m_loc - middle); + if (dist <= snap_dist) { + snap_dist = dist; + final_loc = middle; + } + } + + for (const ScrVert *v1 = sc->vertbase.first; v1; v1 = v1->next) { + if (v1->editflag) { + const int v_loc = (&v1->vec.x)[!axis]; + + for (const ScrVert *v2 = sc->vertbase.first; v2; v2 = v2->next) { + if (!v2->editflag) { + if (v_loc == (&v2->vec.x)[!axis]) { + const int v_loc2 = (&v2->vec.x)[axis]; + /* Do not snap to the vertices at the ends. */ + if ((origval - smaller) < v_loc2 && v_loc2 < (origval + bigger)) { + dist = abs(m_loc - v_loc2); + if (dist <= snap_dist) { + snap_dist = dist; + final_loc = v_loc2; + } + } + } + } + } + } + } + + return final_loc; +} + /* moves selected screen edge amount of delta, used by split & move */ -static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller) +static void area_move_apply_do( + const bContext *C, int delta, + const int origval, const int dir, + const int bigger, const int smaller, + const bool do_snap) { - wmWindow *win = CTX_wm_window(C); - const int winsize_x = WM_window_pixels_x(win); - const int winsize_y = WM_window_pixels_y(win); bScreen *sc = CTX_wm_screen(C); ScrVert *v1; - ScrArea *sa; - int doredraw = 0; - int oldval; - - delta = CLAMPIS(delta, -smaller, bigger); - + bool doredraw = false; + CLAMP(delta, -smaller, bigger); + + short final_loc = -1; + + if (do_snap) { + final_loc = area_snap_calc_location(sc, delta, origval, dir, bigger, smaller); + } + else { + final_loc = origval + delta; + if (delta != bigger && delta != -smaller) { + final_loc -= (final_loc % AREAGRID); + } + } + + BLI_assert(final_loc != -1); + short axis = (dir == 'v') ? 0 : 1; + for (v1 = sc->vertbase.first; v1; v1 = v1->next) { if (v1->editflag) { - /* that way a nice AREAGRID */ - if ((dir == 'v') && v1->vec.x > 0 && v1->vec.x < winsize_x - 1) { - oldval = v1->vec.x; - v1->vec.x = origval + delta; - - if (delta != bigger && delta != -smaller) { - v1->vec.x -= (v1->vec.x % AREAGRID); - v1->vec.x = CLAMPIS(v1->vec.x, origval - smaller, origval + bigger); - } - if (oldval != v1->vec.x) - doredraw = 1; - } - if ((dir == 'h') && v1->vec.y > 0 && v1->vec.y < winsize_y - 1) { - oldval = v1->vec.y; - v1->vec.y = origval + delta; - - if (delta != bigger && delta != smaller) { - v1->vec.y -= (v1->vec.y % AREAGRID); - v1->vec.y = CLAMPIS(v1->vec.y, origval - smaller, origval + bigger); - } - if (oldval != v1->vec.y) - doredraw = 1; + short oldval = (&v1->vec.x)[axis]; + (&v1->vec.x)[axis] = final_loc; + + if (oldval == final_loc) { + /* nothing will change to the other vertices either. */ + break; } + doredraw = true; } } /* only redraw if we actually moved a screen vert, for AREAGRID */ if (doredraw) { - for (sa = sc->areabase.first; sa; sa = sa->next) { - if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag) + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + if (sa->v1->editflag || sa->v2->editflag || sa->v3->editflag || sa->v4->editflag) { ED_area_tag_redraw(sa); + } } - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); /* redraw everything */ } } @@ -1226,10 +1273,9 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int static void area_move_apply(bContext *C, wmOperator *op) { sAreaMoveData *md = op->customdata; - int delta; - - delta = RNA_int_get(op->ptr, "delta"); - area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller); + int delta = RNA_int_get(op->ptr, "delta"); + + area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->do_snap); } static void area_move_exit(bContext *C, wmOperator *op) @@ -1291,7 +1337,6 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) y = RNA_int_get(op->ptr, "y"); delta = (md->dir == 'v') ? event->x - x : event->y - y; - if (md->step) delta = delta - (delta % md->step); RNA_int_set(op->ptr, "delta", delta); area_move_apply(C, op); @@ -1307,12 +1352,12 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) case KM_MODAL_CANCEL: area_move_cancel(C, op); return OPERATOR_CANCELLED; - - case KM_MODAL_STEP10: - md->step = 10; + + case KM_MODAL_SNAP_ON: + md->do_snap = true; break; - case KM_MODAL_STEP10_OFF: - md->step = 0; + case KM_MODAL_SNAP_OFF: + md->do_snap = false; break; } break; @@ -1388,6 +1433,7 @@ typedef struct sAreaSplitData { int delta; /* delta move edge */ int origmin, origsize; /* to calculate fac, for property storage */ int previewmode; /* draw previewline, then split */ + bool do_snap; ScrEdge *nedge; /* new edge */ ScrArea *sarea; /* start area */ @@ -1686,8 +1732,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval; if (sd->previewmode == 0) - area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller); + area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, sd->do_snap); else { + /* TODO: Snap in preview mode too. */ if (sd->sarea) { sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V); ED_area_tag_redraw(sd->sarea); @@ -1766,6 +1813,10 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) case ESCKEY: area_split_cancel(C, op); return OPERATOR_CANCELLED; + + case LEFTCTRLKEY: + sd->do_snap = event->val == KM_PRESS; + break; } return OPERATOR_RUNNING_MODAL; @@ -4298,8 +4349,8 @@ static void keymap_modal_set(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""}, - {KM_MODAL_STEP10, "STEP10", 0, "Steps on", ""}, - {KM_MODAL_STEP10_OFF, "STEP10_OFF", 0, "Steps off", ""}, + {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap on", ""}, + {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""}, {0, NULL, 0, NULL, NULL}}; wmKeyMap *keymap; @@ -4311,8 +4362,8 @@ static void keymap_modal_set(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_STEP10); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_STEP10_OFF); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_SNAP_ON); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_SNAP_OFF); WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move"); |