[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52122] trunk/blender/source/blender: fix [#33142] Ctrl LMB higher selection mode in edit mode sometimes selects extra elements

Campbell Barton ideasman42 at gmail.com
Mon Nov 12 00:34:02 CET 2012


Revision: 52122
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52122
Author:   campbellbarton
Date:     2012-11-11 23:33:59 +0000 (Sun, 11 Nov 2012)
Log Message:
-----------
fix [#33142] Ctrl LMB higher selection mode in edit mode sometimes selects extra elements

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/intern/math_base_inline.c
    trunk/blender/source/blender/bmesh/intern/bmesh_queries.c
    trunk/blender/source/blender/bmesh/intern/bmesh_queries.h
    trunk/blender/source/blender/editors/mesh/editmesh_select.c
    trunk/blender/source/blender/editors/space_view3d/view3d_header.c

Modified: trunk/blender/source/blender/blenlib/intern/math_base_inline.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_base_inline.c	2012-11-11 23:04:59 UTC (rev 52121)
+++ trunk/blender/source/blender/blenlib/intern/math_base_inline.c	2012-11-11 23:33:59 UTC (rev 52122)
@@ -139,6 +139,25 @@
 	return n;
 }
 
+MINLINE unsigned int highest_order_bit_i(unsigned int n)
+{
+	n |= (n >>  1);
+	n |= (n >>  2);
+	n |= (n >>  4);
+	n |= (n >>  8);
+	n |= (n >> 16);
+	return n - (n >> 1);
+}
+
+MINLINE unsigned short highest_order_bit_s(unsigned short n)
+{
+	n |= (n >>  1);
+	n |= (n >>  2);
+	n |= (n >>  4);
+	n |= (n >>  8);
+	return n - (n >> 1);
+}
+
 MINLINE float min_ff(float a, float b)
 {
 	return (a < b) ? a : b;

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_queries.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_queries.c	2012-11-11 23:04:59 UTC (rev 52121)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_queries.c	2012-11-11 23:33:59 UTC (rev 52122)
@@ -1419,3 +1419,38 @@
 
 	return ok;
 }
+
+/* convenience functiosn for checking flags */
+int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
+{
+	return (BM_elem_flag_test(e->v1, hflag) ||
+	        BM_elem_flag_test(e->v2, hflag));
+}
+
+int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
+{
+	BMLoop *l_iter;
+	BMLoop *l_first;
+
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	do {
+		if (BM_elem_flag_test(l_iter->v, hflag)) {
+			return TRUE;
+		}
+	} while ((l_iter = l_iter->next) != l_first);
+	return FALSE;
+}
+
+int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
+{
+	BMLoop *l_iter;
+	BMLoop *l_first;
+
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	do {
+		if (BM_elem_flag_test(l_iter->e, hflag)) {
+			return TRUE;
+		}
+	} while ((l_iter = l_iter->next) != l_first);
+	return FALSE;
+}

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_queries.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_queries.h	2012-11-11 23:04:59 UTC (rev 52121)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_queries.h	2012-11-11 23:33:59 UTC (rev 52122)
@@ -100,4 +100,8 @@
 void    BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
                                  BMLoop *edge_loop);
 
+int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag);
+int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag);
+int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag);
+
 #endif /* __BMESH_QUERIES_H__ */

Modified: trunk/blender/source/blender/editors/mesh/editmesh_select.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_select.c	2012-11-11 23:04:59 UTC (rev 52121)
+++ trunk/blender/source/blender/editors/mesh/editmesh_select.c	2012-11-11 23:33:59 UTC (rev 52122)
@@ -1881,50 +1881,45 @@
 	BMFace *efa;
 	BMIter iter;
 
+	/* first tag-to-select, then select --- this avoids a feedback loop */
+
 	/* have to find out what the selectionmode was previously */
 	if (selectmode_old == SCE_SELECT_VERTEX) {
 		if (selectmode_new == SCE_SELECT_EDGE) {
-			/* select all edges associated with every selected vertex */
-			eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
-			for (; eed; eed = BM_iter_step(&iter)) {
-				if ((BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
-				     BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))
-				{
+			/* select all edges associated with every selected vert */
+			BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+				BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT));
+			}
+
+			BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
+				if (BM_elem_flag_test(eed, BM_ELEM_TAG)) {
 					BM_edge_select_set(em->bm, eed, TRUE);
 				}
 			}
 		}
 		else if (selectmode_new == SCE_SELECT_FACE) {
-			BMIter liter;
-			BMLoop *l;
+			/* select all faces associated with every selected vert */
+			BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+				BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT));
+			}
 
-			/* select all faces associated with every selected vertex */
-			efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
-			for (; efa; efa = BM_iter_step(&iter)) {
-				l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
-				for (; l; l = BM_iter_step(&liter)) {
-					if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) {
-						BM_face_select_set(em->bm, efa, TRUE);
-						break;
-					}
+			BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+				if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+					BM_face_select_set(em->bm, efa, TRUE);
 				}
 			}
 		}
 	}
 	else if (selectmode_old == SCE_SELECT_EDGE) {
 		if (selectmode_new == SCE_SELECT_FACE) {
-			BMIter liter;
-			BMLoop *l;
+			/* select all faces associated with every selected edge */
+			BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+				BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT));
+			}
 
-			/* select all faces associated with every selected vertex */
-			efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
-			for (; efa; efa = BM_iter_step(&iter)) {
-				l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa);
-				for (; l; l = BM_iter_step(&liter)) {
-					if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) {
-						BM_face_select_set(em->bm, efa, TRUE);
-						break;
-					}
+			BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+				if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
+					BM_face_select_set(em->bm, efa, TRUE);
 				}
 			}
 		}

Modified: trunk/blender/source/blender/editors/space_view3d/view3d_header.c
===================================================================
--- trunk/blender/source/blender/editors/space_view3d/view3d_header.c	2012-11-11 23:04:59 UTC (rev 52121)
+++ trunk/blender/source/blender/editors/space_view3d/view3d_header.c	2012-11-11 23:33:59 UTC (rev 52122)
@@ -319,7 +319,7 @@
 	View3D *v3d = sa->spacedata.first;
 	Object *obedit = CTX_data_edit_object(C);
 	BMEditMesh *em = NULL;
-	int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
+	const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
 	PointerRNA props_ptr;
 	
 	if (obedit && obedit->type == OB_MESH) {
@@ -348,8 +348,11 @@
 		case B_SEL_EDGE:
 			if (em) {
 				if (shift == 0 || em->selectmode == 0) {
-					if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) {
-						if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
+					if (ctrl) {
+						const short selmode_max = highest_order_bit_s(ts->selectmode);
+						if (selmode_max == SCE_SELECT_VERTEX) {
+							EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE);
+						}
 					}
 					em->selectmode = SCE_SELECT_EDGE;
 				}
@@ -362,11 +365,13 @@
 		case B_SEL_FACE:
 			if (em) {
 				if (shift == 0 || em->selectmode == 0) {
-					if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) ||
-					    ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE))
-					{
-						if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE);
+					if (ctrl) {
+						const short selmode_max = highest_order_bit_s(ts->selectmode);
+						if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) {
+							EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE);
+						}
 					}
+
 					em->selectmode = SCE_SELECT_FACE;
 				}
 				ts->selectmode = em->selectmode;
@@ -430,9 +435,15 @@
 
 		row = uiLayoutRow(layout, TRUE);
 		block = uiLayoutGetBlock(row);
-		uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select - Shift-Click for multiple modes");
-		uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select - Shift-Click for multiple modes");
-		uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select - Shift-Click for multiple modes");
+		uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
+		                 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
+		                 "Vertex select - Shift-Click for multiple modes");
+		uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL,
+		                 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
+		                 "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection");
+		uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
+		                 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
+		                 "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection");
 	}
 }
 




More information about the Bf-blender-cvs mailing list