[Bf-blender-cvs] [4e9911663a2] blender2.8: Multi-Objects: CURVE_OT_select_similar

Habib Gahbiche noreply at git.blender.org
Wed Nov 7 01:56:45 CET 2018


Commit: 4e9911663a22766f6751d33ae84c1ebcc1fae559
Author: Habib Gahbiche
Date:   Tue Nov 6 22:01:50 2018 -0200
Branches: blender2.8
https://developer.blender.org/rB4e9911663a22766f6751d33ae84c1ebcc1fae559

Multi-Objects: CURVE_OT_select_similar

Implemented the following methods:
* SIMCURHAND_TYPE
* SIMCURHAND_RADIUS
* SIMCURHAND_WEIGHT
* SIMCURHAND_DIRECTION

Limits:
* DIRECTION does not support surfaces, because `BKE_nurb_bpoint_calc_normal`
  does not work with Nurbs of type `CU_CARDINAL`. This also didn't work prior
  to this patch, so we wait until surfaces are properly supported in EditMode.

* Also DIRECTION should take scaling into consideration. We need our own
  versions of BKE_nurb_bpoint_calc_normal/bezt.

* Threshold default is too large. Not sure if it's better to change the default
  or scale the threshold in code.

Differential Revision: https://developer.blender.org/D3846

Changes from committer (Dalai Felinto):
 * Moved nurb_bpoint_direction_worldspace_get/bezt to functions.
 * Comments hinting at the mode (direction) that require scaling to be
   taken into account - to be addressed by patch creator in a future
   patch.

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

M	source/blender/editors/curve/editcurve_select.c
M	source/blender/editors/include/ED_curve.h
M	source/blender/editors/include/ED_select_utils.h
M	source/blender/editors/mesh/editmesh_select_similar.c
M	source/blender/editors/util/select_utils.c

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

diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 3c4d8caba3a..40ae40d3d13 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -39,12 +39,14 @@
 #include "BLI_rand.h"
 #include "BLI_heap.h"
 #include "BLI_heap_simple.h"
+#include "BLI_kdtree.h"
 
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_fcurve.h"
 #include "BKE_layer.h"
 #include "BKE_report.h"
+#include "BKE_object.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -218,6 +220,18 @@ void ED_curve_nurb_deselect_all(Nurb *nu)
 	}
 }
 
+int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb)
+{
+	int sel = 0;
+	Nurb *nu;
+
+	for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+		sel += ED_curve_nurb_select_count(v3d, nu);
+	}
+
+	return sel;
+}
+
 bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb)
 {
 	Nurb *nu;
@@ -1316,12 +1330,6 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
 /** \name Select Similar
  * \{ */
 
-enum {
-	SIM_CMP_EQ = 0,
-	SIM_CMP_GT,
-	SIM_CMP_LT,
-};
-
 static const EnumPropertyItem curve_prop_similar_compare_types[] = {
 	{SIM_CMP_EQ, "EQUAL", 0, "Equal", ""},
 	{SIM_CMP_GT, "GREATER", 0, "Greater", ""},
@@ -1345,261 +1353,301 @@ static const EnumPropertyItem curve_prop_similar_types[] = {
 	{0, NULL, 0, NULL, NULL}
 };
 
-static int curve_select_similar_cmp_fl(const float delta, const float thresh, const int compare)
+/** Note: This function should actually take scaling into consideration. */
+static void nurb_bezt_direction_worldspace_get(Object *ob, Nurb *nu, BezTriple *bezt, float r_dir[3])
 {
-	switch (compare) {
-		case SIM_CMP_EQ:
-			return (fabsf(delta) <= thresh);
-		case SIM_CMP_GT:
-			return ((delta + thresh) >= 0.0f);
-		case SIM_CMP_LT:
-			return ((delta - thresh) <= 0.0f);
-		default:
-			BLI_assert(0);
-			return 0;
-	}
+	float rmat[3][3];
+	BKE_nurb_bezt_calc_normal(nu, bezt, r_dir);
+	BKE_object_rot_to_mat3(ob, rmat, true);
+	mul_m3_v3(rmat, r_dir);
 }
 
-
-static void curve_select_similar_direction__bezt(Nurb *nu, const float dir_ref[3], float angle_cos)
+/** Note: This function should actually take scaling into consideration. */
+static void nurb_bpoint_direction_worldspace_get(Object *ob, Nurb *nu, BPoint *bp, float r_dir[3])
 {
-	BezTriple *bezt;
-	int i;
-
-	for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
-		if (!bezt->hide) {
-			float dir[3];
-			BKE_nurb_bezt_calc_normal(nu, bezt, dir);
-			if (fabsf(dot_v3v3(dir_ref, dir)) >= angle_cos) {
-				select_beztriple(bezt, SELECT, SELECT, VISIBLE);
-			}
-		}
-	}
+	float rmat[3][3];
+	BKE_nurb_bpoint_calc_normal(nu, bp, r_dir);
+	BKE_object_rot_to_mat3(ob, rmat, true);
+	mul_m3_v3(rmat, r_dir);
 }
 
-static void curve_select_similar_direction__bp(Nurb *nu, const float dir_ref[3], float angle_cos)
+static void curve_nurb_selected_type_get(Object *ob, Nurb *nu, const int type, KDTree *r_tree)
 {
-	BPoint *bp;
-	int i;
+	float tree_entry[3] = {0.0f, 0.0f, 0.0f};
 
-	for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
-		if (!bp->hide) {
-			float dir[3];
-			BKE_nurb_bpoint_calc_normal(nu, bp, dir);
-			if (fabsf(dot_v3v3(dir_ref, dir)) >= angle_cos) {
-				select_bpoint(bp, SELECT, SELECT, VISIBLE);
+	if (nu->type == CU_BEZIER) {
+		BezTriple *bezt;
+		int i;
+		int tree_index = 0;
+
+		for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+			if ((!bezt->hide) && (bezt->f1 & SELECT)) {
+
+				switch (type) {
+					case SIMCURHAND_RADIUS:
+					{
+						float radius_ref = bezt->radius;
+						tree_entry[0] = radius_ref;
+						break;
+					}
+					case SIMCURHAND_WEIGHT:
+					{
+						float weight_ref = bezt->weight;
+						tree_entry[0] = weight_ref;
+						break;
+					}
+					case SIMCURHAND_DIRECTION:
+					{
+						nurb_bezt_direction_worldspace_get(ob, nu, bezt, tree_entry);
+						break;
+					}
+				}
+				BLI_kdtree_insert(r_tree, tree_index++, tree_entry);
 			}
 		}
 	}
-}
-
-static bool curve_select_similar_direction(ListBase *editnurb, Curve *cu, float thresh)
-{
-	Nurb *nu, *act_nu;
-	void *act_vert;
-	float dir[3];
-	float angle_cos;
-
-	if (!BKE_curve_nurb_vert_active_get(cu, &act_nu, &act_vert)) {
-		return false;
-	}
-
-	if (act_nu->type == CU_BEZIER) {
-		BKE_nurb_bezt_calc_normal(act_nu, act_vert, dir);
-	}
 	else {
-		BKE_nurb_bpoint_calc_normal(act_nu, act_vert, dir);
-	}
-
-	/* map 0-1 to radians, 'cos' for comparison */
-	angle_cos = cosf(thresh * (float)M_PI_2);
+		BPoint *bp;
+		int i;
+		int tree_index=0;
 
-	for (nu = editnurb->first; nu; nu = nu->next) {
-		if (nu->type == CU_BEZIER) {
-			curve_select_similar_direction__bezt(nu, dir, angle_cos);
-		}
-		else {
-			curve_select_similar_direction__bp(nu, dir, angle_cos);
+		for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+			if (!bp->hide && bp->f1 & SELECT) {
+				switch (type) {
+					case SIMCURHAND_RADIUS:
+					{
+						float radius_ref = bp->radius;
+						tree_entry[0] = radius_ref;
+						break;
+					}
+					case SIMCURHAND_WEIGHT:
+					{
+						float weight_ref = bp->weight;
+						tree_entry[0] = weight_ref;
+						break;
+					}
+					case SIMCURHAND_DIRECTION:
+					{
+						nurb_bpoint_direction_worldspace_get(ob, nu, bp, tree_entry);
+						break;
+					}
+				}
+				BLI_kdtree_insert(r_tree, tree_index++, tree_entry);
+			}
 		}
 	}
-
-	return true;
 }
 
-static void curve_select_similar_radius__bezt(Nurb *nu, float radius_ref, int compare, float thresh)
+static bool curve_nurb_select_similar_type(
+        Object *ob, Nurb *nu, const int type,
+        const KDTree *tree, const float thresh, const int compare)
 {
-	BezTriple *bezt;
-	int i;
+	const float thresh_cos = cosf(thresh * (float)M_PI_2);
+	bool changed = false;
 
-	for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
-		if (!bezt->hide) {
-			if (curve_select_similar_cmp_fl(bezt->radius - radius_ref, thresh, compare)) {
-				select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+	if (nu->type == CU_BEZIER) {
+		BezTriple *bezt;
+		int i;
+
+		for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
+			if (!bezt->hide) {
+				bool select = false;
+
+				switch (type) {
+					case SIMCURHAND_RADIUS:
+					{
+						float radius_ref = bezt->radius;
+						if (ED_select_similar_compare_float_tree(tree, radius_ref, thresh, compare)) {
+							select = true;
+						}
+						break;
+					}
+					case SIMCURHAND_WEIGHT:
+					{
+						float weight_ref = bezt->weight;
+						if (ED_select_similar_compare_float_tree(tree, weight_ref, thresh, compare)) {
+							select = true;
+						}
+						break;
+					}
+					case SIMCURHAND_DIRECTION:
+					{
+						float dir[3];
+						nurb_bezt_direction_worldspace_get(ob, nu, bezt, dir);
+						KDTreeNearest nearest;
+						if (BLI_kdtree_find_nearest(tree, dir, &nearest) != -1) {
+							float orient = angle_normalized_v3v3(dir, nearest.co);
+							float delta = thresh_cos - fabsf(cosf(orient));
+							if (ED_select_similar_compare_float(delta, thresh, compare)) {
+								select = true;
+							}
+						}
+						break;
+					}
+				}
+
+				if (select) {
+					select_beztriple(bezt, SELECT, SELECT, VISIBLE);
+					changed = true;
+				}
 			}
 		}
 	}
-}
+	else {
+		BPoint *bp;
+		int i;
 
-static void curve_select_similar_radius__bp(Nurb *nu, float radius_ref, int compare, float thresh)
-{
-	BPoint *bp;
-	int i;
+		for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
+			if (!bp->hide) {
+				bool select = false;
+
+				switch (type) {
+					case SIMCURHAND_RADIUS:
+					{
+						float radius_ref = bp->radius;
+						if (ED_select_similar_compare_float_tree(tree, radius_ref, thresh, compare)) {
+							select = true;
+						}
+						break;
+					}
+					case SIMCURHAND_WEIGHT:
+					{
+						float weight_ref = bp->weight;
+						if (ED_select_similar_compare_float_tree(tree, weight_ref, thresh, compare)) {
+							select = true;
+						}
+						break;
+					}
+					case SIMCURHAND_DIRECTION:
+					{
+						float dir[3];
+						nurb_bpoint_direction_worldspace_get(ob, nu, bp, dir);
+						KDTreeNearest nearest;
+						if (BLI_kdtree_find_nearest(tree, dir, &nearest) != -1) {
+							float orient = angle_normalized_v3v3(dir, nearest.co);
+							float delta = fabsf(cosf(orient)) - thresh_cos;
+							if (ED_select_similar_compare_float(delta, thresh, compare)) {
+								select = true;
+							}
+						}
+						break;
+					}
+				}
 
-	for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
-		if (!bp->hide) {
-			if (curve_select_similar_cmp_fl(bp->radius - radius_ref, thresh, compare)) {
-				select_bpoint(bp, SELECT, SELECT, VISIBLE);
+				if (select) {
+					select_bpoint(bp, SELECT, SELECT, VISIBLE);
+					changed = true;
+				}
 			}
 		}
 	}
+	return changed;
 }
 
-static bool curve_select_similar_radius(ListBase *editnurb, Curve *cu, float compare, float thresh)
+static int curve_select_similar_exec(bContext *C, wmOperator *op)
 {
-	Nurb *nu, *act_nu;
-	void *act_vert;
-	float radius_ref;
+	/* Get props. */
+	const int optype = RNA_enum_get(op->ptr, "type");
+	const float thresh = RNA_float_get(op->ptr, "threshold");
+	const int compare = RNA_enum_get(op->ptr, "compare");
 
-	if (!BKE_curve_nurb_vert_active_get(cu, &act_nu, &act_vert)) {
-		return false;
-	}
+	ViewLayer *view_layer = CTX_data_view_layer(C);
+	View3D *v3d = CTX_wm_view3d(C);
+	int tot_nurbs_selected_all = 0;
+	uint objects_len = 0;
+	Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
 
-	if (act_nu->type == CU_BEZIER) {
-		radius_ref = ((BezTriple *)act_vert)->radius;
-	}
-	else {
-		radius_ref = ((BPoint *)act_vert)->radius;
+	for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+		Object *obedit = objects[ob_index];
+		Curve *cu = obedit->data;
+		tot_nurbs_selected_all += ED_curve_select_count(v3d, cu->editnurb);
 	}
 
-	/* make relative */
-	thresh *= radius_ref;
-
-	for (nu = editnurb->first; nu; nu = nu->next) {
-		if (nu->type == CU_BEZIER) {
-			curve_select_similar_radius__bezt(nu, radius_ref, compare, thresh);
-		}
-		else {
-			curve_select_similar_radius__bp(nu, radius_ref, compare, thresh);
-		}
+	if (tot_nurbs_selected_all == 0) {
+		BKE_report(op->reports, RPT_ERROR, 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list