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); }
static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, const float point_co[2], const float u, MaskSplinePoint *reference_point, const bool reference_adjacent) { MaskSplinePoint *prev_point = NULL; MaskSplinePoint *next_point = NULL; BezTriple *bezt; float co[3]; 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) { if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) { /* If the reference point is sharp try using some smooth point as reference * for handles. */ int point_index = reference_point - spline->points; int delta = new_point == spline->points ? 1 : -1; int i = 0; for (i = 0; i < spline->tot_point - 1; ++i) { MaskSplinePoint *current_point; point_index += delta; if (point_index == -1 || point_index >= spline->tot_point) { if (spline->flag & MASK_SPLINE_CYCLIC) { if (point_index == -1) { point_index = spline->tot_point - 1; } else if (point_index >= spline->tot_point) { point_index = 0; } } else { break; } } current_point = &spline->points[point_index]; if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) { bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1); break; } } } else { 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); BKE_mask_parent_init(&new_point->parent); if (spline->tot_point != 1) { BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); } /* select new point */ MASKPOINT_SEL_ALL(new_point); ED_mask_select_flush_all(mask); }
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]; BKE_mask_parent_init(&new_point->parent); 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; }
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); }
static void setup_vertex_point( Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point, const float point_co[2], const float u, const float ctime, const MaskSplinePoint *reference_point, const bool reference_adjacent) { const MaskSplinePoint *reference_parent_point = NULL; BezTriple *bezt; float co[3]; 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) { if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) { /* If the reference point is sharp try using some smooth point as reference * for handles. */ int point_index = reference_point - spline->points; int delta = new_point == spline->points ? 1 : -1; int i = 0; for (i = 0; i < spline->tot_point - 1; ++i) { MaskSplinePoint *current_point; point_index += delta; if (point_index == -1 || point_index >= spline->tot_point) { if (spline->flag & MASK_SPLINE_CYCLIC) { if (point_index == -1) { point_index = spline->tot_point - 1; } else if (point_index >= spline->tot_point) { point_index = 0; } } else { break; } } current_point = &spline->points[point_index]; if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) { bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1); break; } } } else { bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1); } reference_parent_point = reference_point; } else if (reference_adjacent) { if (spline->tot_point != 1) { MaskSplinePoint *prev_point, *next_point, *close_point; const int index = (int)(new_point - spline->points); if (spline->flag & MASK_SPLINE_CYCLIC) { prev_point = &spline->points[mod_i(index - 1, spline->tot_point)]; next_point = &spline->points[mod_i(index + 1, spline->tot_point)]; } else { prev_point = (index != 0) ? &spline->points[index - 1] : NULL; next_point = (index != spline->tot_point - 1) ? &spline->points[index + 1] : NULL; } if (prev_point && next_point) { close_point = (len_squared_v2v2(new_point->bezt.vec[1], prev_point->bezt.vec[1]) < len_squared_v2v2(new_point->bezt.vec[1], next_point->bezt.vec[1])) ? prev_point : next_point; } else { close_point = prev_point ? prev_point : next_point; } /* handle type */ char handle_type = 0; if (prev_point) { handle_type = prev_point->bezt.h2; } if (next_point) { handle_type = MAX2(next_point->bezt.h2, handle_type); } bezt->h1 = bezt->h2 = handle_type; /* parent */ reference_parent_point = close_point; /* 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); if (reference_parent_point) { new_point->parent = reference_parent_point->parent; if (new_point->parent.id) { float parent_matrix[3][3]; BKE_mask_point_parent_matrix_get(new_point, ctime, parent_matrix); invert_m3(parent_matrix); mul_m3_v2(parent_matrix, new_point->bezt.vec[1]); } } else { BKE_mask_parent_init(&new_point->parent); } if (spline->tot_point != 1) { BKE_mask_calc_handle_adjacent_interp(spline, new_point, u); } /* select new point */ MASKPOINT_SEL_ALL(new_point); ED_mask_select_flush_all(mask); }