[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