Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/screen/screen_edit.c
| Show First 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new) | ||||
| screen_new->winid = win->winid; | screen_new->winid = win->winid; | ||||
| screen_new->do_refresh = true; | screen_new->do_refresh = true; | ||||
| 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) | ||||
HooglyBoogly: Looks like this should be made static now? Also Personal thing-- I'm not a big fan of the `_ex`… | |||||
| { | { | ||||
| 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) | |||||
Not Done Inline ActionsLooks like this can be made static HooglyBoogly: Looks like this can be made static | |||||
| { | |||||
| 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); | ||||
| if (win->tag_cursor_refresh || swin_changed || (region->type && region->type->event_cursor)) { | if (win->tag_cursor_refresh || swin_changed || (region->type && region->type->event_cursor)) { | ||||
| win->tag_cursor_refresh = false; | win->tag_cursor_refresh = false; | ||||
| ED_region_cursor_set(win, area, region); | ED_region_cursor_set(win, area, region); | ||||
| } | } | ||||
| } | } | ||||
| static void region_cursor_set(wmWindow *win, bool swin_changed) | static void region_cursor_set(wmWindow *win, bool swin_changed) | ||||
| { | { | ||||
| bScreen *screen = WM_window_get_active_screen(win); | bScreen *screen = WM_window_get_active_screen(win); | ||||
| ED_screen_areas_iter (win, screen, area) { | ED_screen_areas_iter (win, screen, area) { | ||||
| LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { | LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { | ||||
| if (region == screen->active_region) { | if (region == screen->active_region) { | ||||
| region_cursor_set_ex(win, area, region, swin_changed); | region_cursor_set_ex(win, area, region, swin_changed); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
Not Done Inline ActionsI'd declare those in a smaller scope, offset1, offset2 and dir can be declared inside the loop even (the compiler will still only declare it once, not every iteration), smallest can be declared just before the loop. Severin: I'd declare those in a smaller scope, `offset1`, `offset2` and `dir` can be declared inside the… | |||||
| } | } | ||||
| } | } | ||||
| void ED_screen_do_listen(bContext *C, wmNotifier *note) | void ED_screen_do_listen(bContext *C, wmNotifier *note) | ||||
| { | { | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| bScreen *screen = CTX_wm_screen(C); | bScreen *screen = CTX_wm_screen(C); | ||||
Not Done Inline ActionsEven if this is covered by the operator precedence, I'd always suggest doing a > (b + c) as opposed to a > b + c, for clarity/readability. Severin: Even if this is covered by the operator precedence, I'd always suggest doing `a > (b + c)` as… | |||||
| /* generic notes */ | /* generic notes */ | ||||
| switch (note->category) { | switch (note->category) { | ||||
Not Done Inline ActionsUnused variable HooglyBoogly: Unused variable | |||||
| case NC_WM: | case NC_WM: | ||||
| if (note->data == ND_FILEREAD) { | if (note->data == ND_FILEREAD) { | ||||
| screen->do_draw = true; | screen->do_draw = true; | ||||
| } | } | ||||
| break; | break; | ||||
| case NC_WINDOW: | case NC_WINDOW: | ||||
| screen->do_draw = true; | screen->do_draw = true; | ||||
| break; | break; | ||||
| case NC_SCREEN: | case NC_SCREEN: | ||||
| if (note->action == NA_EDITED) { | if (note->action == NA_EDITED) { | ||||
| screen->do_draw = screen->do_refresh = true; | screen->do_draw = screen->do_refresh = true; | ||||
| } | } | ||||
Not Done Inline Actionsconst Severin: `const` | |||||
| break; | break; | ||||
Not Done Inline ActionsUse bool / true and false? (Same for screen_area_3wayjoin) HooglyBoogly: Use bool / true and false? (Same for `screen_area_3wayjoin`) | |||||
| case NC_SCENE: | case NC_SCENE: | ||||
| if (note->data == ND_MODE) { | if (note->data == ND_MODE) { | ||||
| region_cursor_set(win, true); | region_cursor_set(win, true); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,274 Lines • Show Last 20 Lines | |||||
Looks like this should be made static now? Also Personal thing-- I'm not a big fan of the _ex suffix on functions. Maybe _and_offsets would be more helpful? Do whatever you prefer though : )