static bool swap_selection_bpoint(BPoint *bp)
{
	if (bp->f1 & SELECT)
		return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
	else
		return select_bpoint(bp, 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 select_nth_bp(Nurb *nu, BPoint *bp, int nth, int skip, int offset)
{
	int a, startrow, startpnt;
	int row, pnt;

	startrow = (bp - nu->bp) / nu->pntsu;
	startpnt = (bp - nu->bp) % nu->pntsu;

	a = nu->pntsu * nu->pntsv;
	bp = &nu->bp[a - 1];
	row = nu->pntsv - 1;
	pnt = nu->pntsu - 1;

	while (a--) {
		const int depth = abs(pnt - startpnt) + abs(row - startrow);
		if ((offset + depth) % (skip + nth) >= skip) {
			select_bpoint(bp, DESELECT, SELECT, HIDDEN);
		}

		pnt--;
		if (pnt < 0) {
			pnt = nu->pntsu - 1;
			row--;
		}

		bp--;
	}
}
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++;
			}
		}
	}
}
Ejemplo n.º 5
0
static void select_nth_bp(Nurb *nu, BPoint *bp, const struct CheckerIntervalParams *params)
{
	int a, startrow, startpnt;
	int row, pnt;

	startrow = (bp - nu->bp) / nu->pntsu;
	startpnt = (bp - nu->bp) % nu->pntsu;

	a = nu->pntsu * nu->pntsv;
	bp = &nu->bp[a - 1];
	row = nu->pntsv - 1;
	pnt = nu->pntsu - 1;

	while (a--) {
		const int depth = abs(pnt - startpnt) + abs(row - startrow);
		if (WM_operator_properties_checker_interval_test(params, depth)) {
			select_bpoint(bp, DESELECT, SELECT, HIDDEN);
		}

		pnt--;
		if (pnt < 0) {
			pnt = nu->pntsu - 1;
			row--;
		}

		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__bp(Nurb *nu, float weight_ref, int compare, float thresh)
{
	BPoint *bp;
	int i;

	for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) {
		if (!bp->hide) {
			if (curve_select_similar_cmp_fl(bp->weight - weight_ref, thresh, compare)) {
				select_bpoint(bp, SELECT, SELECT, VISIBLE);
			}
		}
	}
}
static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	Curve *cu = obedit->data;
	ListBase *editnurb = object_editcurve_get(obedit);
	static BPoint *last = NULL;
	static int direction = 0;
	Nurb *nu = NULL;
	BPoint *bp = NULL;
	int u = 0, v = 0, a, b;

	if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp))
		return OPERATOR_CANCELLED;

	if (last == bp) {
		direction = 1 - direction;
		BKE_nurbList_flag_set(editnurb, 0);
	}
	last = bp;

	u = cu->actvert % nu->pntsu;
	v = cu->actvert / nu->pntsu;
	bp = nu->bp;
	for (a = 0; a < nu->pntsv; a++) {
		for (b = 0; b < nu->pntsu; b++, bp++) {
			if (direction) {
				if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE);
			}
			else {
				if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE);
			}
		}
	}

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

	return OPERATOR_FINISHED;
}
static void curve_select_similar_direction__bp(Nurb *nu, const float dir_ref[3], float angle_cos)
{
	BPoint *bp;
	int i;

	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);
			}
		}
	}
}
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 int select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	ListBase *editnurb = object_editcurve_get(obedit);
	Nurb *nu;
	BPoint *bp, *tempbp;
	int a;
	short sel = 0;

	/* note that NURBS surface is a special case because we mimic */
	/* the behavior of "select more" of mesh tools.	      */
	/* The algorithm is designed to work in planar cases so it    */
	/* may not be optimal always (example: end of NURBS sphere)   */
	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 > 0) {
				if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) {
					/* upper control point */
					if (a % nu->pntsu != 0) {
						tempbp = bp - 1;
						if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
					}

					/* left control point. select only if it is not selected already */
					if (a - nu->pntsu > 0) {
						sel = 0;
						tempbp = bp + nu->pntsu;
						if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
						/* make sure selected bpoint is discarded */
						if (sel == 1) BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu);
					}

					/* right control point */
					if (a + nu->pntsu < nu->pntsu * nu->pntsv) {
						tempbp = bp - nu->pntsu;
						if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
					}

					/* lower control point. skip next bp in case selection was made */
					if (a % nu->pntsu != 1) {
						sel = 0;
						tempbp = bp + 1;
						if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE);
						if (sel) {
							bp++;
							a--;
						}
					}
				}

				bp++;
				a--;
			}

			MEM_freeN(selbpoints);
		}
	}
	else {
		select_adjacent_cp(editnurb, 1, 0, SELECT);
		select_adjacent_cp(editnurb, -1, 0, SELECT);
	}

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, 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);
}