Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/screen/screen_edit.c
| Show First 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | static void screen_delarea(bContext *C, bScreen *screen, ScrArea *area) | ||||
| BLI_remlink(&screen->areabase, area); | BLI_remlink(&screen->areabase, area); | ||||
| MEM_freeN(area); | MEM_freeN(area); | ||||
| } | } | ||||
| ScrArea *area_split(const wmWindow *win, | ScrArea *area_split(const wmWindow *win, | ||||
| bScreen *screen, | bScreen *screen, | ||||
| ScrArea *area, | ScrArea *area, | ||||
| char dir, | const eScreenAxis dir_axis, | ||||
| const float fac, | const float fac, | ||||
| const bool merge) | const bool merge) | ||||
| { | { | ||||
| ScrArea *newa = NULL; | ScrArea *newa = NULL; | ||||
| if (area == NULL) { | if (area == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| rcti window_rect; | rcti window_rect; | ||||
| WM_window_rect_calc(win, &window_rect); | WM_window_rect_calc(win, &window_rect); | ||||
| short split = screen_geom_find_area_split_point(area, &window_rect, dir, fac); | short split = screen_geom_find_area_split_point(area, &window_rect, dir_axis, fac); | ||||
| if (split == 0) { | if (split == 0) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* note regarding (fac > 0.5f) checks below. | /* note regarding (fac > 0.5f) checks below. | ||||
| * normally it shouldn't matter which is used since the copy should match the original | * normally it shouldn't matter which is used since the copy should match the original | ||||
| * however with viewport rendering and python console this isn't the case. - campbell */ | * however with viewport rendering and python console this isn't the case. - campbell */ | ||||
| if (dir == 'h') { | if (dir_axis == SCREEN_AXIS_H) { | ||||
| /* new vertices */ | /* new vertices */ | ||||
| ScrVert *sv1 = screen_geom_vertex_add(screen, area->v1->vec.x, split); | ScrVert *sv1 = screen_geom_vertex_add(screen, area->v1->vec.x, split); | ||||
| ScrVert *sv2 = screen_geom_vertex_add(screen, area->v4->vec.x, split); | ScrVert *sv2 = screen_geom_vertex_add(screen, area->v4->vec.x, split); | ||||
| /* new edges */ | /* new edges */ | ||||
| screen_geom_edge_add(screen, area->v1, sv1); | screen_geom_edge_add(screen, area->v1, sv1); | ||||
| screen_geom_edge_add(screen, sv1, area->v2); | screen_geom_edge_add(screen, sv1, area->v2); | ||||
| screen_geom_edge_add(screen, area->v3, sv2); | screen_geom_edge_add(screen, area->v3, sv2); | ||||
| ▲ Show 20 Lines • Show All 142 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 `sa_a` as center, `sa_b` is located at: 0=W, 1=N, 2=E, 3=S | * with `sa_a` as center, `sa_b` 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 *sa_a, ScrArea *sa_b) | eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b) | ||||
| { | { | ||||
| if (sa_a == NULL || sa_b == NULL || sa_a == sa_b) { | if (sa_a == NULL || sa_b == NULL || sa_a == sa_b) { | ||||
| return -1; | return SCREEN_DIR_NONE; | ||||
| } | } | ||||
| const vec2s *sa_bl = &sa_a->v1->vec; | const vec2s *sa_bl = &sa_a->v1->vec; | ||||
| const vec2s *sa_tl = &sa_a->v2->vec; | const vec2s *sa_tl = &sa_a->v2->vec; | ||||
| const vec2s *sa_tr = &sa_a->v3->vec; | const vec2s *sa_tr = &sa_a->v3->vec; | ||||
| const vec2s *sa_br = &sa_a->v4->vec; | const vec2s *sa_br = &sa_a->v4->vec; | ||||
| const vec2s *sb_bl = &sa_b->v1->vec; | const vec2s *sb_bl = &sa_b->v1->vec; | ||||
| Show All 23 Lines | eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b) | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| /** | /** | ||||
| * Get alignment offset of adjacent areas. 'dir' value is like #area_getorientation(). | * Get alignment offset of adjacent areas. 'dir' value is like #area_getorientation(). | ||||
| */ | */ | ||||
| void area_getoffsets(ScrArea *sa_a, ScrArea *sa_b, const int dir, int *r_offset1, int *r_offset2) | void area_getoffsets( | ||||
| ScrArea *sa_a, ScrArea *sa_b, const eScreenDir dir, int *r_offset1, int *r_offset2) | |||||
| { | { | ||||
| if (sa_a == NULL || sa_b == NULL) { | if (sa_a == NULL || sa_b == NULL) { | ||||
| *r_offset1 = INT_MAX; | *r_offset1 = INT_MAX; | ||||
| *r_offset2 = INT_MAX; | *r_offset2 = INT_MAX; | ||||
| } | } | ||||
| else if (dir == 0) { /* West: sa on right and sa_b to the left. */ | else if (dir == SCREEN_DIR_W) { /* West: sa on right and sa_b to the left. */ | ||||
| *r_offset1 = sa_b->v3->vec.y - sa_a->v2->vec.y; | *r_offset1 = sa_b->v3->vec.y - sa_a->v2->vec.y; | ||||
| *r_offset2 = sa_b->v4->vec.y - sa_a->v1->vec.y; | *r_offset2 = sa_b->v4->vec.y - sa_a->v1->vec.y; | ||||
| } | } | ||||
| else if (dir == 1) { /* North: sa below and sa_b above. */ | else if (dir == SCREEN_DIR_N) { /* North: sa below and sa_b above. */ | ||||
| *r_offset1 = sa_a->v2->vec.x - sa_b->v1->vec.x; | *r_offset1 = sa_a->v2->vec.x - sa_b->v1->vec.x; | ||||
| *r_offset2 = sa_a->v3->vec.x - sa_b->v4->vec.x; | *r_offset2 = sa_a->v3->vec.x - sa_b->v4->vec.x; | ||||
| } | } | ||||
| else if (dir == 2) { /* East: sa on left and sa_b to the right. */ | else if (dir == SCREEN_DIR_E) { /* East: sa on left and sa_b to the right. */ | ||||
| *r_offset1 = sa_b->v2->vec.y - sa_a->v3->vec.y; | *r_offset1 = sa_b->v2->vec.y - sa_a->v3->vec.y; | ||||
| *r_offset2 = sa_b->v1->vec.y - sa_a->v4->vec.y; | *r_offset2 = sa_b->v1->vec.y - sa_a->v4->vec.y; | ||||
| } | } | ||||
| else if (dir == 3) { /* South: sa above and sa_b below. */ | else if (dir == SCREEN_DIR_S) { /* South: sa above and sa_b below. */ | ||||
| *r_offset1 = sa_a->v1->vec.x - sa_b->v2->vec.x; | *r_offset1 = sa_a->v1->vec.x - sa_b->v2->vec.x; | ||||
| *r_offset2 = sa_a->v4->vec.x - sa_b->v3->vec.x; | *r_offset2 = sa_a->v4->vec.x - sa_b->v3->vec.x; | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(dir == SCREEN_DIR_NONE); | |||||
| *r_offset1 = INT_MAX; | *r_offset1 = INT_MAX; | ||||
| *r_offset2 = INT_MAX; | *r_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, | ||||
| Show All 20 Lines | if (v1->vec.y == from_y) { | ||||
| v1->vec.y = to_y; | v1->vec.y = to_y; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation(). | /* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation(). | ||||
| */ | */ | ||||
| static void screen_areas_align( | static void screen_areas_align( | ||||
| bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const int dir) | bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const eScreenDir dir) | ||||
| { | { | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| if (ELEM(dir, 0, 2)) { | if (SCREEN_DIR_IS_HORIZONTAL(dir)) { | ||||
| /* horizontal join, use average for new top and bottom. */ | /* horizontal join, use average for new top and bottom. */ | ||||
| int top = (sa1->v2->vec.y + sa2->v2->vec.y) / 2; | int top = (sa1->v2->vec.y + sa2->v2->vec.y) / 2; | ||||
| int bottom = (sa1->v4->vec.y + sa2->v4->vec.y) / 2; | int bottom = (sa1->v4->vec.y + sa2->v4->vec.y) / 2; | ||||
| /* Move edges exactly matching source top and bottom. */ | /* Move edges exactly matching source top and bottom. */ | ||||
| screen_verts_valign(win, screen, sa1->v2->vec.y, top); | screen_verts_valign(win, screen, sa1->v2->vec.y, top); | ||||
| screen_verts_valign(win, screen, sa1->v4->vec.y, bottom); | screen_verts_valign(win, screen, sa1->v4->vec.y, bottom); | ||||
| Show All 14 Lines | else { | ||||
| 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); | ||||
| } | } | ||||
| } | } | ||||
| /* Simple join of two areas without any splitting. Will return false if not possible. */ | /* Simple join of two areas without any splitting. Will return false if not possible. */ | ||||
| static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2) | static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2) | ||||
| { | { | ||||
| int dir = area_getorientation(sa1, sa2); | const eScreenDir dir = area_getorientation(sa1, sa2); | ||||
| if (dir == -1) { | if (dir == SCREEN_DIR_NONE) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| int offset1; | int offset1; | ||||
| int offset2; | int offset2; | ||||
| area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | ||||
| int tolerance = ELEM(dir, 0, 2) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX; | int tolerance = SCREEN_DIR_IS_HORIZONTAL(dir) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX; | ||||
| if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) { | if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Align areas if they are not. */ | /* 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 == SCREEN_DIR_W) { /* sa1 to right of sa2 = West. */ | ||||
| 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); | ||||
| } | } | ||||
| else if (dir == 1) { /* sa1 to bottom of sa2 = N */ | else if (dir == SCREEN_DIR_N) { /* sa1 to bottom of sa2 = North. */ | ||||
| sa1->v2 = sa2->v2; /* TL */ | sa1->v2 = sa2->v2; /* TL */ | ||||
| sa1->v3 = sa2->v3; /* TR */ | sa1->v3 = sa2->v3; /* TR */ | ||||
| screen_geom_edge_add(screen, sa1->v1, sa1->v2); | screen_geom_edge_add(screen, sa1->v1, sa1->v2); | ||||
| screen_geom_edge_add(screen, sa1->v3, sa1->v4); | screen_geom_edge_add(screen, sa1->v3, sa1->v4); | ||||
| } | } | ||||
| else if (dir == 2) { /* sa1 to left of sa2 = E */ | else if (dir == SCREEN_DIR_E) { /* sa1 to left of sa2 = East. */ | ||||
| sa1->v3 = sa2->v3; /* TR */ | sa1->v3 = sa2->v3; /* TR */ | ||||
| sa1->v4 = sa2->v4; /* BR */ | sa1->v4 = sa2->v4; /* BR */ | ||||
| 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); | ||||
| } | } | ||||
| else if (dir == 3) { /* sa1 on top of sa2 = S */ | else if (dir == SCREEN_DIR_S) { /* sa1 on top of sa2 = South. */ | ||||
| sa1->v1 = sa2->v1; /* BL */ | sa1->v1 = sa2->v1; /* BL */ | ||||
| sa1->v4 = sa2->v4; /* BR */ | sa1->v4 = sa2->v4; /* BR */ | ||||
| screen_geom_edge_add(screen, sa1->v1, sa1->v2); | screen_geom_edge_add(screen, sa1->v1, sa1->v2); | ||||
| 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 true; | return true; | ||||
| } | } | ||||
| /* Slice off and return new area. "Reverse" gives right/bottom, rather than left/top. */ | /* Slice off and return new area. "Reverse" gives right/bottom, rather than left/top. */ | ||||
| static ScrArea *screen_area_trim( | static ScrArea *screen_area_trim( | ||||
| bContext *C, bScreen *screen, ScrArea **area, int size, int dir, bool reverse) | bContext *C, bScreen *screen, ScrArea **area, int size, eScreenDir dir, bool reverse) | ||||
| { | { | ||||
| bool vertical = ELEM(dir, 1, 3); | const bool vertical = SCREEN_DIR_IS_VERTICAL(dir); | ||||
| if (abs(size) < (vertical ? AREAJOINTOLERANCEX : AREAJOINTOLERANCEY)) { | if (abs(size) < (vertical ? AREAJOINTOLERANCEX : AREAJOINTOLERANCEY)) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* Measurement with ScrVerts because winx and winy might not be correct at this time. */ | /* 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) : | float fac = abs(size) / (float)(vertical ? ((*area)->v3->vec.x - (*area)->v1->vec.x) : | ||||
| ((*area)->v3->vec.y - (*area)->v1->vec.y)); | ((*area)->v3->vec.y - (*area)->v1->vec.y)); | ||||
| fac = (reverse == vertical) ? 1.0f - fac : fac; | fac = (reverse == vertical) ? 1.0f - fac : fac; | ||||
| ScrArea *newsa = area_split(CTX_wm_window(C), screen, *area, vertical ? 'v' : 'h', fac, true); | ScrArea *newsa = area_split( | ||||
| CTX_wm_window(C), screen, *area, vertical ? SCREEN_AXIS_V : SCREEN_AXIS_H, fac, true); | |||||
| /* area_split always returns smallest of the two areas, so might have to swap. */ | /* area_split always returns smallest of the two areas, so might have to swap. */ | ||||
| if (((fac > 0.5f) == vertical) != reverse) { | if (((fac > 0.5f) == vertical) != reverse) { | ||||
| ScrArea *temp = *area; | ScrArea *temp = *area; | ||||
| *area = newsa; | *area = newsa; | ||||
| newsa = temp; | newsa = temp; | ||||
| } | } | ||||
| return newsa; | return newsa; | ||||
| } | } | ||||
| /* Join any two neighboring areas. Might create new areas, kept if over min_remainder. */ | /* Join any two neighboring areas. Might create new areas, kept if over min_remainder. */ | ||||
| static bool screen_area_join_ex( | static bool screen_area_join_ex( | ||||
| bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, bool close_all_remainders) | bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, bool close_all_remainders) | ||||
| { | { | ||||
| int dir = area_getorientation(sa1, sa2); | const eScreenDir dir = area_getorientation(sa1, sa2); | ||||
| if (dir == -1) { | if (dir == SCREEN_DIR_NONE) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| int offset1; | int offset1; | ||||
| int offset2; | int offset2; | ||||
| area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | area_getoffsets(sa1, sa2, dir, &offset1, &offset2); | ||||
| /* Split Left/Top into new area if overhanging. */ | /* Split Left/Top into new area if overhanging. */ | ||||
| Show All 27 Lines | bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area) | ||||
| if (area == NULL) { | if (area == NULL) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| ScrArea *sa2 = NULL; | ScrArea *sa2 = NULL; | ||||
| float best_alignment = 0.0f; | float best_alignment = 0.0f; | ||||
| LISTBASE_FOREACH (ScrArea *, neighbor, &screen->areabase) { | LISTBASE_FOREACH (ScrArea *, neighbor, &screen->areabase) { | ||||
| int dir = area_getorientation(area, neighbor); | const eScreenDir dir = area_getorientation(area, neighbor); | ||||
| /* Must at least partially share an edge and not be a global area. */ | /* Must at least partially share an edge and not be a global area. */ | ||||
| if (dir != -1 && !neighbor->global) { | if ((dir != SCREEN_DIR_NONE) && (neighbor->global == NULL)) { | ||||
| /* Winx/Winy might not be updated yet, so get lengths from verts. */ | /* Winx/Winy might not be updated yet, so get lengths from verts. */ | ||||
| int area_length = ELEM(dir, 1, 3) ? area->v3->vec.x - area->v1->vec.x : | const bool vertical = SCREEN_DIR_IS_VERTICAL(dir); | ||||
| area->v3->vec.y - area->v1->vec.y; | int area_length = vertical ? (area->v3->vec.x - area->v1->vec.x) : | ||||
| int ar_length = ELEM(dir, 1, 3) ? neighbor->v3->vec.x - neighbor->v1->vec.x : | (area->v3->vec.y - area->v1->vec.y); | ||||
| neighbor->v3->vec.y - neighbor->v1->vec.y; | int ar_length = vertical ? (neighbor->v3->vec.x - neighbor->v1->vec.x) : | ||||
| (neighbor->v3->vec.y - neighbor->v1->vec.y); | |||||
| /* Calculate the ratio of the lengths of the shared edges. */ | /* Calculate the ratio of the lengths of the shared edges. */ | ||||
| float alignment = MIN2(area_length, ar_length) / (float)MAX2(area_length, ar_length); | float alignment = MIN2(area_length, ar_length) / (float)MAX2(area_length, ar_length); | ||||
| if (alignment > best_alignment) { | if (alignment > best_alignment) { | ||||
| best_alignment = alignment; | best_alignment = alignment; | ||||
| sa2 = neighbor; | sa2 = neighbor; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,333 Lines • Show Last 20 Lines | |||||