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; }
/* *** 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; }
static int paste_splines_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); BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer); /* TODO: only update edited splines */ BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; }
/* *** switch direction *** */ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; 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) { if (ED_mask_spline_select_check(spline)) { BKE_mask_spline_direction_switch(masklay, spline); 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; }
static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; int i; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) { 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)) { BezTriple *bezt = &point->bezt; bezt->weight = 0.0f; changed = true; } } } } if (changed) { /* TODO: only update edited splines */ BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } else { return OPERATOR_CANCELLED; } }
static int add_feather_vertex_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; MaskSpline *spline; MaskSplinePoint *point = NULL; const float threshold = 9; float co[2], u; RNA_float_get_array(op->ptr, "location", co); point = ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL); if (point) return OPERATOR_FINISHED; if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) { Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); if (weight_scalar != 0.0f) { w = w / weight_scalar; } BKE_mask_point_add_uw(point, u, w); BKE_mask_update_display(mask, scene->r.cfra); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; }
static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int mask_layer_shape_ofs = 0; if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } spline = masklay->splines.first; while (spline) { const int tot_point_orig = spline->tot_point; int i, count = 0; MaskSpline *next_spline = spline->next; /* count unselected points */ for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; if (!MASKPOINT_ISSEL_ANY(point)) count++; } if (count == 0) { /* delete the whole spline */ BLI_remlink(&masklay->splines, spline); BKE_mask_spline_free(spline); if (spline == masklay->act_spline) { masklay->act_spline = NULL; masklay->act_point = NULL; } BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig); } else { MaskSplinePoint *new_points; int j; new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints"); for (i = 0, j = 0; i < tot_point_orig; i++) { MaskSplinePoint *point = &spline->points[i]; if (!MASKPOINT_ISSEL_ANY(point)) { if (point == masklay->act_point) masklay->act_point = &new_points[j]; delete_feather_points(point); new_points[j] = *point; j++; } else { if (point == masklay->act_point) masklay->act_point = NULL; BKE_mask_point_free(point); spline->tot_point--; BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1); } } mask_layer_shape_ofs += spline->tot_point; MEM_freeN(spline->points); spline->points = new_points; ED_mask_select_flush_all(mask); } changed = true; spline = next_spline; } /* not essential but confuses users when there are keys with no data! * assume if they delete all data from the layer they also dont care about keys */ if (masklay->splines.first == NULL) { BKE_mask_layer_free_shapes(masklay); } } if (!changed) { return OPERATOR_CANCELLED; } /* 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_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 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; }