Пример #1
0
static void rna_MaskSpline_points_add(ID *id, MaskSpline *spline, int count)
{
	Mask *mask = (Mask *) id;
	MaskLayer *layer;
	int active_point_index = -1;
	int i, spline_shape_index;

	if (count <= 0) {
		return;
	}

	for (layer = mask->masklayers.first; layer; layer = layer->next) {
		if (BLI_findindex(&layer->splines, spline) != -1) {
			break;
		}
	}

	if (!layer) {
		/* Shall not happen actually */
		BLI_assert(!"No layer found for the spline");
		return;
	}

	if (layer->act_spline == spline) {
		active_point_index = layer->act_point - spline->points;
	}

	spline->points = MEM_recallocN(spline->points, sizeof(MaskSplinePoint) * (spline->tot_point + count));
	spline->tot_point += count;

	if (active_point_index >= 0) {
		layer->act_point = spline->points + active_point_index;
	}

	spline_shape_index = BKE_mask_layer_shape_spline_to_index(layer, spline);

	for (i = 0; i < count; i++) {
		int point_index = spline->tot_point - count + i;
		MaskSplinePoint *new_point = spline->points + point_index;
		new_point->bezt.h1 = new_point->bezt.h2 = HD_ALIGN;
		BKE_mask_calc_handle_point_auto(spline, new_point, TRUE);
		BKE_mask_parent_init(&new_point->parent);

		/* Not efficient, but there's no other way for now */
		BKE_mask_layer_shape_changed_add(layer, spline_shape_index + point_index, true, true);
	}

	WM_main_add_notifier(NC_MASK | ND_DATA, mask);
	DAG_id_tag_update(&mask->id, 0);
}
Пример #2
0
/* *** recalc normals *** */
static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op))
{
	Scene *scene = CTX_data_scene(C);
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;
	int i;

	bool changed = false;

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

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

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

				if (MASKPOINT_ISSEL_ANY(point)) {
					BKE_mask_calc_handle_point_auto(spline, point, FALSE);
					changed = true;
					changed_layer = true;
				}
			}
		}

		if (changed_layer) {
			if (IS_AUTOKEY_ON(scene)) {
				ED_mask_layer_shape_auto_key(masklay, CFRA);
			}
		}
	}

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

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

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
Пример #3
0
static int add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
{
	MaskSpline *spline;
	MaskSplinePoint *point;
	MaskSplinePoint *new_point = NULL, *ref_point = NULL;

	/* check on which side we want to add the point */
	int point_index;
	float tangent_point[2];
	float tangent_co[2];
	int do_cyclic_correct = FALSE;
	int do_recalc_src = FALSE;  /* when extruding from endpoints only */
	int do_prev;                /* use prev point rather then next?? */

	if (!masklay) {
		return FALSE;
	}
	else {
		finSelectedSplinePoint(masklay, &spline, &point, TRUE);
	}

	ED_mask_select_toggle_all(mask, SEL_DESELECT);

	point_index = (point - spline->points);

	MASKPOINT_DESEL_ALL(point);

	if ((spline->flag & MASK_SPLINE_CYCLIC) ||
	    (point_index > 0 && point_index != spline->tot_point - 1))
	{
		BKE_mask_calc_tangent_polyline(spline, point, tangent_point);
		sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]);

		if (dot_v2v2(tangent_point, tangent_co) < 0.0f) {
			do_prev = TRUE;
		}
		else {
			do_prev = FALSE;
		}
	}
	else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == 0)) {
		do_prev = TRUE;
		do_recalc_src = TRUE;
	}
	else if (((spline->flag & MASK_SPLINE_CYCLIC) == 0) && (point_index == spline->tot_point - 1)) {
		do_prev = FALSE;
		do_recalc_src = TRUE;
	}
	else {
		do_prev = FALSE;  /* quiet warning */
		/* should never get here */
		BLI_assert(0);
	}

	/* use the point before the active one */
	if (do_prev) {
		point_index--;
		if (point_index < 0) {
			point_index += spline->tot_point; /* wrap index */
			if ((spline->flag & MASK_SPLINE_CYCLIC) == 0) {
				do_cyclic_correct = TRUE;
				point_index = 0;
			}
		}
	}

//		print_v2("", tangent_point);
//		printf("%d\n", point_index);

	mask_spline_add_point_at_index(spline, point_index);

	if (do_cyclic_correct) {
		ref_point = &spline->points[point_index + 1];
		new_point = &spline->points[point_index];
		*ref_point = *new_point;
		memset(new_point, 0, sizeof(*new_point));
	}
	else {
		ref_point = &spline->points[point_index];
		new_point = &spline->points[point_index + 1];
	}

	masklay->act_point = new_point;

	setup_vertex_point(mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE, 1.0f);

	if (masklay->splines_shapes.first) {
		point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
		BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index, TRUE, TRUE);
	}

	if (do_recalc_src) {
		/* TODO, update keyframes in time */
		BKE_mask_calc_handle_point_auto(spline, ref_point, FALSE);
	}

	WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);

	return TRUE;
}
Пример #4
0
static int add_vertex_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	Mask *mask = CTX_data_edit_mask(C);
	MaskLayer *masklay;

	float co[2];

	if (mask == NULL) {
		/* if there's no active mask, create one */
		mask = ED_mask_new(C, NULL);
	}

	masklay = BKE_mask_layer_active(mask);

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

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

	/* TODO, having an active point but no active spline is possible, why? */
	if (masklay && masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {

		/* cheap trick - double click for cyclic */
		MaskSpline *spline = masklay->act_spline;
		MaskSplinePoint *point = masklay->act_point;

		const bool is_sta = (point == spline->points);
		const bool is_end = (point == &spline->points[spline->tot_point - 1]);

		/* then check are we overlapping the mouse */
		if ((is_sta || is_end) && equals_v2v2(co, point->bezt.vec[1])) {
			if (spline->flag & MASK_SPLINE_CYCLIC) {
				/* nothing to do */
				return OPERATOR_CANCELLED;
			}
			else {
				/* recalc the connecting point as well to make a nice even curve */
				MaskSplinePoint *point_other = is_end ? spline->points : &spline->points[spline->tot_point - 1];
				spline->flag |= MASK_SPLINE_CYCLIC;

				/* TODO, update keyframes in time */
				BKE_mask_calc_handle_point_auto(spline, point, false);
				BKE_mask_calc_handle_point_auto(spline, point_other, false);

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

				WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
				return OPERATOR_FINISHED;
			}
		}

		if (!add_vertex_subdivide(C, mask, co)) {
			if (!add_vertex_extrude(C, mask, masklay, co)) {
				return OPERATOR_CANCELLED;
			}
		}
	}
	else {
		if (!add_vertex_subdivide(C, mask, co)) {
			if (!add_vertex_new(C, mask, masklay, co)) {
				return OPERATOR_CANCELLED;
			}
		}
	}

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

	return OPERATOR_FINISHED;
}
Пример #5
0
static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
                               const float point_co[2], const float tangent[2], const float u,
                               MaskSplinePoint *reference_point, const short reference_adjacent,
                               const float view_zoom)
{
	MaskSplinePoint *prev_point = NULL;
	MaskSplinePoint *next_point = NULL;
	BezTriple *bezt;
	float co[3];
	const float len = 10.0; /* default length of handle in pixel space */

	copy_v2_v2(co, point_co);
	co[2] = 0.0f;

	/* point coordinate */
	bezt = &new_point->bezt;

	bezt->h1 = bezt->h2 = HD_ALIGN;

	if (reference_point) {
		bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
	}
	else if (reference_adjacent) {
		if (spline->tot_point != 1) {
			int index = (int)(new_point - spline->points);
			prev_point = &spline->points[(index - 1) % spline->tot_point];
			next_point = &spline->points[(index + 1) % spline->tot_point];

			bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1);

			/* note, we may want to copy other attributes later, radius? pressure? color? */
		}
	}

	copy_v3_v3(bezt->vec[0], co);
	copy_v3_v3(bezt->vec[1], co);
	copy_v3_v3(bezt->vec[2], co);

	/* initial offset for handles */
	if (spline->tot_point == 1) {
		/* first point of splien is aligned horizontally */
		bezt->vec[0][0] -= len * view_zoom;
		bezt->vec[2][0] += len * view_zoom;
	}
	else if (tangent) {
		float vec[2];

		copy_v2_v2(vec, tangent);

		mul_v2_fl(vec, len);

		sub_v2_v2(bezt->vec[0], vec);
		add_v2_v2(bezt->vec[2], vec);

		if (reference_adjacent) {
			BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
		}
	}
	else {

		/* calculating auto handles works much nicer */
#if 0
		/* next points are aligning in the direction of previous/next point */
		MaskSplinePoint *point;
		float v1[2], v2[2], vec[2];
		float dir = 1.0f;

		if (new_point == spline->points) {
			point = new_point + 1;
			dir = -1.0f;
		}
		else
			point = new_point - 1;

		if (spline->tot_point < 3) {
			v1[0] = point->bezt.vec[1][0] * width;
			v1[1] = point->bezt.vec[1][1] * height;

			v2[0] = new_point->bezt.vec[1][0] * width;
			v2[1] = new_point->bezt.vec[1][1] * height;
		}
		else {
			if (new_point == spline->points) {
				v1[0] = spline->points[1].bezt.vec[1][0] * width;
				v1[1] = spline->points[1].bezt.vec[1][1] * height;

				v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width;
				v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height;
			}
			else {
				v1[0] = spline->points[0].bezt.vec[1][0] * width;
				v1[1] = spline->points[0].bezt.vec[1][1] * height;

				v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width;
				v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height;
			}
		}

		sub_v2_v2v2(vec, v1, v2);
		mul_v2_fl(vec, len * dir / len_v2(vec));

		vec[0] /= width;
		vec[1] /= height;

		add_v2_v2(bezt->vec[0], vec);
		sub_v2_v2(bezt->vec[2], vec);
#else
		BKE_mask_calc_handle_point_auto(spline, new_point, TRUE);
		BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);

#endif
	}

	BKE_mask_parent_init(&new_point->parent);

	/* select new point */
	MASKPOINT_SEL_ALL(new_point);
	ED_mask_select_flush_all(mask);
}