static int set_handle_type_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; int handle_type = RNA_enum_get(op->ptr, "type"); for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; 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)) { BezTriple *bezt = &point->bezt; bezt->h1 = bezt->h2 = handle_type; } } } } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; }
static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; 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)) { point->parent.id = NULL; } } } } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; }
static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, MaskSplinePoint **point, bool check_active) { MaskSpline *cur_spline = masklay->splines.first; *spline = NULL; *point = NULL; if (check_active) { /* TODO, having an active point but no active spline is possible, why? */ if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) { *spline = masklay->act_spline; *point = masklay->act_point; return; } } while (cur_spline) { int i; for (i = 0; i < cur_spline->tot_point; i++) { MaskSplinePoint *cur_point = &cur_spline->points[i]; if (MASKPOINT_ISSEL_ANY(cur_point)) { if (*spline != NULL && *spline != cur_spline) { *spline = NULL; *point = NULL; return; } else if (*point) { *point = NULL; } else { *spline = cur_spline; *point = cur_point; } } } cur_spline = cur_spline->next; } }
/* 'check' select */ bool ED_mask_spline_select_check(MaskSpline *spline) { int i; for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(point)) return true; } return false; }
/* *** 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 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 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); } } }
void ED_mask_select_flush_all(Mask *mask) { MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; for (spline = masklay->splines.first; spline; spline = spline->next) { int i; spline->flag &= ~SELECT; /* intentionally _dont_ do this in the masklay loop * so we clear flags on all splines */ if (masklay->restrictflag & MASK_RESTRICT_VIEW) { continue; } for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *cur_point = &spline->points[i]; if (MASKPOINT_ISSEL_ANY(cur_point)) { spline->flag |= SELECT; } else { int j; for (j = 0; j < cur_point->tot_uw; j++) { if (cur_point->uw[j].flag & SELECT) { spline->flag |= SELECT; break; } } } } } } }
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; }
static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } if (masklay->splines_shapes.first) { MaskLayerShape *masklay_shape_reset; MaskLayerShape *masklay_shape; /* get the shapekey of the current state */ masklay_shape_reset = BKE_mask_layer_shape_alloc(masklay, frame); /* initialize from mask - as if inseting a keyframe */ BKE_mask_layer_shape_from_mask(masklay, masklay_shape_reset); for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { if (masklay_shape_reset->tot_vert == masklay_shape->tot_vert) { int i_abs = 0; int i; MaskSpline *spline; MaskLayerShapeElem *shape_ele_src; MaskLayerShapeElem *shape_ele_dst; shape_ele_src = (MaskLayerShapeElem *)masklay_shape_reset->data; shape_ele_dst = (MaskLayerShapeElem *)masklay_shape->data; 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)) { /* TODO - nicer access here */ shape_ele_dst->value[6] = shape_ele_src->value[6]; } shape_ele_src++; shape_ele_dst++; i_abs++; } } } else { // printf("%s: skipping\n", __func__); } changed = true; } BKE_mask_layer_shape_free(masklay_shape_reset); } } if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } else { return OPERATOR_CANCELLED; } }
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 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; }
/* * - loop over selected shapekeys. * - find firstsel/lastsel pairs. * - move these into a temp list. * - re-key all the original shapes. * - copy unselected values back from the original. * - free the original. */ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); const int frame = CFRA; Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; const bool do_feather = RNA_boolean_get(op->ptr, "feather"); const bool do_location = RNA_boolean_get(op->ptr, "location"); for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } /* we need at least one point selected here to bother re-interpolating */ if (!ED_mask_layer_select_check(masklay)) { continue; } if (masklay->splines_shapes.first) { MaskLayerShape *masklay_shape, *masklay_shape_next; MaskLayerShape *masklay_shape_lastsel = NULL; for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) { MaskLayerShape *masklay_shape_a = NULL; MaskLayerShape *masklay_shape_b = NULL; masklay_shape_next = masklay_shape->next; /* find contiguous selections */ if (masklay_shape->flag & MASK_SHAPE_SELECT) { if (masklay_shape_lastsel == NULL) { masklay_shape_lastsel = masklay_shape; } if ((masklay_shape->next == NULL) || (((MaskLayerShape *)masklay_shape->next)->flag & MASK_SHAPE_SELECT) == 0) { masklay_shape_a = masklay_shape_lastsel; masklay_shape_b = masklay_shape; masklay_shape_lastsel = NULL; /* this will be freed below, step over selection */ masklay_shape_next = masklay_shape->next; } } /* we have a from<>to? - re-interpolate! */ if (masklay_shape_a && masklay_shape_b) { ListBase shapes_tmp = {NULL, NULL}; MaskLayerShape *masklay_shape_tmp; MaskLayerShape *masklay_shape_tmp_next; MaskLayerShape *masklay_shape_tmp_last = masklay_shape_b->next; MaskLayerShape *masklay_shape_tmp_rekey; /* move keys */ for (masklay_shape_tmp = masklay_shape_a; masklay_shape_tmp && (masklay_shape_tmp != masklay_shape_tmp_last); masklay_shape_tmp = masklay_shape_tmp_next) { masklay_shape_tmp_next = masklay_shape_tmp->next; BLI_remlink(&masklay->splines_shapes, masklay_shape_tmp); BLI_addtail(&shapes_tmp, masklay_shape_tmp); } /* re-key, note: cant modify the keys here since it messes uop */ for (masklay_shape_tmp = shapes_tmp.first; masklay_shape_tmp; masklay_shape_tmp = masklay_shape_tmp->next) { BKE_mask_layer_evaluate(masklay, masklay_shape_tmp->frame, true); masklay_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(masklay, masklay_shape_tmp->frame); BKE_mask_layer_shape_from_mask(masklay, masklay_shape_tmp_rekey); masklay_shape_tmp_rekey->flag = masklay_shape_tmp->flag & MASK_SHAPE_SELECT; } /* restore unselected points and free copies */ for (masklay_shape_tmp = shapes_tmp.first; masklay_shape_tmp; masklay_shape_tmp = masklay_shape_tmp_next) { /* restore */ int i_abs = 0; int i; MaskSpline *spline; MaskLayerShapeElem *shape_ele_src; MaskLayerShapeElem *shape_ele_dst; masklay_shape_tmp_next = masklay_shape_tmp->next; /* we know this exists, added above */ masklay_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(masklay, masklay_shape_tmp->frame); shape_ele_src = (MaskLayerShapeElem *)masklay_shape_tmp->data; shape_ele_dst = (MaskLayerShapeElem *)masklay_shape_tmp_rekey->data; for (spline = masklay->splines.first; spline; spline = spline->next) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; /* not especially efficient but makes this easier to follow */ SWAP(MaskLayerShapeElem, *shape_ele_src, *shape_ele_dst); if (MASKPOINT_ISSEL_ANY(point)) { if (do_location) { memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float) * 6); } if (do_feather) { shape_ele_dst->value[6] = shape_ele_src->value[6]; } } shape_ele_src++; shape_ele_dst++; i_abs++; } } BKE_mask_layer_shape_free(masklay_shape_tmp); } changed = true; } } /* re-evaluate */ BKE_mask_layer_evaluate(masklay, frame, true); } } if (changed) { WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; } else { 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; }
/* return non-zero if spline is selected */ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline, const char draw_flag, const char draw_type, const float xscale, const float yscale) { const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); SpaceClip *sc = CTX_wm_space_clip(C); bool undistort = false; int i, handle_size, tot_feather_point; float (*feather_points)[2], (*fp)[2]; float min[2], max[2]; if (!spline->tot_point) return; if (sc) undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); /* TODO, add this to sequence editor */ handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; glPointSize(handle_size); mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; int j; for (j = 0; j <= point->tot_uw; j++) { float feather_point[2]; bool sel = false; copy_v2_v2(feather_point, *fp); if (undistort) mask_point_undistort_pos(sc, feather_point, feather_point); if (j == 0) { sel = MASKPOINT_ISSEL_ANY(point); } else { sel = (point->uw[j - 1].flag & SELECT) != 0; } if (sel) { if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); } else { UI_ThemeColor(TH_HANDLE_VERTEX); } glBegin(GL_POINTS); glVertex2fv(feather_point); glEnd(); fp++; } } MEM_freeN(feather_points); if (is_smooth) { glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } /* control points */ INIT_MINMAX2(min, max); for (i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; MaskSplinePoint *point_deform = &points_array[i]; BezTriple *bezt = &point_deform->bezt; float vert[2]; copy_v2_v2(vert, bezt->vec[1]); if (undistort) { mask_point_undistort_pos(sc, vert, vert); } /* draw handle segment */ if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { float handle[2]; BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle); if (undistort) { mask_point_undistort_pos(sc, handle, handle); } draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK, draw_type, handle_size, xscale, yscale, vert, handle); } else { float handle_left[2], handle_right[2]; BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left); BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right); if (undistort) { mask_point_undistort_pos(sc, handle_left, handle_left); mask_point_undistort_pos(sc, handle_left, handle_left); } draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT, draw_type, handle_size, xscale, yscale, vert, handle_left); draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT, draw_type, handle_size, xscale, yscale, vert, handle_right); } /* draw CV point */ if (MASKPOINT_ISSEL_KNOT(point)) { if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else UI_ThemeColor(TH_HANDLE_VERTEX_SELECT); } else UI_ThemeColor(TH_HANDLE_VERTEX); glBegin(GL_POINTS); glVertex2fv(vert); glEnd(); minmax_v2v2_v2(min, max, vert); } if (is_spline_sel) { float x = (min[0] + max[0]) / 2.0f; float y = (min[1] + max[1]) / 2.0f; /* TODO(sergey): Remove hardcoded colors. */ if (masklay->act_spline == spline) { glColor3ub(255, 255, 255); } else { glColor3ub(255, 255, 0); } draw_circle(x, y, 6.0f, true, xscale, yscale); glColor3ub(0, 0, 0); draw_circle(x, y, 6.0f, false, xscale, yscale); } if (is_smooth) { glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); } }
static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; /* parent info */ SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking; MovieTrackingTrack *track; MovieTrackingPlaneTrack *plane_track; MovieTrackingObject *tracking_object; /* done */ int framenr, parent_type; float parmask_pos[2], orig_corners[4][2]; char *sub_parent_name; if (ELEM(NULL, sc, clip)) { return OPERATOR_CANCELLED; } framenr = ED_space_clip_get_clip_frame_number(sc); tracking = &clip->tracking; tracking_object = BKE_tracking_object_get_active(&clip->tracking); if (tracking_object == NULL) { return OPERATOR_CANCELLED; } if ((track = BKE_tracking_track_get_active(tracking)) != NULL) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); float marker_pos_ofs[2]; add_v2_v2v2(marker_pos_ofs, marker->pos, track->offset); BKE_mask_coord_from_movieclip(clip, &sc->user, parmask_pos, marker_pos_ofs); sub_parent_name = track->name; parent_type = MASK_PARENT_POINT_TRACK; memset(orig_corners, 0, sizeof(orig_corners)); } else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); zero_v2(parmask_pos); sub_parent_name = plane_track->name; parent_type = MASK_PARENT_PLANE_TRACK; memcpy(orig_corners, plane_marker->corners, sizeof(orig_corners)); } else { return OPERATOR_CANCELLED; } for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; int i; 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)) { point->parent.id_type = ID_MC; point->parent.id = &clip->id; point->parent.type = parent_type; BLI_strncpy(point->parent.parent, tracking_object->name, sizeof(point->parent.parent)); BLI_strncpy(point->parent.sub_parent, sub_parent_name, sizeof(point->parent.sub_parent)); copy_v2_v2(point->parent.parent_orig, parmask_pos); memcpy(point->parent.parent_corners_orig, orig_corners, sizeof(point->parent.parent_corners_orig)); } } } } WM_event_add_notifier(C, NC_MASK | ND_DATA, mask); DAG_id_tag_update(&mask->id, 0); return OPERATOR_FINISHED; }
/* return non-zero if spline is selected */ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline, const char UNUSED(draw_flag), const char draw_type) { const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); SpaceClip *sc = CTX_wm_space_clip(C); int undistort = FALSE; int i, hsize, tot_feather_point; float (*feather_points)[2], (*fp)[2]; if (!spline->tot_point) return; if (sc) undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; /* TODO, add this to sequence editor */ hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */ glPointSize(hsize); mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); /* feather points */ feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); for (i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; int j; for (j = 0; j <= point->tot_uw; j++) { float feather_point[2]; int sel = FALSE; copy_v2_v2(feather_point, *fp); if (undistort) mask_point_undistort_pos(sc, feather_point, feather_point); if (j == 0) { sel = MASKPOINT_ISSEL_ANY(point); } else { sel = point->uw[j - 1].flag & SELECT; } if (sel) { if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); } else { glColor3f(0.5f, 0.5f, 0.0f); } glBegin(GL_POINTS); glVertex2fv(feather_point); glEnd(); fp++; } } MEM_freeN(feather_points); /* control points */ for (i = 0; i < spline->tot_point; i++) { /* watch it! this is intentionally not the deform array, only check for sel */ MaskSplinePoint *point = &spline->points[i]; MaskSplinePoint *point_deform = &points_array[i]; BezTriple *bezt = &point_deform->bezt; float handle[2]; float vert[2]; const bool has_handle = BKE_mask_point_has_handle(point); copy_v2_v2(vert, bezt->vec[1]); BKE_mask_point_handle(point_deform, handle); if (undistort) { mask_point_undistort_pos(sc, vert, vert); mask_point_undistort_pos(sc, handle, handle); } /* draw handle segment */ if (has_handle) { /* this could be split into its own loop */ if (draw_type == MASK_DT_OUTLINE) { const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; glLineWidth(3); glColor4ubv(rgb_gray); glBegin(GL_LINES); glVertex2fv(vert); glVertex2fv(handle); glEnd(); glLineWidth(1); } glColor3ubv(rgb_spline); glBegin(GL_LINES); glVertex2fv(vert); glVertex2fv(handle); glEnd(); } /* draw CV point */ if (MASKPOINT_ISSEL_KNOT(point)) { if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); } else glColor3f(0.5f, 0.5f, 0.0f); glBegin(GL_POINTS); glVertex2fv(vert); glEnd(); /* draw handle points */ if (has_handle) { if (MASKPOINT_ISSEL_HANDLE(point)) { if (point == masklay->act_point) glColor3f(1.0f, 1.0f, 1.0f); else glColor3f(1.0f, 1.0f, 0.0f); } else { glColor3f(0.5f, 0.5f, 0.0f); } glBegin(GL_POINTS); glVertex2fv(handle); glEnd(); } } glPointSize(1.0f); }