static bool swap_selection_beztriple(BezTriple *bezt)
{
	if (bezt->f2 & SELECT)
		return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
	else
		return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
}
static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_dst)
{
	const int u = nu->pntsu;
	int i;

	if (vert_src > vert_dst) {
		SWAP(int, vert_src, vert_dst);
	}

	if (nu->flagu & CU_NURB_CYCLIC) {
		if (curve_calc_dist_span(nu, vert_src, vert_dst) >
		    curve_calc_dist_span(nu, vert_dst, vert_src))
		{
			SWAP(int, vert_src, vert_dst);
		}
	}

	i = vert_src;
	while (true) {
		if (nu->type & CU_BEZIER) {
			select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN);
		}
		else {
			select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN);
		}

		if (i == vert_dst) {
			break;
		}
		i = (i + 1) % u;
	}
}
static void curve_select_random(ListBase *editnurb, float randfac, bool select)
{
	Nurb *nu;
	BezTriple *bezt;
	BPoint *bp;
	int a;

	for (nu = editnurb->first; nu; nu = nu->next) {
		if (nu->type == CU_BEZIER) {
			bezt = nu->bezt;
			a = nu->pntsu;
			while (a--) {
				if (!bezt->hide) {
					if (BLI_frand() < randfac) {
						select_beztriple(bezt, select, SELECT, VISIBLE);
					}
				}
				bezt++;
			}
		}
		else {
			bp = nu->bp;
			a = nu->pntsu * nu->pntsv;

			while (a--) {
				if (!bp->hide) {
					if (BLI_frand() < randfac) {
						select_bpoint(bp, select, SELECT, VISIBLE);
					}
				}
				bp++;
			}
		}
	}
}
/**
 * \param next: -1/1 for prev/next
 * \param cont: when true select continuously
 * \param selstatus: inverts behavior
 */
static void select_adjacent_cp(
        ListBase *editnurb, short next,
        const bool cont, const bool selstatus)
{
	Nurb *nu;
	BezTriple *bezt;
	BPoint *bp;
	int a;
	bool lastsel = false;

	if (next == 0) return;

	for (nu = editnurb->first; nu; nu = nu->next) {
		lastsel = false;
		if (nu->type == CU_BEZIER) {
			a = nu->pntsu;
			bezt = nu->bezt;
			if (next < 0) bezt = &nu->bezt[a - 1];
			while (a--) {
				if (a - abs(next) < 0) break;
				if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) {
					bezt += next;
					if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) {
						short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);
						if ((sel == 1) && (cont == 0)) lastsel = true;
					}
				}
				else {
					bezt += next;
					lastsel = false;
				}
				/* move around in zigzag way so that we go through each */
				bezt -= (next - next / abs(next));
			}
		}
		else {
			a = nu->pntsu * nu->pntsv;
			bp = nu->bp;
			if (next < 0) bp = &nu->bp[a - 1];
			while (a--) {
				if (a - abs(next) < 0) break;
				if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) {
					bp += next;
					if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) {
						short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);
						if ((sel == 1) && (cont == 0)) lastsel = true;
					}
				}
				else {
					bp += next;
					lastsel = false;
				}
				/* move around in zigzag way so that we go through each */
				bp -= (next - next / abs(next));
			}
		}
	}
}
/* (de)selects first or last of visible part of each Nurb depending on selFirst
 * selFirst: defines the end of which to select
 * doswap: defines if selection state of each first/last control point is swapped
 * selstatus: selection status in case doswap is false
 */
static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus)
{
	ListBase *editnurb = object_editcurve_get(obedit);
	Nurb *nu;
	BPoint *bp;
	BezTriple *bezt;
	Curve *cu;
	int a;

	if (obedit == NULL) return;

	cu = (Curve *)obedit->data;
	cu->actvert = CU_ACT_NONE;

	for (nu = editnurb->first; nu; nu = nu->next) {
		if (nu->type == CU_BEZIER) {
			a = nu->pntsu;

			/* which point? */
			if (selfirst == LAST) { /* select last */
				bezt = &nu->bezt[a - 1];
			}
			else { /* select first */
				bezt = nu->bezt;
			}

			while (a--) {
				bool sel;
				if (doswap) sel = swap_selection_beztriple(bezt);
				else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE);

				if (sel == true) break;
			}
		}
		else {
			a = nu->pntsu * nu->pntsv;

			/* which point? */
			if (selfirst == LAST) { /* select last */
				bp = &nu->bp[a - 1];
			}
			else { /* select first */
				bp = nu->bp;
			}

			while (a--) {
				if (bp->hide == 0) {
					bool sel;
					if (doswap) sel = swap_selection_bpoint(bp);
					else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE);

					if (sel == true) break;
				}
			}
		}
	}
}
static void curve_select_similar_weight__bezt(Nurb *nu, float weight_ref, int compare, float thresh)
{
	BezTriple *bezt;
	int i;

	for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) {
		if (!bezt->hide) {
			if (curve_select_similar_cmp_fl(bezt->weight - weight_ref, thresh, compare)) {
				select_beztriple(bezt, SELECT, SELECT, VISIBLE);
			}
		}
	}
}
static void curve_select_similar_direction__bezt(Nurb *nu, const float dir_ref[3], float angle_cos)
{
	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);
			}
		}
	}
}
static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth, int skip, int offset)
{
	int a, start;

	start = bezt - nu->bezt;
	a = nu->pntsu;
	bezt = &nu->bezt[a - 1];

	while (a--) {
		const int depth = abs(start - a);
		if ((offset + depth) % (skip + nth) >= skip) {
			select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
		}

		bezt--;
	}
}
Example #9
0
static void select_nth_bezt(Nurb *nu, BezTriple *bezt, const struct CheckerIntervalParams *params)
{
	int a, start;

	start = bezt - nu->bezt;
	a = nu->pntsu;
	bezt = &nu->bezt[a - 1];

	while (a--) {
		const int depth = abs(start - a);
		if (WM_operator_properties_checker_interval_test(params, depth)) {
			select_beztriple(bezt, DESELECT, SELECT, HIDDEN);
		}

		bezt--;
	}
}
static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	Object *obedit = CTX_data_edit_object(C);
	ViewContext vc;
	Nurb *nu;
	BezTriple *bezt;
	BPoint *bp;
	int a;
	const bool select = !RNA_boolean_get(op->ptr, "deselect");

	view3d_operator_needs_opengl(C);
	view3d_set_viewcontext(C, &vc);

	if (!ED_curve_pick_vert(&vc, 1, event->mval, &nu, &bezt, &bp, NULL)) {
		return OPERATOR_CANCELLED;
	}

	if (bezt) {
		a = nu->pntsu;
		bezt = nu->bezt;
		while (a--) {
			select_beztriple(bezt, select, SELECT, VISIBLE);
			bezt++;
		}
	}
	else if (bp) {
		a = nu->pntsu * nu->pntsv;
		bp = nu->bp;
		while (a--) {
			select_bpoint(bp, select, SELECT, VISIBLE);
			bp++;
		}
	}

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
	if (!select) {
		BKE_curve_nurb_vert_active_validate(obedit->data);
	}

	return OPERATOR_FINISHED;
}
/* basic method: deselect if control point doesn't have all neighbors selected */
static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	ListBase *editnurb = object_editcurve_get(obedit);
	Nurb *nu;
	BPoint *bp;
	BezTriple *bezt;
	int a;
	int sel = 0;
	short lastsel = false;

	if (obedit->type == OB_SURF) {
		for (nu = editnurb->first; nu; nu = nu->next) {
			BLI_bitmap *selbpoints;
			a = nu->pntsu * nu->pntsv;
			bp = nu->bp;
			selbpoints = BLI_BITMAP_NEW(a, "selectlist");
			while (a--) {
				if ((bp->hide == 0) && (bp->f1 & SELECT)) {
					sel = 0;

					/* check if neighbors have been selected */
					/* edges of surface are an exception */
					if ((a + 1) % nu->pntsu == 0) {
						sel++;
					}
					else {
						bp--;
						if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
						bp++;
					}

					if ((a + 1) % nu->pntsu == 1) {
						sel++;
					}
					else {
						bp++;
						if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
						bp--;
					}

					if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) {
						sel++;
					}
					else {
						bp -= nu->pntsu;
						if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++;
						bp += nu->pntsu;
					}

					if (a < nu->pntsu) {
						sel++;
					}
					else {
						bp += nu->pntsu;
						if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
						bp -= nu->pntsu;
					}

					if (sel != 4) {
						select_bpoint(bp, DESELECT, SELECT, VISIBLE);
						BLI_BITMAP_ENABLE(selbpoints, a);
					}
				}
				else {
					lastsel = false;
				}

				bp++;
			}

			MEM_freeN(selbpoints);
		}
	}
	else {
		for (nu = editnurb->first; nu; nu = nu->next) {
			lastsel = false;
			/* check what type of curve/nurb it is */
			if (nu->type == CU_BEZIER) {
				a = nu->pntsu;
				bezt = nu->bezt;
				while (a--) {
					if ((bezt->hide == 0) && (bezt->f2 & SELECT)) {
						sel = (lastsel == 1);

						/* check if neighbors have been selected */
						/* first and last are exceptions */
						if (a == nu->pntsu - 1) {
							sel++;
						}
						else {
							bezt--;
							if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
							bezt++;
						}

						if (a == 0) {
							sel++;
						}
						else {
							bezt++;
							if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++;
							bezt--;
						}

						if (sel != 2) {
							select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
							lastsel = true;
						}
						else {
							lastsel = false;
						}
					}
					else {
						lastsel = false;
					}

					bezt++;
				}
			}
			else {
				a = nu->pntsu * nu->pntsv;
				bp = nu->bp;
				while (a--) {
					if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) {
						if (lastsel != 0) sel = 1;
						else sel = 0;

						/* first and last are exceptions */
						if (a == nu->pntsu * nu->pntsv - 1) {
							sel++;
						}
						else {
							bp--;
							if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
							bp++;
						}

						if (a == 0) {
							sel++;
						}
						else {
							bp++;
							if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++;
							bp--;
						}

						if (sel != 2) {
							select_bpoint(bp, DESELECT, SELECT, VISIBLE);
							lastsel = true;
						}
						else {
							lastsel = false;
						}
					}
					else {
						lastsel = false;
					}

					bp++;
				}
			}
		}
	}

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
	BKE_curve_nurb_vert_active_validate(obedit->data);

	return OPERATOR_FINISHED;
}
static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst)
{
	Heap *heap;

	int i, vert_curr;

	int totu = nu->pntsu;
	int totv = nu->pntsv;
	int vert_num = totu * totv;

	/* custom data */
	struct PointAdj {
		int vert, vert_prev;
		float cost;
	} *data;

	/* init connectivity data */
	data = MEM_mallocN(sizeof(*data) * vert_num, __func__);
	for (i = 0; i < vert_num; i++) {
		data[i].vert = i;
		data[i].vert_prev  = -1;
		data[i].cost  = FLT_MAX;
	}

	/* init heap */
	heap = BLI_heap_new();

	BLI_heap_insert(heap, 0.0f, &data[vert_src].vert);
	data[vert_src].cost = 0.0f;
	data[vert_src].vert_prev = vert_src;  /* nop */

	while (!BLI_heap_is_empty(heap)) {
		int axis, sign;
		int u, v;

		vert_curr = *((int *)BLI_heap_popmin(heap));
		if (vert_curr == vert_dst) {
			break;
		}

		BKE_nurb_index_to_uv(nu, vert_curr, &u, &v);

		/* loop over 4 adjacent verts */
		for (sign = -1; sign != 3; sign += 2) {
			for (axis = 0; axis != 2; axis += 1) {
				int uv_other[2] = {u, v};
				int vert_other;

				uv_other[axis] += sign;

				vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]);
				if (vert_other != -1) {
					const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other);

					if (data[vert_other].cost > dist) {
						data[vert_other].cost = dist;
						if (data[vert_other].vert_prev == -1) {
							BLI_heap_insert(heap, data[vert_other].cost, &data[vert_other].vert);
						}
						data[vert_other].vert_prev = vert_curr;
					}
				}

			}
		}

	}

	BLI_heap_free(heap, NULL);

	if (vert_curr == vert_dst) {
		i = 0;
		while (vert_curr != vert_src && i++ < vert_num) {
			if (nu->type == CU_BEZIER) {
				select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN);
			}
			else {
				select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN);
			}
			vert_curr = data[vert_curr].vert_prev;
		}
	}

	MEM_freeN(data);
}