[Bf-blender-cvs] [a81abbbb8f0] master: Fix T100772: Joins with Interfering Tiny Areas

Harley Acheson noreply at git.blender.org
Wed Nov 16 18:08:24 CET 2022


Commit: a81abbbb8f047f969cbe26ceeb6223d623f4e234
Author: Harley Acheson
Date:   Wed Nov 16 09:06:03 2022 -0800
Branches: master
https://developer.blender.org/rBa81abbbb8f047f969cbe26ceeb6223d623f4e234

Fix T100772: Joins with Interfering Tiny Areas

Detect unlikely situation of an area (that is smaller than our allowed
minimums) sharing an edge that will be moved during a join.

See D16519 for more details.

Differential Revision: https://developer.blender.org/D16519

Reviewed by Campbell Barton

===================================================================

M	source/blender/editors/screen/screen_edit.c

===================================================================

diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index f06e2bd4f3c..b2ec251697e 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -360,11 +360,59 @@ static void screen_verts_valign(const wmWindow *win,
   }
 }
 
+/* Test if two adjoining areas can be aligned by having their screen edges adjusted. */
+static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2, eScreenDir dir)
+{
+  if (dir == SCREEN_DIR_NONE) {
+    return false;
+  }
+
+  int offset1;
+  int offset2;
+  area_getoffsets(sa1, sa2, dir, &offset1, &offset2);
+
+  const int tolerance = SCREEN_DIR_IS_HORIZONTAL(dir) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX;
+  if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) {
+    /* Misalignment is too great. */
+    return false;
+  }
+
+  /* Areas that are _smaller_ than minimum sizes, sharing an edge to be moved. See T100772.  */
+  if (SCREEN_DIR_IS_VERTICAL(dir)) {
+    const short xmin = MIN2(sa1->v1->vec.x, sa2->v1->vec.x);
+    const short xmax = MAX2(sa1->v3->vec.x, sa2->v3->vec.x);
+    LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+      if (area->v3->vec.x - area->v1->vec.x < tolerance &&
+          (area->v1->vec.x == xmin || area->v3->vec.x == xmax)) {
+        /* There is a narrow vertical area sharing an edge of the combined bounds. */
+        return false;
+      }
+    }
+  }
+  else {
+    const short ymin = MIN2(sa1->v1->vec.y, sa2->v1->vec.y);
+    const short ymax = MAX2(sa1->v3->vec.y, sa2->v3->vec.y);
+    LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+      if (area->v3->vec.y - area->v1->vec.y < tolerance &&
+          (area->v1->vec.y == ymin || area->v3->vec.y == ymax)) {
+        /* There is a narrow horizontal area sharing an edge of the combined bounds. */
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
 /* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation().
  */
-static void screen_areas_align(
+static bool screen_areas_align(
     bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const eScreenDir dir)
 {
+  if (!screen_areas_can_align(screen, sa1, sa2, dir)) {
+    return false;
+  }
+
   wmWindow *win = CTX_wm_window(C);
 
   if (SCREEN_DIR_IS_HORIZONTAL(dir)) {
@@ -393,28 +441,20 @@ static void screen_areas_align(
     screen_verts_halign(win, screen, sa2->v1->vec.x, left);
     screen_verts_halign(win, screen, sa2->v3->vec.x, right);
   }
+
+  return true;
 }
 
 /* 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)
 {
   const eScreenDir dir = area_getorientation(sa1, sa2);
-  if (dir == SCREEN_DIR_NONE) {
-    return false;
-  }
-
-  int offset1;
-  int offset2;
-  area_getoffsets(sa1, sa2, dir, &offset1, &offset2);
 
-  int tolerance = SCREEN_DIR_IS_HORIZONTAL(dir) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX;
-  if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) {
+  /* Ensure that the area edges are exactly aligned. */
+  if (!screen_areas_align(C, screen, sa1, sa2, dir)) {
     return false;
   }
 
-  /* Align areas if they are not. */
-  screen_areas_align(C, screen, sa1, sa2, dir);
-
   if (dir == SCREEN_DIR_W) { /* sa1 to right of sa2 = West. */
     sa1->v1 = sa2->v1;       /* BL */
     sa1->v2 = sa2->v2;       /* TL */



More information about the Bf-blender-cvs mailing list