WM: improved area resize snapping

Instead of 10px steps, snap to mid-point & adjacent edges.

Not yet implemented for split preview.
This commit is contained in:
Germano Cavalcante 2018-01-18 11:22:58 +11:00 committed by Campbell Barton
parent e6df02861e
commit 7ffe838473
1 changed files with 105 additions and 54 deletions

View File

@ -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;
}
/* 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 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(
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");