[Bf-blender-cvs] [338be95874b] master: Fix bone select failing with end-points outside the view

Campbell Barton noreply at git.blender.org
Tue Jun 22 06:24:23 CEST 2021


Commit: 338be95874bddec300a863c9583652cda0ccf5de
Author: Campbell Barton
Date:   Tue Jun 22 14:04:30 2021 +1000
Branches: master
https://developer.blender.org/rB338be95874bddec300a863c9583652cda0ccf5de

Fix bone select failing with end-points outside the view

Apply the same fix for T32214 (edge-select failing) to bones
which also failed when their end-points were outside of the view.

- Add V3D_PROJ_TEST_CLIP_CONTENT support for edit & pose bone iterator
  and use for selection operators.
- Remove unnecessarily complicated checks with pose-mode lasso tagging.
- Correct error in pose-mode LassoSelectUserData.is_changed
  (currently harmless as it's not read back).

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

M	source/blender/editors/space_view3d/view3d_iterators.c
M	source/blender/editors/space_view3d/view3d_select.c

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

diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 0eb594fb3dc..5e0101e4160 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -97,6 +97,110 @@ static int content_planes_from_clip_flag(const ARegion *region,
   return planes_len;
 }
 
+/**
+ * Edge projection is more involved since part of the edge may be behind the view
+ * or extend beyond the far limits. In the case of single points, these can be ignored.
+ * However it just may still be visible on screen, so constrained the edge to planes
+ * defined by the port to ensure both ends of the edge can be projected, see T32214.
+ *
+ * \note This is unrelated to #V3D_PROJ_TEST_CLIP_BB which must be checked separately.
+ */
+static bool view3d_project_segment_to_screen_with_content_clip_planes(
+    const ARegion *region,
+    const float v_a[3],
+    const float v_b[3],
+    const eV3DProjTest clip_flag,
+    const rctf *win_rect,
+    const float content_planes[][4],
+    const int content_planes_len,
+    /* Output. */
+    float r_screen_co_a[2],
+    float r_screen_co_b[2])
+{
+  /* Clipping already handled, no need to check in projection. */
+  eV3DProjTest clip_flag_nowin = clip_flag & ~V3D_PROJ_TEST_CLIP_WIN;
+
+  const eV3DProjStatus status_a = ED_view3d_project_float_object(
+      region, v_a, r_screen_co_a, clip_flag_nowin);
+  const eV3DProjStatus status_b = ED_view3d_project_float_object(
+      region, v_b, r_screen_co_b, clip_flag_nowin);
+
+  if ((status_a == V3D_PROJ_RET_OK) && (status_b == V3D_PROJ_RET_OK)) {
+    if (clip_flag & V3D_PROJ_TEST_CLIP_WIN) {
+      if (!BLI_rctf_isect_segment(win_rect, r_screen_co_a, r_screen_co_b)) {
+        return false;
+      }
+    }
+  }
+  else {
+    if (content_planes_len == 0) {
+      return false;
+    }
+
+    /* Both too near, ignore. */
+    if ((status_a & V3D_PROJ_TEST_CLIP_NEAR) && (status_b & V3D_PROJ_TEST_CLIP_NEAR)) {
+      return false;
+    }
+
+    /* Both too far, ignore. */
+    if ((status_a & V3D_PROJ_TEST_CLIP_FAR) && (status_b & V3D_PROJ_TEST_CLIP_FAR)) {
+      return false;
+    }
+
+    /* Simple cases have been ruled out, clip by viewport planes, then re-project. */
+    float v_a_clip[3], v_b_clip[3];
+    if (!clip_segment_v3_plane_n(
+            v_a, v_b, content_planes, content_planes_len, v_a_clip, v_b_clip)) {
+      return false;
+    }
+
+    if ((ED_view3d_project_float_object(region, v_a_clip, r_screen_co_a, clip_flag_nowin) !=
+         V3D_PROJ_RET_OK) ||
+        (ED_view3d_project_float_object(region, v_b_clip, r_screen_co_b, clip_flag_nowin) !=
+         V3D_PROJ_RET_OK)) {
+      return false;
+    }
+
+    /* No need for #V3D_PROJ_TEST_CLIP_WIN check here,
+     * clipping the segment by planes handle this. */
+  }
+
+  return true;
+}
+
+/**
+ * Project an edge, points that fail to project are tagged with #IS_CLIPPED.
+ */
+static bool view3d_project_segment_to_screen_with_clip_tag(const ARegion *region,
+                                                           const float v_a[3],
+                                                           const float v_b[3],
+                                                           const eV3DProjTest clip_flag,
+                                                           /* Output. */
+                                                           float r_screen_co_a[2],
+                                                           float r_screen_co_b[2])
+{
+  int count = 0;
+
+  if (ED_view3d_project_float_object(region, v_a, r_screen_co_a, clip_flag) == V3D_PROJ_RET_OK) {
+    count++;
+  }
+  else {
+    r_screen_co_a[0] = IS_CLIPPED; /* weak */
+    /* screen_co_a[1]: intentionally don't set this so we get errors on misuse */
+  }
+
+  if (ED_view3d_project_float_object(region, v_b, r_screen_co_b, clip_flag) == V3D_PROJ_RET_OK) {
+    count++;
+  }
+  else {
+    r_screen_co_b[0] = IS_CLIPPED; /* weak */
+    /* screen_co_b[1]: intentionally don't set this so we get errors on misuse */
+  }
+
+  /* Caller may want to know this value, for now it's not needed. */
+  return count != 0;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -261,76 +365,6 @@ void mesh_foreachScreenVert(
 /** \name Edit-Mesh: For Each Screen Mesh Edge
  * \{ */
 
-/**
- * Edge projection is more involved since part of the edge may be behind the view
- * or extend beyond the far limits. In the case of single points, these can be ignored.
- * However it just may still be visible on screen, so constrained the edge to planes
- * defined by the port to ensure both ends of the edge can be projected, see T32214.
- *
- * \note This is unrelated to #V3D_PROJ_TEST_CLIP_BB which must be checked separately.
- */
-static bool mesh_foreachScreenEdge_shared_project_and_test(const ARegion *region,
-                                                           const float v_a[3],
-                                                           const float v_b[3],
-                                                           const eV3DProjTest clip_flag,
-                                                           const rctf *win_rect,
-                                                           const float content_planes[][4],
-                                                           const int content_planes_len,
-                                                           /* Output. */
-                                                           float r_screen_co_a[2],
-                                                           float r_screen_co_b[2])
-{
-  /* Clipping already handled, no need to check in projection. */
-  eV3DProjTest clip_flag_nowin = clip_flag & ~V3D_PROJ_TEST_CLIP_WIN;
-
-  const eV3DProjStatus status_a = ED_view3d_project_float_object(
-      region, v_a, r_screen_co_a, clip_flag_nowin);
-  const eV3DProjStatus status_b = ED_view3d_project_float_object(
-      region, v_b, r_screen_co_b, clip_flag_nowin);
-
-  if ((status_a == V3D_PROJ_RET_OK) && (status_b == V3D_PROJ_RET_OK)) {
-    if (clip_flag & V3D_PROJ_TEST_CLIP_WIN) {
-      if (!BLI_rctf_isect_segment(win_rect, r_screen_co_a, r_screen_co_b)) {
-        return false;
-      }
-    }
-  }
-  else {
-    if (content_planes_len == 0) {
-      return false;
-    }
-
-    /* Both too near, ignore. */
-    if ((status_a & V3D_PROJ_TEST_CLIP_NEAR) && (status_b & V3D_PROJ_TEST_CLIP_NEAR)) {
-      return false;
-    }
-
-    /* Both too far, ignore. */
-    if ((status_a & V3D_PROJ_TEST_CLIP_FAR) && (status_b & V3D_PROJ_TEST_CLIP_FAR)) {
-      return false;
-    }
-
-    /* Simple cases have been ruled out, clip by viewport planes, then re-project. */
-    float v_a_clip[3], v_b_clip[3];
-    if (!clip_segment_v3_plane_n(
-            v_a, v_b, content_planes, content_planes_len, v_a_clip, v_b_clip)) {
-      return false;
-    }
-
-    if ((ED_view3d_project_float_object(region, v_a_clip, r_screen_co_a, clip_flag_nowin) !=
-         V3D_PROJ_RET_OK) ||
-        (ED_view3d_project_float_object(region, v_b_clip, r_screen_co_b, clip_flag_nowin) !=
-         V3D_PROJ_RET_OK)) {
-      return false;
-    }
-
-    /* No need for #V3D_PROJ_TEST_CLIP_WIN check here,
-     * clipping the segment by planes handle this. */
-  }
-
-  return true;
-}
-
 static void mesh_foreachScreenEdge__mapFunc(void *userData,
                                             int index,
                                             const float v_a[3],
@@ -343,15 +377,15 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData,
   }
 
   float screen_co_a[2], screen_co_b[2];
-  if (!mesh_foreachScreenEdge_shared_project_and_test(data->vc.region,
-                                                      v_a,
-                                                      v_b,
-                                                      data->clip_flag,
-                                                      &data->win_rect,
-                                                      data->content_planes,
-                                                      data->content_planes_len,
-                                                      screen_co_a,
-                                                      screen_co_b)) {
+  if (!view3d_project_segment_to_screen_with_content_clip_planes(data->vc.region,
+                                                                 v_a,
+                                                                 v_b,
+                                                                 data->clip_flag,
+                                                                 &data->win_rect,
+                                                                 data->content_planes,
+                                                                 data->content_planes_len,
+                                                                 screen_co_a,
+                                                                 screen_co_b)) {
     return;
   }
 
@@ -430,15 +464,15 @@ static void mesh_foreachScreenEdge_clip_bb_segment__mapFunc(void *userData,
   }
 
   float screen_co_a[2], screen_co_b[2];
-  if (!mesh_foreachScreenEdge_shared_project_and_test(data->vc.region,
-                                                      v_a_clip,
-                                                      v_b_clip,
-                                                      data->clip_flag,
-                                                      &data->win_rect,
-                                                      data->content_planes,
-                                                      data->content_planes_len,
-                                                      screen_co_a,
-                                                      screen_co_b)) {
+  if (!view3d_project_segment_to_screen_with_content_clip_planes(data->vc.region,
+                                                                 v_a_clip,
+                                                                 v_b_clip,
+                                                                 data->clip_flag,
+                                             

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list