[Bf-blender-cvs] [221d0786412] blender2.8: Multi-Objects Metaball: Selection refactor - fix pick and box selection

Dalai Felinto noreply at git.blender.org
Fri Nov 9 19:45:32 CET 2018


Commit: 221d07864128687858634aebcfb27798a494557a
Author: Dalai Felinto
Date:   Fri Nov 9 14:26:58 2018 -0200
Branches: blender2.8
https://developer.blender.org/rB221d07864128687858634aebcfb27798a494557a

Multi-Objects Metaball: Selection refactor - fix pick and box selection

This is inspired/based on the code we use for armature bone selection.
Both pick selection, and box selection should be working now.

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

M	source/blender/draw/modes/edit_metaball_mode.c
M	source/blender/editors/include/ED_mball.h
M	source/blender/editors/metaball/mball_edit.c
M	source/blender/editors/space_view3d/view3d_select.c
M	source/blender/makesdna/DNA_meta_types.h

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

diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
index 9e27ed7bd17..912c30c1482 100644
--- a/source/blender/draw/modes/edit_metaball_mode.c
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -31,6 +31,8 @@
 #include "BKE_object.h"
 #include "BKE_mball.h"
 
+#include "ED_mball.h"
+
 /* If builtin shaders are needed */
 #include "GPU_shader.h"
 #include "GPU_select.h"
@@ -147,8 +149,6 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
 
 			const bool is_select = DRW_state_is_select();
 
-			int selection_id = 0;
-
 			float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */
 			{
 				float scamat[3][3];
@@ -165,7 +165,8 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
 				copy_v3_v3(draw_scale_xform[2], scamat[2]);
 			}
 
-			for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
+			int selection_id = ob->select_color;
+			for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next, selection_id += 0x10000) {
 				float world_pos[3];
 				mul_v3_m4v3(world_pos, ob->obmat, &ml->x);
 				draw_scale_xform[0][3] = world_pos[0];
@@ -178,8 +179,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
 				else color = col_radius;
 
 				if (is_select) {
-					ml->selcol1 = ++selection_id;
-					DRW_select_load_id(selection_id);
+					DRW_select_load_id(selection_id | MBALLSEL_RADIUS);
 				}
 
 				DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color);
@@ -188,8 +188,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
 				else color = col_stiffness;
 
 				if (is_select) {
-					ml->selcol2 = ++selection_id;
-					DRW_select_load_id(selection_id);
+					DRW_select_load_id(selection_id | MBALLSEL_STIFF);
 				}
 
 				DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color);
diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h
index 46c34d36efc..47ea3929883 100644
--- a/source/blender/editors/include/ED_mball.h
+++ b/source/blender/editors/include/ED_mball.h
@@ -51,4 +51,11 @@ void ED_mball_editmball_load(struct Object *obedit);
 /* editmball_undo.c */
 void ED_mball_undosys_type(struct UndoType *ut);
 
+
+#define MBALLSEL_STIFF    (1 << 29)
+#define MBALLSEL_RADIUS   (1 << 30)
+#define MBALLSEL_ANY      (MBALLSEL_STIFF | MBALLSEL_RADIUS)
+
+#define MBALL_NOSEL   (1u << 31u)
+
 #endif  /* __ED_MBALL_H__ */
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 83e454c0d35..6d1ba2d3fe0 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -56,6 +56,7 @@
 #include "DEG_depsgraph.h"
 
 #include "ED_mball.h"
+#include "ED_object.h"
 #include "ED_screen.h"
 #include "ED_select_utils.h"
 #include "ED_view3d.h"
@@ -676,10 +677,7 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot)
 bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
 {
 	static MetaElem *startelem = NULL;
-	Object *obedit = CTX_data_edit_object(C);
 	ViewContext vc;
-	MetaBall *mb = (MetaBall *)obedit->data;
-	MetaElem *ml, *ml_act = NULL;
 	int a, hits;
 	unsigned int buffer[MAXPICKBUF];
 	rcti rect;
@@ -692,66 +690,116 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
 	        &vc, buffer, MAXPICKBUF, &rect,
 	        VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
 
-	/* does startelem exist? */
-	ml = mb->editelems->first;
-	while (ml) {
-		if (ml == startelem) break;
-		ml = ml->next;
-	}
-
-	if (ml == NULL) startelem = mb->editelems->first;
+	FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, base) {
+		ED_view3d_viewcontext_init_object(&vc, base->object);
+		MetaBall *mb = (MetaBall *)base->object->data;
+		MetaElem *ml, *ml_act = NULL;
 
-	if (hits > 0) {
-		ml = startelem;
+		/* does startelem exist? */
+		ml = mb->editelems->first;
 		while (ml) {
-			for (a = 0; a < hits; a++) {
-				/* index converted for gl stuff */
-				if (ml->selcol1 == buffer[4 * a + 3]) {
-					ml->flag |= MB_SCALE_RAD;
-					ml_act = ml;
-				}
-				if (ml->selcol2 == buffer[4 * a + 3]) {
-					ml->flag &= ~MB_SCALE_RAD;
-					ml_act = ml;
-				}
-			}
-			if (ml_act) break;
-			ml = ml->next;
-			if (ml == NULL) ml = mb->editelems->first;
 			if (ml == startelem) break;
+			ml = ml->next;
 		}
 
-		/* When some metaelem was found, then it is necessary to select or
-		 * deselect it. */
-		if (ml_act) {
-			if (extend) {
-				ml_act->flag |= SELECT;
-			}
-			else if (deselect) {
-				ml_act->flag &= ~SELECT;
+		if (ml == NULL) startelem = mb->editelems->first;
+
+		if (hits > 0) {
+			int metaelem_id = 0;
+			ml = startelem;
+			while (ml) {
+				for (a = 0; a < hits; a++) {
+					int hitresult = buffer[(4 * a) + 3];
+					if (hitresult == -1) {
+						continue;
+					}
+					else if (hitresult & MBALL_NOSEL) {
+						continue;
+					}
+
+					const uint hit_object = hitresult & 0xFFFF;
+					if (vc.obedit->select_color != hit_object) {
+						continue;
+					}
+
+					if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
+						continue;
+					}
+
+					if (hitresult & MBALLSEL_RADIUS) {
+						ml->flag |= MB_SCALE_RAD;
+						ml_act = ml;
+						break;
+					}
+
+					if (hitresult & MBALLSEL_STIFF) {
+						ml->flag &= ~MB_SCALE_RAD;
+						ml_act = ml;
+						break;
+					}
+				}
+
+				if (ml_act) break;
+				ml = ml->next;
+				if (ml == NULL) ml = mb->editelems->first;
+				if (ml == startelem) break;
+
+				metaelem_id += 0x10000;
 			}
-			else if (toggle) {
-				if (ml_act->flag & SELECT)
+
+			/* When some metaelem was found, then it is necessary to select or
+			* deselect it. */
+			if (ml_act) {
+				if (!extend && !deselect && !toggle) {
+					uint objects_len;
+					Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, &objects_len);
+					for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+						Object *ob_iter = objects[ob_index];
+
+						if (ob_iter == base->object) {
+							continue;
+						}
+
+						BKE_mball_deselect_all((MetaBall *)ob_iter->data);
+						DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE);
+						WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
+					}
+					MEM_freeN(objects);
+				}
+
+				if (extend) {
+					ml_act->flag |= SELECT;
+				}
+				else if (deselect) {
 					ml_act->flag &= ~SELECT;
-				else
+				}
+				else if (toggle) {
+					if (ml_act->flag & SELECT)
+						ml_act->flag &= ~SELECT;
+					else
+						ml_act->flag |= SELECT;
+				}
+				else {
+					/* Deselect all existing metaelems */
+					BKE_mball_deselect_all(mb);
+
+					/* Select only metaelem clicked on */
 					ml_act->flag |= SELECT;
-			}
-			else {
-				/* Deselect all existing metaelems */
-				BKE_mball_deselect_all(mb);
+				}
 
-				/* Select only metaelem clicked on */
-				ml_act->flag |= SELECT;
-			}
+				mb->lastelem = ml_act;
 
-			mb->lastelem = ml_act;
+				DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
+				WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
 
-			DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
-			WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
+				if (vc.view_layer->basact != base) {
+					ED_object_base_activate(C, base);
+				}
 
-			return true;
+				return true;
+			}
 		}
-	}
+	} FOREACH_BASE_IN_EDIT_MODE_END;
 
 	return false;
 }
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 230bbd11450..c421c96e530 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -2169,7 +2169,8 @@ static int do_meta_box_select(
         ViewContext *vc,
         const rcti *rect, const eSelectOp sel_op)
 {
-	MetaBall *mb = (MetaBall *)vc->obedit->data;
+	Object *ob = vc->obedit;
+	MetaBall *mb = (MetaBall *)ob->data;
 	MetaElem *ml;
 	int a;
 
@@ -2184,27 +2185,50 @@ static int do_meta_box_select(
 		BKE_mball_deselect_all(mb);
 	}
 
-	for (ml = mb->editelems->first; ml; ml = ml->next) {
-		bool is_inside_1 = false;
-		bool is_inside_2 = false;
+	int metaelem_id = 0;
+	for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) {
+		bool is_inside_radius = false;
+		bool is_inside_stiff = false;
+
 		for (a = 0; a < hits; a++) {
-			if (ml->selcol1 == buffer[(4 * a) + 3]) {
-				is_inside_1 = true;
+			int hitresult = buffer[(4 * a) + 3];
+
+			if (hitresult == -1) {
+				continue;
+			}
+			else if (hitresult & MBALL_NOSEL) {
+				continue;
+			}
+
+			const uint hit_object = hitresult & 0xFFFF;
+			if (vc->obedit->select_color != hit_object) {
+				continue;
+			}
+
+			if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
+				continue;
+			}
+
+			if (hitresult & MBALLSEL_RADIUS) {
+				is_inside_radius = true;
 				break;
 			}
-			if (ml->selcol2 == buffer[(4 * a) + 3]) {
-				is_inside_2 = true;
+
+			if (hitresult & MBALLSEL_STIFF) {
+				is_inside_stiff = true;
 				break;
 			}
 		}
-		if (is_inside_1) {
+		if (is_inside_radius) {
 			ml->flag |= MB_SCALE_RAD;
 		}
-		if (is_inside_2) {
+		if (is_inside_stiff) {
 			ml->flag &= ~MB_SCALE_RAD;
 		}
+
 		const bool is_select = (ml->flag & SELECT);
-		const bool is_inside = is_inside_1 || is_inside_2;
+		const bool is_inside = is_inside_radius || is_inside_stiff;
+
 		const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
 		if (sel_op_result != -1) {
 			SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT);
diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h
index c312d45567f..3f0b1b302c7 100644
--- a/source/blender/makesdna/DNA_meta_types.h
+++ b/source/blender/makesdna/DNA_meta_types.h
@@ -47,7 +47,8 @@ typedef struct MetaElem {
 
 	struct BoundBox *bb;        /* Bound Box of MetaElem */
 
-	short type, flag, selcol1, selcol2;
+	short type, flag;
+	short pad[2];
 	float x, y, z;          /* Position of center of MetaElem */
 	float quat[4];          /* Rotation of MetaElem (MUST be kept normalized) */
 	float expx

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list