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; }
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; }
/* '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); } }
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; }
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); } } }
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; }
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; }
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; }
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; }
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; }