Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarley Acheson <harley.acheson@gmail.com>2020-05-28 21:34:31 +0300
committerHarley Acheson <harley.acheson@gmail.com>2020-05-28 21:34:31 +0300
commit2deb6c51778701135a54c05043a123a715cde938 (patch)
tree1d10c459bdcdaf29163466ad3169c3db97dfa6ca
parent1be79dc2a09aa66a1dab2d9d312dd5fcb4395bd0 (diff)
Fix for T77111: Joins Areas Without Creating Invalid Edges
Properly align every involved edge when performing 'tolerant' area joins. Differential Revision: https://developer.blender.org/D7859 Reviewed by Brecht Van Lommel
-rw-r--r--source/blender/editors/screen/screen_edit.c97
-rw-r--r--source/blender/editors/screen/screen_intern.h2
2 files changed, 74 insertions, 25 deletions
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 77f68eed883..6f004238522 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -305,30 +305,28 @@ int area_getorientation(ScrArea *area, ScrArea *sb)
ScrVert *sbTR = sb->v3;
ScrVert *sbBR = sb->v4;
- int tolerance = U.pixelsize * 4;
-
if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* area to right of sb = W */
- if ((abs(saBL->vec.y - sbBR->vec.y) <= tolerance) &&
- (abs(saTL->vec.y - sbTR->vec.y) <= tolerance)) {
+ if ((abs(saBL->vec.y - sbBR->vec.y) <= AREAJOINTOLERANCE) &&
+ (abs(saTL->vec.y - sbTR->vec.y) <= AREAJOINTOLERANCE)) {
return 0;
}
}
else if (saTL->vec.y == sbBL->vec.y &&
saTR->vec.y == sbBR->vec.y) { /* area to bottom of sb = N */
- if ((abs(saTL->vec.x - sbBL->vec.x) <= tolerance) &&
- (abs(saTR->vec.x - sbBR->vec.x) <= tolerance)) {
+ if ((abs(saTL->vec.x - sbBL->vec.x) <= AREAJOINTOLERANCE) &&
+ (abs(saTR->vec.x - sbBR->vec.x) <= AREAJOINTOLERANCE)) {
return 1;
}
}
else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* area to left of sb = E */
- if ((abs(saTR->vec.y - sbTL->vec.y) <= tolerance) &&
- (abs(saBR->vec.y - sbBL->vec.y) <= tolerance)) {
+ if ((abs(saTR->vec.y - sbTL->vec.y) <= AREAJOINTOLERANCE) &&
+ (abs(saBR->vec.y - sbBL->vec.y) <= AREAJOINTOLERANCE)) {
return 2;
}
}
else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* area on top of sb = S*/
- if ((abs(saBL->vec.x - sbTL->vec.x) <= tolerance) &&
- (abs(saBR->vec.x - sbTR->vec.x) <= tolerance)) {
+ if ((abs(saBL->vec.x - sbTL->vec.x) <= AREAJOINTOLERANCE) &&
+ (abs(saBR->vec.x - sbTR->vec.x) <= AREAJOINTOLERANCE)) {
return 3;
}
}
@@ -336,6 +334,69 @@ int area_getorientation(ScrArea *area, ScrArea *sb)
return -1;
}
+/* Screen verts with horizontal position equal to from_x are moved to to_x. */
+static void screen_verts_halign(const wmWindow *win,
+ const bScreen *screen,
+ const short from_x,
+ const short to_x)
+{
+ ED_screen_verts_iter(win, screen, v1)
+ {
+ if (v1->vec.x == from_x) {
+ v1->vec.x = to_x;
+ }
+ }
+}
+
+/* Screen verts with vertical position equal to from_y are moved to to_y. */
+static void screen_verts_valign(const wmWindow *win,
+ const bScreen *screen,
+ const short from_y,
+ const short to_y)
+{
+ ED_screen_verts_iter(win, screen, v1)
+ {
+ if (v1->vec.y == from_y) {
+ v1->vec.y = to_y;
+ }
+ }
+}
+
+/* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation().
+ */
+static void screen_areas_align(
+ bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const int dir)
+{
+ wmWindow *win = CTX_wm_window(C);
+
+ if (dir == 0 || dir == 2) {
+ /* horizontal join, use average for new top and bottom. */
+ int top = (sa1->v2->vec.y + sa2->v2->vec.y) / 2;
+ int bottom = (sa1->v4->vec.y + sa2->v4->vec.y) / 2;
+
+ /* Move edges exactly matching source top and bottom. */
+ screen_verts_valign(win, screen, sa1->v2->vec.y, top);
+ screen_verts_valign(win, screen, sa1->v4->vec.y, bottom);
+
+ /* Move edges exactly matching target top and bottom. */
+ screen_verts_valign(win, screen, sa2->v2->vec.y, top);
+ screen_verts_valign(win, screen, sa2->v4->vec.y, bottom);
+ }
+ else {
+ /* Vertical join, use averages for new left and right. */
+ int left = (sa1->v1->vec.x + sa2->v1->vec.x) / 2;
+ int right = (sa1->v3->vec.x + sa2->v3->vec.x) / 2;
+
+ /* Move edges exactly matching source left and right. */
+ screen_verts_halign(win, screen, sa1->v1->vec.x, left);
+ screen_verts_halign(win, screen, sa1->v3->vec.x, 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->v3->vec.x, right);
+ }
+}
+
/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
* used by the split, join operators
*/
@@ -348,21 +409,7 @@ int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2)
}
/* Align areas if they are not. Do sanity checking before getting here. */
-
- if (dir == 0 || dir == 2) {
- /* horizontal join, so vertically align source vert to target */
- sa2->v1->vec.y = sa1->v1->vec.y; /* vertical align sa1 BL */
- sa2->v2->vec.y = sa1->v2->vec.y; /* vertical align sa1 TL */
- sa2->v3->vec.y = sa1->v3->vec.y; /* vertical align sa1 TR */
- sa2->v4->vec.y = sa1->v4->vec.y; /* vertical align sa1 BR */
- }
- else {
- /* vertical join, so horizontally align source verts to target */
- sa2->v1->vec.x = sa1->v1->vec.x; /* vertical align sa1 BL */
- sa2->v2->vec.x = sa1->v2->vec.x; /* vertical align sa1 TL */
- sa2->v3->vec.x = sa1->v3->vec.x; /* vertical align sa1 TR */
- sa2->v4->vec.x = sa1->v4->vec.x; /* vertical align sa1 BR */
- }
+ screen_areas_align(C, screen, sa1, sa2, dir);
if (dir == 0) { /* sa1 to right of sa2 = W */
sa1->v1 = sa2->v1; /* BL */
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index a5e0263104d..2d42313d528 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -35,6 +35,8 @@ struct bContextDataResult;
#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */
#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */
+#define AREAJOINTOLERANCE (1.0f * U.widget_unit) /* Edges must be close to allow joining. */
+
/* Expanded interaction influence of area borders. */
#define BORDERPADDING (U.dpi_fac + U.pixelsize)