Example #1
0
static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2],
                                        int num_points, char handle_type)
{
	ScrArea *sa = CTX_wm_area(C);
	Scene *scene = CTX_data_scene(C);
	Mask *mask;
	MaskLayer *mask_layer;
	MaskSpline *new_spline;
	float scale, location[2], frame_size[2];
	int i, width, height;
	int size = RNA_float_get(op->ptr, "size");

	ED_mask_get_size(sa, &width, &height);
	scale = (float)size / max_ii(width, height);

	/* Get location in mask space. */
	frame_size[0] = width;
	frame_size[1] = height;
	RNA_float_get_array(op->ptr, "location", location);
	location[0] /= width;
	location[1] /= height;
	BKE_mask_coord_from_frame(location, location, frame_size);

	/* Make it so new primitive is centered to mouse location. */
	location[0] -= 0.5f * scale;
	location[1] -= 0.5f * scale;

	mask_layer = ED_mask_layer_ensure(C);
	mask = CTX_data_edit_mask(C);

	ED_mask_select_toggle_all(mask, SEL_DESELECT);

	new_spline = BKE_mask_spline_add(mask_layer);
	new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
	new_spline->tot_point = num_points;
	new_spline->points = MEM_recallocN(new_spline->points,
	                                   sizeof(MaskSplinePoint) * new_spline->tot_point);

	mask_layer->act_spline = new_spline;
	mask_layer->act_point = NULL;

	for (i = 0; i < num_points; i++) {
		MaskSplinePoint *new_point = &new_spline->points[i];

		copy_v2_v2(new_point->bezt.vec[1], points[i]);
		mul_v2_fl(new_point->bezt.vec[1], scale);
		add_v2_v2(new_point->bezt.vec[1], location);

		new_point->bezt.h1 = handle_type;
		new_point->bezt.h2 = handle_type;
		BKE_mask_point_select_set(new_point, true);
	}

	WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);

	/* TODO: only update this spline */
	BKE_mask_update_display(mask, CFRA);

	return OPERATOR_FINISHED;
}
Example #2
0
static bool do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, short select)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	rcti rect;
	bool changed = false;

	/* get rectangle from operator */
	BLI_lasso_boundbox(&rect, mcords, moves);

	/* do actual selection */
	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];
				MaskSplinePoint *point_deform = &points_array[i];

				/* TODO: handles? */
				/* TODO: uw? */

				float screen_co[2];

				/* point in screen coords */
				ED_mask_point_pos__reverse(sa, ar,
				                           point_deform->bezt.vec[1][0], point_deform->bezt.vec[1][1],
				                           &screen_co[0], &screen_co[1]);

				if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
				    BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
				{
					BKE_mask_point_select_set(point, select);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
				}

				changed = true;
			}
		}
	}

	if (changed) {
		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
	}

	return changed;
}
Example #3
0
/* 'sel' select  */
void ED_mask_spline_select_set(MaskSpline *spline, const bool do_select)
{
	int i;

	if (do_select)
		spline->flag |= SELECT;
	else
		spline->flag &= ~SELECT;

	for (i = 0; i < spline->tot_point; i++) {
		MaskSplinePoint *point = &spline->points[i];

		BKE_mask_point_select_set(point, do_select);
	}
}
Example #4
0
static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	SlidePointData *slidedata = slide_point_customdata(C, op, event);

	if (slidedata) {
		Mask *mask = CTX_data_edit_mask(C);

		op->customdata = slidedata;

		WM_event_add_modal_handler(C, op);

#if 0
		if (slidedata->uw) {
			if ((slidedata->uw->flag & SELECT) == 0) {
				ED_mask_select_toggle_all(mask, SEL_DESELECT);

				slidedata->uw->flag |= SELECT;

				ED_mask_select_flush_all(mask);
			}
		}
		else if (!MASKPOINT_ISSEL_ANY(slidedata->point)) {
			ED_mask_select_toggle_all(mask, SEL_DESELECT);

			BKE_mask_point_select_set(slidedata->point, TRUE);

			ED_mask_select_flush_all(mask);
		}
#endif

		slidedata->masklay->act_spline = slidedata->spline;
		slidedata->masklay->act_point = slidedata->point;

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_RUNNING_MODAL;
	}

	return OPERATOR_PASS_THROUGH;
}
Example #5
0
void ED_mask_select_toggle_all(Mask *mask, int action)
{
	MaskLayer *masklay;

	if (action == SEL_TOGGLE) {
		if (ED_mask_select_check(mask))
			action = SEL_DESELECT;
		else
			action = SEL_SELECT;
	}

	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {

		if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
			continue;
		}

		if (action == SEL_INVERT) {
			/* we don't have generic functions for this, its restricted to this operator
			 * if one day we need to re-use such functionality, they can be split out */

			MaskSpline *spline;
			if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
				continue;
			}
			for (spline = masklay->splines.first; spline; spline = spline->next) {
				int i;
				for (i = 0; i < spline->tot_point; i++) {
					MaskSplinePoint *point = &spline->points[i];
					BKE_mask_point_select_set(point, !MASKPOINT_ISSEL_ANY(point));
				}
			}

		}
		else {
			ED_mask_layer_select_set(masklay, (action == SEL_SELECT) ? true : false);
		}
	}
}
Example #6
0
static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
	Scene *scene = CTX_data_scene(C);
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *mask_layer = BKE_mask_layer_active(mask);
	MaskSpline *spline;

	if (mask_layer == NULL) {
		return OPERATOR_CANCELLED;
	}

	for (spline = mask_layer->splines.last;
	     spline;
	     spline = spline->prev)
	{
		MaskSplinePoint *point = spline->points;
		int i = 0;
		while (i < spline->tot_point) {
			int start = i, end = -1;
			/* Find next selected segment. */
			while (MASKPOINT_ISSEL_ANY(point)) {
				BKE_mask_point_select_set(point, false);
				end = i;
				if (i >= spline->tot_point - 1) {
					break;
				}
				i++;
				point++;
			}
			if (end >= start) {
				MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
				MaskSplinePoint *new_point;
				int b;

				/* BKE_mask_spline_add might allocate the points, need to free them in this case. */
				if (new_spline->points) {
					MEM_freeN(new_spline->points);
				}

				/* Copy options from old spline. */
				new_spline->flag = spline->flag;
				new_spline->offset_mode = spline->offset_mode;
				new_spline->weight_interp = spline->weight_interp;
				new_spline->parent = spline->parent;

				/* Allocate new points and copy them from old spline. */
				new_spline->tot_point = end - start + 1;
				new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
				                                 "duplicated mask points");

				memcpy(new_spline->points, spline->points + start,
				       new_spline->tot_point * sizeof(MaskSplinePoint));

				/* Select points and duplicate their UWs (if needed). */
				for (b = 0, new_point = new_spline->points;
				     b < new_spline->tot_point;
				     b++, new_point++)
				{
					if (new_point->uw) {
						new_point->uw = MEM_dupallocN(new_point->uw);
					}
					BKE_mask_point_select_set(new_point, true);
				}

				/* Clear cyclic flag if we didn't copy the whole spline. */
				if (new_spline->flag & MASK_SPLINE_CYCLIC) {
					if (start != 0 || end != spline->tot_point - 1) {
						new_spline->flag &= ~MASK_SPLINE_CYCLIC;
					}
				}

				/* Flush selection to splines. */
				new_spline->flag |= SELECT;
				spline->flag &= ~SELECT;

				mask_layer->act_spline = new_spline;
			}
			i++;
			point++;
		}
	}

	/* TODO: only update edited splines */
	BKE_mask_update_display(mask, CFRA);

	WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);

	return OPERATOR_FINISHED;
}
Example #7
0
static int mask_select_more_less(bContext *C, bool more)
{
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;

	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			const bool cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0;
			bool start_sel, end_sel, prev_sel, cur_sel;
			int i;

			/* reselect point if any handle is selected to make the result more predictable */
			for (i = 0; i < spline->tot_point; i++) {
				BKE_mask_point_select_set(spline->points + i, MASKPOINT_ISSEL_ANY(spline->points + i));
			}

			/* select more/less does not affect empty/single point splines */
			if (spline->tot_point < 2) {
				continue;
			}

			if (cyclic) {
				start_sel = !!MASKPOINT_ISSEL_KNOT(spline->points);
				end_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[spline->tot_point - 1]);
			}
			else {
				start_sel = false;
				end_sel = false;
			}

			for (i = 0; i < spline->tot_point; i++) {
				if (i == 0 && !cyclic) {
					continue;
				}

				prev_sel = (i > 0) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i - 1]) : end_sel;
				cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);

				if (cur_sel != more) {
					if (prev_sel == more) {
						BKE_mask_point_select_set(&spline->points[i], more);
					}
					i++;
				}
			}

			for (i = spline->tot_point - 1; i >= 0; i--) {
				if (i == spline->tot_point - 1 && !cyclic) {
					continue;
				}

				prev_sel = (i < spline->tot_point - 1) ? !!MASKPOINT_ISSEL_KNOT(&spline->points[i + 1]) : start_sel;
				cur_sel = !!MASKPOINT_ISSEL_KNOT(&spline->points[i]);

				if (cur_sel != more) {
					if (prev_sel == more) {
						BKE_mask_point_select_set(&spline->points[i], more);
					}
					i--;
				}
			}
		}
	}

	WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

	return OPERATOR_FINISHED;
}
Example #8
0
static int circle_select_exec(bContext *C, wmOperator *op)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	float zoomx, zoomy, offset[2], ellipse[2];
	int width, height;
	bool changed = false;

	/* get operator properties */
	const int x = RNA_int_get(op->ptr, "x");
	const int y = RNA_int_get(op->ptr, "y");
	const int radius = RNA_int_get(op->ptr, "radius");

	const bool select = !RNA_boolean_get(op->ptr, "deselect");

	/* compute ellipse and position in unified coordinates */
	ED_mask_get_size(sa, &width, &height);
	ED_mask_zoom(sa, ar, &zoomx, &zoomy);
	width = height = max_ii(width, height);

	ellipse[0] = width * zoomx / radius;
	ellipse[1] = height * zoomy / radius;

	ED_mask_point_pos(sa, ar, x, y, &offset[0], &offset[1]);

	/* do actual selection */
	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];
				MaskSplinePoint *point_deform = &points_array[i];

				if (mask_spline_point_inside_ellipse(&point_deform->bezt, offset, ellipse)) {
					BKE_mask_point_select_set(point, select);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);

					changed = true;
				}
			}
		}
	}

	if (changed) {
		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
Example #9
0
static int border_select_exec(bContext *C, wmOperator *op)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	rcti rect;
	rctf rectf;
	bool changed = false;
	const bool select = !RNA_boolean_get(op->ptr, "deselect");
	const bool extend = RNA_boolean_get(op->ptr, "extend");

	/* get rectangle from operator */
	WM_operator_properties_border_to_rcti(op, &rect);

	ED_mask_point_pos(sa, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
	ED_mask_point_pos(sa, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);

	/* do actual selection */
	for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
		MaskSpline *spline;

		if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
			continue;
		}

		for (spline = masklay->splines.first; spline; spline = spline->next) {
			MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

			for (i = 0; i < spline->tot_point; i++) {
				MaskSplinePoint *point = &spline->points[i];
				MaskSplinePoint *point_deform = &points_array[i];

				/* TODO: handles? */
				/* TODO: uw? */

				if (BLI_rctf_isect_pt_v(&rectf, point_deform->bezt.vec[1])) {
					BKE_mask_point_select_set(point, select);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select);
				}
				else if (!extend) {
					BKE_mask_point_select_set(point, false);
					BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, false);
				}

				changed = true;
			}
		}
	}

	if (changed) {
		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
Example #10
0
static int select_exec(bContext *C, wmOperator *op)
{
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	MaskSpline *spline;
	MaskSplinePoint *point = NULL;
	float co[2];
	bool extend = RNA_boolean_get(op->ptr, "extend");
	bool deselect = RNA_boolean_get(op->ptr, "deselect");
	bool toggle = RNA_boolean_get(op->ptr, "toggle");
	eMaskWhichHandle which_handle;
	const float threshold = 19;

	RNA_float_get_array(op->ptr, "location", co);

	point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &which_handle, NULL);

	if (extend == false && deselect == false && toggle == false)
		ED_mask_select_toggle_all(mask, SEL_DESELECT);

	if (point) {
		if (which_handle != MASK_WHICH_HANDLE_NONE) {
			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				BKE_mask_point_select_set_handle(point, which_handle, true);
			}
			else if (deselect) {
				BKE_mask_point_select_set_handle(point, which_handle, false);
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (!MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
					BKE_mask_point_select_set_handle(point, which_handle, true);
				}
				else if (toggle) {
					BKE_mask_point_select_set_handle(point, which_handle, false);
				}
			}
		}
		else {
			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				BKE_mask_point_select_set(point, true);
			}
			else if (deselect) {
				BKE_mask_point_select_set(point, false);
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (!MASKPOINT_ISSEL_ANY(point)) {
					BKE_mask_point_select_set(point, true);
				}
				else if (toggle) {
					BKE_mask_point_select_set(point, false);
				}
			}
		}

		masklay->act_spline = spline;
		masklay->act_point = point;

		ED_mask_select_flush_all(mask);

		WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

		return OPERATOR_FINISHED;
	}
	else {
		MaskSplinePointUW *uw;

		if (ED_mask_feather_find_nearest(C, mask, co, threshold, &masklay, &spline, &point, &uw, NULL)) {

			if (extend) {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (uw) uw->flag |= SELECT;
			}
			else if (deselect) {
				if (uw) uw->flag &= ~SELECT;
			}
			else {
				masklay->act_spline = spline;
				masklay->act_point = point;

				if (uw) {
					if (!(uw->flag & SELECT)) {
						uw->flag |= SELECT;
					}
					else if (toggle) {
						uw->flag &= ~SELECT;
					}
				}
			}

			ED_mask_select_flush_all(mask);

			WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);

			return OPERATOR_FINISHED;
		}
	}

	return OPERATOR_PASS_THROUGH;
}