Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/screen/screen_edit.c
| Show First 20 Lines • Show All 278 Lines • ▼ Show 20 Lines | void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new) | ||||
| screen_new->do_draw = true; | screen_new->do_draw = true; | ||||
| } | } | ||||
| /* with area as center, sb is located at: 0=W, 1=N, 2=E, 3=S */ | /* with area as center, sb is located at: 0=W, 1=N, 2=E, 3=S */ | ||||
| /* -1 = not valid check */ | /* -1 = not valid check */ | ||||
| /* used with join operator */ | /* used with join operator */ | ||||
| int area_getorientation(ScrArea *area, ScrArea *sb) | int area_getorientation(ScrArea *area, ScrArea *sb) | ||||
| { | { | ||||
| if (area == NULL || sb == NULL) { | if (area == NULL || sb == NULL || area == sb) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| ScrVert *saBL = area->v1; | vec2s saBL = area->v1->vec; | ||||
| ScrVert *saTL = area->v2; | vec2s saTL = area->v2->vec; | ||||
| ScrVert *saTR = area->v3; | vec2s saTR = area->v3->vec; | ||||
| ScrVert *saBR = area->v4; | vec2s saBR = area->v4->vec; | ||||
| ScrVert *sbBL = sb->v1; | vec2s sbBL = sb->v1->vec; | ||||
| ScrVert *sbTL = sb->v2; | vec2s sbTL = sb->v2->vec; | ||||
| ScrVert *sbTR = sb->v3; | vec2s sbTR = sb->v3->vec; | ||||
| ScrVert *sbBR = sb->v4; | vec2s sbBR = sb->v4->vec; | ||||
| if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* area to right of sb = W */ | if (saBL.x == sbBR.x && saTL.x == sbTR.x) { /* area to right of sb = W */ | ||||
| if ((abs(saBL->vec.y - sbBR->vec.y) <= AREAJOINTOLERANCE) && | if ((MIN2(saTL.y, sbTR.y) - MAX2(saBL.y, sbBR.y)) > AREAJOINTOLERANCEY) { | ||||
| (abs(saTL->vec.y - sbTR->vec.y) <= AREAJOINTOLERANCE)) { | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| else if (saTL->vec.y == sbBL->vec.y && | else if (saTL.y == sbBL.y && saTR.y == sbBR.y) { /* area to bottom of sb = N */ | ||||
| saTR->vec.y == sbBR->vec.y) { /* area to bottom of sb = N */ | if ((MIN2(saTR.x, sbBR.x) - MAX2(saTL.x, sbBL.x)) > AREAJOINTOLERANCEX) { | ||||
| if ((abs(saTL->vec.x - sbBL->vec.x) <= AREAJOINTOLERANCE) && | |||||
| (abs(saTR->vec.x - sbBR->vec.x) <= AREAJOINTOLERANCE)) { | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| } | } | ||||
| else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* area to left of sb = E */ | else if (saTR.x == sbTL.x && saBR.x == sbBL.x) { /* area to left of sb = E */ | ||||
| if ((abs(saTR->vec.y - sbTL->vec.y) <= AREAJOINTOLERANCE) && | if ((MIN2(saTR.y, sbTL.y) - MAX2(saBR.y, sbBL.y)) > AREAJOINTOLERANCEY) { | ||||
| (abs(saBR->vec.y - sbBL->vec.y) <= AREAJOINTOLERANCE)) { | |||||
| return 2; | return 2; | ||||
| } | } | ||||
| } | } | ||||
| else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* area on top of sb = S*/ | else if (saBL.y == sbTL.y && saBR.y == sbTR.y) { /* area on top of sb = S */ | ||||
| if ((abs(saBL->vec.x - sbTL->vec.x) <= AREAJOINTOLERANCE) && | if ((MIN2(saBR.x, sbTR.x) - MAX2(saBL.x, sbTL.x)) > AREAJOINTOLERANCEX) { | ||||
| (abs(saBR->vec.x - sbTR->vec.x) <= AREAJOINTOLERANCE)) { | |||||
| return 3; | return 3; | ||||
| } | } | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| /* Get alignment offset of adjacent areas. 'dir' value is like area_getorientation(). */ | |||||
| void area_getoffsets(ScrArea *area, ScrArea *sb, const int dir, int *offset1, int *offset2) | |||||
| { | |||||
| if (area == NULL || sb == NULL) { | |||||
| *offset1 = INT_MAX; | |||||
| *offset2 = INT_MAX; | |||||
| } | |||||
| else if (dir == 0) { /* West: sa on right and sb to the left. */ | |||||
| *offset1 = sb->v3->vec.y - area->v2->vec.y; | |||||
| *offset2 = sb->v4->vec.y - area->v1->vec.y; | |||||
| } | |||||
| else if (dir == 1) { /* North: sa below and sb above. */ | |||||
| *offset1 = area->v2->vec.x - sb->v1->vec.x; | |||||
| *offset2 = area->v3->vec.x - sb->v4->vec.x; | |||||
| } | |||||
| else if (dir == 2) { /* East: sa on left and sb to the right. */ | |||||
| *offset1 = sb->v2->vec.y - area->v3->vec.y; | |||||
| *offset2 = sb->v1->vec.y - area->v4->vec.y; | |||||
| } | |||||
| else if (dir == 3) { /* South: sa above and sb below. */ | |||||
| *offset1 = area->v1->vec.x - sb->v2->vec.x; | |||||
| *offset2 = area->v4->vec.x - sb->v3->vec.x; | |||||
| } | |||||
| else { | |||||
| *offset1 = INT_MAX; | |||||
| *offset2 = INT_MAX; | |||||
| } | |||||
| } | |||||
| /* Screen verts with horizontal position equal to from_x are moved to to_x. */ | /* Screen verts with horizontal position equal to from_x are moved to to_x. */ | ||||
| static void screen_verts_halign(const wmWindow *win, | static void screen_verts_halign(const wmWindow *win, | ||||
| const bScreen *screen, | const bScreen *screen, | ||||
| const short from_x, | const short from_x, | ||||
| const short to_x) | const short to_x) | ||||
| { | { | ||||
| ED_screen_verts_iter(win, screen, v1) | ED_screen_verts_iter(win, screen, v1) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else { | ||||
| screen_verts_halign(win, screen, sa1->v3->vec.x, right); | screen_verts_halign(win, screen, sa1->v3->vec.x, right); | ||||
| /* Move edges exactly matching target left and right */ | /* Move edges exactly matching target left and right */ | ||||
| screen_verts_halign(win, screen, sa2->v1->vec.x, left); | screen_verts_halign(win, screen, sa2->v1->vec.x, left); | ||||
| screen_verts_halign(win, screen, sa2->v3->vec.x, right); | screen_verts_halign(win, screen, sa2->v3->vec.x, right); | ||||
| } | } | ||||
| } | } | ||||
| /* Helper function to join 2 areas, it has a return value, 0=failed 1=success | /* Simple join of two areas without any splitting. Will return false if not possible. */ | ||||
| * used by the split, join operators | static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2) | ||||
| */ | |||||
| int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2) | |||||
| { | { | ||||
| int dir = area_getorientation(sa1, sa2); | int dir = area_getorientation(sa1, sa2); | ||||
| if (dir == -1) { | if (dir == -1) { | ||||
| return 0; | return false; | ||||
| } | |||||
| int offset1; | |||||
| int offset2; | |||||
| area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | |||||
| int tolerance = ELEM(dir, 0, 2) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX; | |||||
| if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) { | |||||
| return false; | |||||
| } | } | ||||
| /* Align areas if they are not. Do sanity checking before getting here. */ | /* Align areas if they are not. */ | ||||
| screen_areas_align(C, screen, sa1, sa2, dir); | screen_areas_align(C, screen, sa1, sa2, dir); | ||||
| if (dir == 0) { /* sa1 to right of sa2 = W */ | if (dir == 0) { /* sa1 to right of sa2 = W */ | ||||
| sa1->v1 = sa2->v1; /* BL */ | sa1->v1 = sa2->v1; /* BL */ | ||||
| sa1->v2 = sa2->v2; /* TL */ | sa1->v2 = sa2->v2; /* TL */ | ||||
| screen_geom_edge_add(screen, sa1->v2, sa1->v3); | screen_geom_edge_add(screen, sa1->v2, sa1->v3); | ||||
| screen_geom_edge_add(screen, sa1->v1, sa1->v4); | screen_geom_edge_add(screen, sa1->v1, sa1->v4); | ||||
| } | } | ||||
| Show All 16 Lines | else if (dir == 3) { /* sa1 on top of sa2 = S */ | ||||
| screen_geom_edge_add(screen, sa1->v3, sa1->v4); | screen_geom_edge_add(screen, sa1->v3, sa1->v4); | ||||
| } | } | ||||
| screen_delarea(C, screen, sa2); | screen_delarea(C, screen, sa2); | ||||
| BKE_screen_remove_double_scrverts(screen); | BKE_screen_remove_double_scrverts(screen); | ||||
| /* Update preview thumbnail */ | /* Update preview thumbnail */ | ||||
| BKE_icon_changed(screen->id.icon_id); | BKE_icon_changed(screen->id.icon_id); | ||||
| return 1; | return true; | ||||
| } | |||||
| /* Slice off and return new area. "Reverse" gives right/bottom, rather than left/top. */ | |||||
| static ScrArea *screen_area_trim( | |||||
| bContext *C, bScreen *screen, ScrArea **area, int size, int dir, bool reverse) | |||||
| { | |||||
| bool vertical = ELEM(dir, 1, 3); | |||||
| if (abs(size) < (vertical ? AREAJOINTOLERANCEX : AREAJOINTOLERANCEY)) { | |||||
| return NULL; | |||||
| } | |||||
| /* Measurement with ScrVerts because winx and winy might not be correct at this time. */ | |||||
| float fac = abs(size) / (float)(vertical ? ((*area)->v3->vec.x - (*area)->v1->vec.x) : | |||||
| ((*area)->v3->vec.y - (*area)->v1->vec.y)); | |||||
| fac = (reverse == vertical) ? 1.0f - fac : fac; | |||||
| ScrArea *newsa = area_split(CTX_wm_window(C), screen, *area, vertical ? 'v' : 'h', fac, 1); | |||||
| /* area_split always returns smallest of the two areas, so might have to swap. */ | |||||
| if (((fac > 0.5f) == vertical) != reverse) { | |||||
| ScrArea *temp = *area; | |||||
| *area = newsa; | |||||
| newsa = temp; | |||||
| } | |||||
| return newsa; | |||||
| } | |||||
| /* Join any two neighboring areas. Might create new areas, kept if over min_remainder. */ | |||||
| static bool screen_area_join_ex( | |||||
| bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, bool close_all_remainders) | |||||
| { | |||||
| int dir = area_getorientation(sa1, sa2); | |||||
| if (dir == -1) { | |||||
| return false; | |||||
| } | |||||
| int offset1; | |||||
| int offset2; | |||||
| area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | |||||
| /* Split Left/Top into new area if overhanging. */ | |||||
| ScrArea *side1 = screen_area_trim(C, screen, (offset1 > 0) ? &sa2 : &sa1, offset1, dir, false); | |||||
| /* Split Right/Bottom into new area if overhanging. */ | |||||
| ScrArea *side2 = screen_area_trim(C, screen, (offset2 > 0) ? &sa1 : &sa2, offset2, dir, true); | |||||
| /* The two areas now line up, so join them. */ | |||||
| screen_area_join_aligned(C, screen, sa1, sa2); | |||||
| if (close_all_remainders || offset1 < 0 || offset2 > 0) { | |||||
| /* Close both if trimiming sa1. */ | |||||
| screen_area_close(C, screen, side1); | |||||
| screen_area_close(C, screen, side2); | |||||
| } | |||||
| BKE_icon_changed(screen->id.icon_id); | |||||
| return true; | |||||
| } | |||||
| /* Join any two neighboring areas. Might involve complex changes. */ | |||||
| int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2) | |||||
| { | |||||
| return screen_area_join_ex(C, screen, sa1, sa2, false); | |||||
| } | |||||
| /* Close a screen area, allowing any neighbor to take its place. */ | |||||
| bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area) | |||||
| { | |||||
| if (area == NULL) { | |||||
| return false; | |||||
| } | |||||
| ScrArea *sa2 = NULL; | |||||
| /* Find the most-aligned joinable area. Larger size breaks ties. */ | |||||
| int min_alignment = INT_MAX; | |||||
| int max_size = 0; | |||||
| LISTBASE_FOREACH (ScrArea *, ar, &screen->areabase) { | |||||
| int dir = area_getorientation(area, ar); | |||||
| if (dir != -1) { | |||||
| int offset1; | |||||
| int offset2; | |||||
| area_getoffsets(area, ar, dir, &offset1, &offset2); | |||||
| int area_alignment = abs(offset1) + abs(offset2); | |||||
| if (area_alignment < min_alignment) { | |||||
| min_alignment = area_alignment; | |||||
| max_size = ar->winx * ar->winy; | |||||
| sa2 = ar; | |||||
| } | |||||
| else if (area_alignment == min_alignment) { | |||||
| int area_size = ar->winx * ar->winy; | |||||
| if (area_size > max_size) { | |||||
| max_size = area_size; | |||||
| sa2 = ar; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return screen_area_join_ex(C, screen, sa2, area, true); | |||||
| } | } | ||||
| /* ****************** EXPORTED API TO OTHER MODULES *************************** */ | /* ****************** EXPORTED API TO OTHER MODULES *************************** */ | ||||
| /* screen sets cursor based on active region */ | /* screen sets cursor based on active region */ | ||||
| static void region_cursor_set_ex(wmWindow *win, ScrArea *area, ARegion *region, bool swin_changed) | static void region_cursor_set_ex(wmWindow *win, ScrArea *area, ARegion *region, bool swin_changed) | ||||
| { | { | ||||
| BLI_assert(WM_window_get_active_screen(win)->active_region == region); | BLI_assert(WM_window_get_active_screen(win)->active_region == region); | ||||
| ▲ Show 20 Lines • Show All 1,322 Lines • Show Last 20 Lines | |||||