[Bf-blender-cvs] [6146b90] strand_editmode: Select Linked operator for hair edit mode (select all vertices of a strand).

Lukas Tönne noreply at git.blender.org
Mon Apr 20 14:24:21 CEST 2015


Commit: 6146b9031206b7fff7a0a66a1e27ac0134fda8e4
Author: Lukas Tönne
Date:   Tue Jan 6 11:13:39 2015 +0100
Branches: strand_editmode
https://developer.blender.org/rB6146b9031206b7fff7a0a66a1e27ac0134fda8e4

Select Linked operator for hair edit mode (select all vertices of a
strand).

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

M	source/blender/bmesh/intern/bmesh_strands.h
M	source/blender/editors/hair/hair_intern.h
M	source/blender/editors/hair/hair_ops.c
M	source/blender/editors/hair/hair_select.c

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

diff --git a/source/blender/bmesh/intern/bmesh_strands.h b/source/blender/bmesh/intern/bmesh_strands.h
index f326331..cd4267f 100644
--- a/source/blender/bmesh/intern/bmesh_strands.h
+++ b/source/blender/bmesh/intern/bmesh_strands.h
@@ -73,6 +73,42 @@ BLI_INLINE bool BM_strands_vert_is_tip(BMVert *v)
 	return false;
 }
 
+/* Next vertex on a strand */
+BLI_INLINE BMVert *BM_strands_vert_next(BMVert *v)
+{
+	BMEdge *e_first = v->e;
+	BMEdge *e_next;
+	
+	/* one of the edges leads to the previous vertex */
+	if (e_first) {
+		if (e_first->v1 == v)
+			return e_first->v2;
+		
+		e_next = bmesh_disk_edge_next(e_first, v);
+		if (e_next->v1 == v)
+			return e_next->v2;
+	}
+	return NULL;
+}
+
+/* Previous vertex on a strand */
+BLI_INLINE BMVert *BM_strands_vert_prev(BMVert *v)
+{
+	BMEdge *e_first = v->e;
+	BMEdge *e_next;
+	
+	/* one of the edges leads to the previous vertex */
+	if (e_first) {
+		if (e_first->v2 == v)
+			return e_first->v1;
+		
+		e_next = bmesh_disk_edge_next(e_first, v);
+		if (e_next->v2 == v)
+			return e_next->v1;
+	}
+	return NULL;
+}
+
 int BM_strands_count(BMesh *bm);
 int BM_strands_keys_count(BMVert *root);
 
diff --git a/source/blender/editors/hair/hair_intern.h b/source/blender/editors/hair/hair_intern.h
index cd59af7..4854104 100644
--- a/source/blender/editors/hair/hair_intern.h
+++ b/source/blender/editors/hair/hair_intern.h
@@ -49,6 +49,7 @@ void HAIR_OT_hair_edit_toggle(struct wmOperatorType *ot);
 
 /* hair_select.c */
 void HAIR_OT_select_all(struct wmOperatorType *ot);
+void HAIR_OT_select_linked(struct wmOperatorType *ot);
 
 /* hair_stroke.c */
 void HAIR_OT_stroke(struct wmOperatorType *ot);
diff --git a/source/blender/editors/hair/hair_ops.c b/source/blender/editors/hair/hair_ops.c
index 9792c79..bb3b027 100644
--- a/source/blender/editors/hair/hair_ops.c
+++ b/source/blender/editors/hair/hair_ops.c
@@ -50,6 +50,7 @@ void ED_operatortypes_hair(void)
 	WM_operatortype_append(HAIR_OT_hair_edit_toggle);
 	
 	WM_operatortype_append(HAIR_OT_select_all);
+	WM_operatortype_append(HAIR_OT_select_linked);
 	
 	WM_operatortype_append(HAIR_OT_stroke);
 }
@@ -129,6 +130,11 @@ void ED_keymap_hair(wmKeyConfig *keyconf)
 	kmi = WM_keymap_add_item(keymap, "HAIR_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
 	RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
 	
+	kmi = WM_keymap_add_item(keymap, "HAIR_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+	RNA_boolean_set(kmi->ptr, "deselect", false);
+	kmi = WM_keymap_add_item(keymap, "HAIR_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
+	RNA_boolean_set(kmi->ptr, "deselect", true);
+	
 	kmi = WM_keymap_add_item(keymap, "HAIR_OT_stroke", LEFTMOUSE, KM_PRESS, 0,        0);
 	
 	ed_keymap_hair_brush_switch(keymap, "hair_edit");
diff --git a/source/blender/editors/hair/hair_select.c b/source/blender/editors/hair/hair_select.c
index 808a1ce..986e669 100644
--- a/source/blender/editors/hair/hair_select.c
+++ b/source/blender/editors/hair/hair_select.c
@@ -49,6 +49,7 @@
 #include "bmesh.h"
 
 #include "RNA_access.h"
+#include "RNA_define.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -92,6 +93,7 @@ BLI_INLINE bool apply_select_action_flag(BMVert *v, int action)
 typedef bool (*PollVertexCb)(void *userdata, struct BMVert *v);
 /* distance metric function */
 typedef bool (*DistanceVertexCb)(void *userdata, struct BMVert *v, float *dist);
+typedef void (*ActionVertexCb)(void *userdata, struct BMVert *v, int action);
 
 static int hair_select_verts_filter(BMEditStrands *edit, HairEditSelectMode select_mode, int action, PollVertexCb cb, void *userdata)
 {
@@ -133,13 +135,12 @@ static int hair_select_verts_filter(BMEditStrands *edit, HairEditSelectMode sele
 	return tot;
 }
 
-static int hair_select_verts_closest(BMEditStrands *edit, HairEditSelectMode select_mode, int action, DistanceVertexCb cb, void *userdata)
+static bool hair_select_verts_closest(BMEditStrands *edit, HairEditSelectMode select_mode, int action, DistanceVertexCb cb, ActionVertexCb action_cb, void *userdata)
 {
 	BMesh *bm = edit->bm;
 	
 	BMVert *v;
 	BMIter iter;
-	int tot = 0;
 	
 	float dist;
 	BMVert *closest_v = NULL;
@@ -177,13 +178,13 @@ static int hair_select_verts_closest(BMEditStrands *edit, HairEditSelectMode sel
 	}
 	
 	if (closest_v) {
-		if (apply_select_action_flag(closest_v, action))
-			++tot;
+		action_cb(userdata, closest_v, action);
+		
+		BM_mesh_select_mode_flush(bm);
+		return true;
 	}
-	
-	BM_mesh_select_mode_flush(bm);
-	
-	return tot;
+	else
+		return false;
 }
 
 static void hair_deselect_all(BMEditStrands *edit)
@@ -263,6 +264,11 @@ static bool distance_vertex_circle(void *userdata, struct BMVert *v, float *dist
 	return hair_test_vertex_inside_circle(&data->viewdata, data->mval, data->radsq, v, dist);
 }
 
+static void closest_vertex_select(void *UNUSED(userdata), struct BMVert *v, int action)
+{
+	apply_select_action_flag(v, action);
+}
+
 int ED_hair_mouse_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
 {
 	Scene *scene = CTX_data_scene(C);
@@ -290,13 +296,81 @@ int ED_hair_mouse_select(bContext *C, const int mval[2], bool extend, bool desel
 	else
 		action = SEL_INVERT;
 	
-	hair_select_verts_closest(edit, settings->select_mode, action, distance_vertex_circle, &data);
+	hair_select_verts_closest(edit, settings->select_mode, action, distance_vertex_circle, closest_vertex_select, &data);
+	
+	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | NA_SELECTED, ob);
+	
+	return OPERATOR_FINISHED;
+}
+
+/************************ select linked operator ************************/
+
+static void linked_vertices_select(void *UNUSED(userdata), struct BMVert *v, int action)
+{
+	BMVert *lv;
+	
+	apply_select_action_flag(v, action);
+	
+	for (lv = BM_strands_vert_prev(v); lv; lv = BM_strands_vert_prev(lv))
+		apply_select_action_flag(lv, action);
+	for (lv = BM_strands_vert_next(v); lv; lv = BM_strands_vert_next(lv))
+		apply_select_action_flag(lv, action);
+}
+
+static int select_linked_exec(bContext *C, wmOperator *op)
+{
+	Scene *scene = CTX_data_scene(C);
+	Object *ob = CTX_data_active_object(C);
+	BMEditStrands *edit = BKE_editstrands_from_object(ob);
+	HairEditSettings *settings = &scene->toolsettings->hair_edit;
+	float select_radius = ED_view3d_select_dist_px();
+	
+	DistanceVertexCirleData data;
+	int location[2];
+	int action;
+	
+	RNA_int_get_array(op->ptr, "location", location);
+	
+	hair_init_viewdata(C, &data.viewdata);
+	data.mval[0] = location[0];
+	data.mval[1] = location[1];
+	data.radsq = select_radius * select_radius;
+	
+	action = RNA_boolean_get(op->ptr, "deselect") ? SEL_DESELECT : SEL_SELECT;
+	
+	hair_select_verts_closest(edit, settings->select_mode, action, distance_vertex_circle, linked_vertices_select, &data);
 	
 	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | NA_SELECTED, ob);
 	
 	return OPERATOR_FINISHED;
 }
 
+static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	RNA_int_set_array(op->ptr, "location", event->mval);
+	return select_linked_exec(C, op);
+}
+
+void HAIR_OT_select_linked(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Select Linked";
+	ot->idname = "HAIR_OT_select_linked";
+	ot->description = "Select connected vertices";
+	
+	/* api callbacks */
+	ot->exec = select_linked_exec;
+	ot->invoke = select_linked_invoke;
+	ot->poll = hair_edit_poll;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	/* properties */
+	RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them");
+	RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
+}
+
 /************************ border select operator ************************/
 
 typedef struct PollVertexRectData {




More information about the Bf-blender-cvs mailing list