Esempio n. 1
0
/* *** mask point functions which involve evaluation *** */
float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point,
                                           int width, int height,
                                           unsigned int *tot_feather_point)
{
	float *feather, *fp;
	unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
	unsigned int i;

	feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points");

	for (i = 0; i < resol; i++, fp += 2) {
		float u = (float)(i % resol) / resol, weight;
		float co[2], n[2];

		BKE_mask_point_segment_co(spline, point, u, co);
		BKE_mask_point_normal(spline, point, u, n);
		weight = BKE_mask_point_weight(spline, point, u);

		fp[0] = co[0] + n[0] * weight;
		fp[1] = co[1] + n[1] * weight;
	}

	*tot_feather_point = resol;

	return feather;
}
Esempio n. 2
0
float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2]
{
	MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

	int i, tot = 0;
	float (*feather)[2], (*fp)[2];

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

		tot += point->tot_uw + 1;
	}

	/* create data */
	feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points");

	for (i = 0; i < spline->tot_point; i++) {
		MaskSplinePoint *point = &points_array[i];
		BezTriple *bezt = &point->bezt;
		float weight, n[2];
		int j;

		BKE_mask_point_normal(spline, point, 0.0f, n);
		weight = BKE_mask_point_weight(spline, point, 0.0f);

		madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight);
		fp++;

		for (j = 0; j < point->tot_uw; j++) {
			float u = point->uw[j].u;
			float co[2];

			BKE_mask_point_segment_co(spline, point, u, co);
			BKE_mask_point_normal(spline, point, u, n);
			weight = BKE_mask_point_weight(spline, point, u);

			madd_v2_v2v2fl(*fp, co, n, weight);
			fp++;
		}
	}

	*tot_feather_point = tot;

	return feather;
}
Esempio n. 3
0
static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
	SlidePointData *data = (SlidePointData *)op->customdata;
	BezTriple *bezt = &data->point->bezt;
	float co[2], dco[2];

	switch (event->type) {
		case LEFTALTKEY:
		case RIGHTALTKEY:
		case LEFTSHIFTKEY:
		case RIGHTSHIFTKEY:
			if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
				if (data->action == SLIDE_ACTION_FEATHER)
					data->overall_feather = (event->val == KM_PRESS);
				else
					data->curvature_only = (event->val == KM_PRESS);
			}

			if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
				data->accurate = (event->val == KM_PRESS);

			/* fall-through */  /* update CV position */
		case MOUSEMOVE:
		{
			ScrArea *sa = CTX_wm_area(C);
			ARegion *ar = CTX_wm_region(C);

			ED_mask_mouse_pos(sa, ar, event->mval, co);
			sub_v2_v2v2(dco, co, data->co);

			if (data->action == SLIDE_ACTION_HANDLE) {
				float delta[2], offco[2];

				sub_v2_v2v2(delta, data->handle, data->co);

				sub_v2_v2v2(offco, co, data->co);
				if (data->accurate)
					mul_v2_fl(offco, 0.2f);
				add_v2_v2(offco, data->co);
				add_v2_v2(offco, delta);

				BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec);
			}
			else if (data->action == SLIDE_ACTION_POINT) {
				float delta[2];

				copy_v2_v2(delta, dco);
				if (data->accurate)
					mul_v2_fl(delta, 0.2f);

				add_v2_v2v2(bezt->vec[0], data->vec[0], delta);
				add_v2_v2v2(bezt->vec[1], data->vec[1], delta);
				add_v2_v2v2(bezt->vec[2], data->vec[2], delta);
			}
			else if (data->action == SLIDE_ACTION_FEATHER) {
				float vec[2], no[2], p[2], c[2], w, offco[2];
				float *weight = NULL;
				float weight_scalar = 1.0f;
				int overall_feather = data->overall_feather || data->initial_feather;

				add_v2_v2v2(offco, data->feather, dco);

				if (data->uw) {
					/* project on both sides and find the closest one,
					 * prevents flickering when projecting onto both sides can happen */
					const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
					                                               data->uw->u, offco, MASK_PROJ_NEG);
					const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
					                                               data->uw->u, offco, MASK_PROJ_POS);
					float dist_pos = FLT_MAX;
					float dist_neg = FLT_MAX;
					float co_pos[2];
					float co_neg[2];
					float u;

					if (u_pos > 0.0f && u_pos < 1.0f) {
						BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
						dist_pos = len_squared_v2v2(offco, co_pos);
					}

					if (u_neg > 0.0f && u_neg < 1.0f) {
						BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
						dist_neg = len_squared_v2v2(offco, co_neg);
					}

					u = dist_pos < dist_neg ? u_pos : u_neg;

					if (u > 0.0f && u < 1.0f) {
						data->uw->u = u;

						data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
						weight = &data->uw->w;
						weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
						if (weight_scalar != 0.0f) {
							weight_scalar = 1.0f / weight_scalar;
						}

						BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
						BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
					}
				}
				else {
					weight = &bezt->weight;
					/* weight_scalar = 1.0f; keep as is */
					copy_v2_v2(no, data->no);
					copy_v2_v2(p, bezt->vec[1]);
				}

				if (weight) {
					sub_v2_v2v2(c, offco, p);
					project_v2_v2v2(vec, c, no);

					w = len_v2(vec);

					if (overall_feather) {
						float delta;

						if (dot_v2v2(no, vec) <= 0.0f)
							w = -w;

						delta = w - data->weight * data->weight_scalar;

						if (data->orig_spline == NULL) {
							/* restore weight for currently sliding point, so orig_spline would be created
							 * with original weights used
							 */
							*weight = data->weight;

							data->orig_spline = BKE_mask_spline_copy(data->spline);
						}

						slide_point_delta_all_feather(data, delta);
					}
					else {
						if (dot_v2v2(no, vec) <= 0.0f)
							w = 0.0f;

						if (data->orig_spline) {
							/* restore possible overall feather changes */
							slide_point_restore_spline(data);

							BKE_mask_spline_free(data->orig_spline);
							data->orig_spline = NULL;
						}

						if (weight_scalar != 0.0f) {
							*weight = w * weight_scalar;
						}
					}
				}
			}

			WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
			DAG_id_tag_update(&data->mask->id, 0);

			break;
		}

		case LEFTMOUSE:
			if (event->val == KM_RELEASE) {
				Scene *scene = CTX_data_scene(C);

				/* dont key sliding feather uw's */
				if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) {
					if (IS_AUTOKEY_ON(scene)) {
						ED_mask_layer_shape_auto_key(data->masklay, CFRA);
					}
				}

				WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
				DAG_id_tag_update(&data->mask->id, 0);

				free_slide_point_data(op->customdata); /* keep this last! */
				return OPERATOR_FINISHED;
			}

			break;

		case ESCKEY:
			cancel_slide_point(op->customdata);

			WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
			DAG_id_tag_update(&data->mask->id, 0);

			free_slide_point_data(op->customdata); /* keep this last! */
			return OPERATOR_CANCELLED;
	}

	return OPERATOR_RUNNING_MODAL;
}
Esempio n. 4
0
static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
	ScrArea *sa = CTX_wm_area(C);
	ARegion *ar = CTX_wm_region(C);

	Mask *mask = CTX_data_edit_mask(C);
	SlidePointData *customdata = NULL;
	MaskLayer *masklay, *cv_masklay, *feather_masklay;
	MaskSpline *spline, *cv_spline, *feather_spline;
	MaskSplinePoint *point, *cv_point, *feather_point;
	MaskSplinePointUW *uw = NULL;
	int width, height, action = SLIDE_ACTION_NONE;
	bool is_handle = false;
	const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
	float co[2], cv_score, feather_score;
	const float threshold = 19;

	ED_mask_mouse_pos(sa, ar, event->mval, co);
	ED_mask_get_size(sa, &width, &height);

	cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score);

	if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
		if (slide_feather || !cv_point || feather_score < cv_score) {
			action = SLIDE_ACTION_FEATHER;

			masklay = feather_masklay;
			spline = feather_spline;
			point = feather_point;
		}
	}

	if (cv_point && action == SLIDE_ACTION_NONE) {
		if (is_handle)
			action = SLIDE_ACTION_HANDLE;
		else
			action = SLIDE_ACTION_POINT;

		masklay = cv_masklay;
		spline = cv_spline;
		point = cv_point;
	}

	if (action != SLIDE_ACTION_NONE) {
		customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");

		customdata->mask = mask;
		customdata->masklay = masklay;
		customdata->spline = spline;
		customdata->point = point;
		customdata->width = width;
		customdata->height = height;
		customdata->action = action;
		customdata->uw = uw;

		if (uw) {
			float co_uw[2];
			float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);

			customdata->weight = uw->w;
			customdata->weight_scalar = weight_scalar;
			BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
			BKE_mask_point_normal(spline, point, uw->u, customdata->no);

			madd_v2_v2v2fl(customdata->feather, co_uw, customdata->no, uw->w * weight_scalar);
		}
		else {
			BezTriple *bezt = &point->bezt;

			customdata->weight = bezt->weight;
			customdata->weight_scalar = 1.0f;
			BKE_mask_point_normal(spline, point, 0.0f, customdata->no);

			madd_v2_v2v2fl(customdata->feather, bezt->vec[1], customdata->no, bezt->weight);
		}

		if (customdata->action == SLIDE_ACTION_FEATHER)
			customdata->initial_feather = slide_point_check_initial_feather(spline);

		copy_m3_m3(customdata->vec, point->bezt.vec);
		if (BKE_mask_point_has_handle(point))
			BKE_mask_point_handle(point, customdata->handle);
		ED_mask_mouse_pos(sa, ar, event->mval, customdata->co);
	}

	return customdata;
}
Esempio n. 5
0
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */
static float (*mask_spline_feather_differentiated_points_with_resolution__double(
        MaskSpline *spline, unsigned int *tot_feather_point,
        const unsigned int resol, const bool do_feather_isect))[2]
{
	MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);

	MaskSplinePoint *point_curr, *point_prev;
	float (*feather)[2], (*fp)[2];
	const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
	int a;

	if (spline->tot_point <= 1) {
		/* nothing to differentiate */
		*tot_feather_point = 0;
		return NULL;
	}

	/* len+1 because of 'forward_diff_bezier' function */
	*tot_feather_point = tot;
	feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets");

	a = spline->tot_point - 1;
	if (spline->flag & MASK_SPLINE_CYCLIC)
		a++;

	point_prev = points_array;
	point_curr = point_prev + 1;

	while (a--) {
		BezTriple local_prevbezt;
		BezTriple local_bezt;
		float point_prev_n[2], point_curr_n[2], tvec[2];
		float weight_prev, weight_curr;
		float len_base, len_feather, len_scalar;

		BezTriple *bezt_prev;
		BezTriple *bezt_curr;
		int j;

		if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
			point_curr = points_array;

		bezt_prev = &point_prev->bezt;
		bezt_curr = &point_curr->bezt;

		/* modified copy for feather */
		local_prevbezt = *bezt_prev;
		local_bezt     = *bezt_curr;

		bezt_prev = &local_prevbezt;
		bezt_curr = &local_bezt;

		/* calc the normals */
		sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]);
		normalize_v2(tvec);
		point_prev_n[0] = -tvec[1];
		point_prev_n[1] =  tvec[0];

		sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]);
		normalize_v2(tvec);
		point_curr_n[0] = -tvec[1];
		point_curr_n[1] =  tvec[0];

		weight_prev = bezt_prev->weight;
		weight_curr = bezt_curr->weight;

		mul_v2_fl(point_prev_n, weight_prev);
		mul_v2_fl(point_curr_n, weight_curr);

		/* before we transform verts */
		len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);

		// add_v2_v2(bezt_prev->vec[0], point_prev_n);  // not needed
		add_v2_v2(bezt_prev->vec[1], point_prev_n);
		add_v2_v2(bezt_prev->vec[2], point_prev_n);

		add_v2_v2(bezt_curr->vec[0], point_curr_n);
		add_v2_v2(bezt_curr->vec[1], point_curr_n);
		// add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed

		len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);

		/* scale by chane in length */
		len_scalar = len_feather / len_base;
		dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1]));
		dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1]));


		for (j = 0; j < 2; j++) {
			BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
			                              bezt_curr->vec[0][j], bezt_curr->vec[1][j],
			                              &(*fp)[j], resol, 2 * sizeof(float));
		}


		/* scale by the uw's */
		if (point_prev->tot_uw) {
			for (j = 0; j < resol; j++, fp++) {
				float u = (float) j / resol;
				float weight_uw, weight_scalar;
				float co[2];

				/* TODO - these calls all calculate similar things
				 * could be unified for some speed */
				BKE_mask_point_segment_co(spline, point_prev, u, co);

				weight_uw     = BKE_mask_point_weight(spline, point_prev, u);
				weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u);

				dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar));
			}
		}
		else {
			fp += resol;
		}

		if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
			copy_v2_v2(*fp, bezt_curr->vec[1]);
		}

		point_prev = point_curr;
		point_curr++;
	}

	if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
		BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
	}

	return feather;
}
Esempio n. 6
0
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */
static float (*mask_spline_feather_differentiated_points_with_resolution__even(
        MaskSpline *spline, unsigned int *tot_feather_point,
        const unsigned int resol, const bool do_feather_isect))[2]
{
	MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
	MaskSplinePoint *point_curr, *point_prev;
	float (*feather)[2], (*fp)[2];

	const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
	int a;

	/* tot+1 because of 'forward_diff_bezier' function */
	feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points");

	a = spline->tot_point - 1;
	if (spline->flag & MASK_SPLINE_CYCLIC)
		a++;

	point_prev = points_array;
	point_curr = point_prev + 1;

	while (a--) {
		/* BezTriple *bezt_prev; */  /* UNUSED */
		/* BezTriple *bezt_curr; */      /* UNUSED */
		int j;

		if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
			point_curr = points_array;


		/* bezt_prev = &point_prev->bezt; */
		/* bezt_curr = &point_curr->bezt; */

		for (j = 0; j < resol; j++, fp++) {
			float u = (float) j / resol, weight;
			float co[2], n[2];

			/* TODO - these calls all calculate similar things
			 * could be unified for some speed */
			BKE_mask_point_segment_co(spline, point_prev, u, co);
			BKE_mask_point_normal(spline, point_prev, u, n);
			weight = BKE_mask_point_weight(spline, point_prev, u);

			madd_v2_v2v2fl(*fp, co, n, weight);
		}

		if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
			float u = 1.0f, weight;
			float co[2], n[2];

			BKE_mask_point_segment_co(spline, point_prev, u, co);
			BKE_mask_point_normal(spline, point_prev, u, n);
			weight = BKE_mask_point_weight(spline, point_prev, u);

			madd_v2_v2v2fl(*fp, co, n, weight);
		}

		point_prev = point_curr;
		point_curr++;
	}

	*tot_feather_point = tot;

	if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
		BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
	}

	return feather;
}