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; }
void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type) { ScrArea *sa = CTX_wm_area(C); Mask *mask = CTX_data_edit_mask(C); int width, height; if (!mask) return; ED_mask_get_size(sa, &width, &height); draw_masklays(C, mask, draw_flag, draw_type, width, height); }
static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { ScrArea *sa = CTX_wm_area(C); float cursor[2]; int width, height; ED_mask_get_size(sa, &width, &height); ED_mask_cursor_location_get(sa, cursor); cursor[0] *= width; cursor[1] *= height; RNA_float_set_array(op->ptr, "location", cursor); return op->type->exec(C, op); }
void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Mask *mask = CTX_data_edit_mask(C); int width, height; float aspx, aspy; float xscale, yscale; if (!mask) return; ED_mask_get_size(sa, &width, &height); ED_mask_get_aspect(sa, ar, &aspx, &aspy); UI_view2d_scale_get(&ar->v2d, &xscale, &yscale); draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy); }
MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const float normal_co[2], const float threshold, MaskLayer **masklay_r, MaskSpline **spline_r, bool *is_handle_r, float *score) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); MaskLayer *masklay; MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; float co[2]; const float threshold_sq = threshold * threshold; float len_sq = FLT_MAX, scalex, scaley; int is_handle = FALSE, width, height; ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; 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); int i; for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *cur_point = &spline->points[i]; MaskSplinePoint *cur_point_deform = &points_array[i]; float cur_len_sq, vec[2], handle[2]; vec[0] = cur_point_deform->bezt.vec[1][0] * scalex; vec[1] = cur_point_deform->bezt.vec[1][1] * scaley; if (BKE_mask_point_has_handle(cur_point)) { BKE_mask_point_handle(cur_point_deform, handle); handle[0] *= scalex; handle[1] *= scaley; cur_len_sq = len_squared_v2v2(co, handle); if (cur_len_sq < len_sq) { point_masklay = masklay; point_spline = spline; point = cur_point; len_sq = cur_len_sq; is_handle = TRUE; } } cur_len_sq = len_squared_v2v2(co, vec); if (cur_len_sq < len_sq) { point_spline = spline; point_masklay = masklay; point = cur_point; len_sq = cur_len_sq; is_handle = FALSE; } } } } if (len_sq < threshold_sq) { if (masklay_r) *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; if (is_handle_r) *is_handle_r = is_handle; if (score) *score = sqrtf(len_sq); return point; } if (masklay_r) *masklay_r = NULL; if (spline_r) *spline_r = NULL; if (is_handle_r) *is_handle_r = FALSE; return NULL; }
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; }
bool ED_mask_feather_find_nearest(const bContext *C, Mask *mask, const float normal_co[2], const float threshold, MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, MaskSplinePointUW **uw_r, float *score) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); MaskLayer *masklay, *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; MaskSplinePointUW *uw = NULL; const float threshold_sq = threshold * threshold; float len = FLT_MAX, co[2]; float scalex, scaley; int width, height; ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; for (spline = masklay->splines.first; spline; spline = spline->next) { //MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot_feather_point; float (*feather_points)[2], (*fp)[2]; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { int j; MaskSplinePoint *cur_point = &spline->points[i]; for (j = 0; j <= cur_point->tot_uw; j++) { float cur_len_sq, vec[2]; vec[0] = (*fp)[0] * scalex; vec[1] = (*fp)[1] * scaley; cur_len_sq = len_squared_v2v2(vec, co); if (point == NULL || cur_len_sq < len) { if (j == 0) uw = NULL; else uw = &cur_point->uw[j - 1]; point_masklay = masklay; point_spline = spline; point = cur_point; len = cur_len_sq; } fp++; } } MEM_freeN(feather_points); } } if (len < threshold_sq) { if (masklay_r) *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; if (point_r) *point_r = point; if (uw_r) *uw_r = uw; if (score) *score = sqrtf(len); return TRUE; } if (masklay_r) *masklay_r = NULL; if (spline_r) *spline_r = NULL; if (point_r) *point_r = NULL; return FALSE; }
bool ED_mask_find_nearest_diff_point(const bContext *C, struct Mask *mask, const float normal_co[2], int threshold, bool feather, MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r, float *u_r, float tangent[2], const bool use_deform, const bool use_project) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist = FLT_MAX, co[2]; int width, height; float u; float scalex, scaley; ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; 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) { int i; MaskSplinePoint *cur_point; for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points; i < spline->tot_point; i++, cur_point++) { float *diff_points; unsigned int tot_diff_point; diff_points = BKE_mask_point_segment_diff(spline, cur_point, width, height, &tot_diff_point); if (diff_points) { int j, tot_point; unsigned int tot_feather_point; float *feather_points = NULL, *points; if (feather) { feather_points = BKE_mask_point_segment_feather_diff(spline, cur_point, width, height, &tot_feather_point); points = feather_points; tot_point = tot_feather_point; } else { points = diff_points; tot_point = tot_diff_point; } for (j = 0; j < tot_point - 1; j++) { float cur_dist, a[2], b[2]; a[0] = points[2 * j] * scalex; a[1] = points[2 * j + 1] * scaley; b[0] = points[2 * j + 2] * scalex; b[1] = points[2 * j + 3] * scaley; cur_dist = dist_to_line_segment_v2(co, a, b); if (cur_dist < dist) { if (tangent) sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); point_masklay = masklay; point_spline = spline; point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point; dist = cur_dist; u = (float)j / tot_point; } } if (feather_points) MEM_freeN(feather_points); MEM_freeN(diff_points); } } } } if (point && dist < threshold) { if (masklay_r) *masklay_r = point_masklay; if (spline_r) *spline_r = point_spline; if (point_r) *point_r = point; if (u_r) { /* TODO(sergey): Projection fails in some weirdo cases.. */ if (use_project) { u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); } *u_r = u; } return true; } if (masklay_r) *masklay_r = NULL; if (spline_r) *spline_r = NULL; if (point_r) *point_r = NULL; return false; }
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; }