float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot = 0; float (*feather)[2], (*fp)[2]; /* count */ for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; tot += point->tot_uw + 1; } /* create data */ feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points"); for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &points_array[i]; BezTriple *bezt = &point->bezt; float weight, n[2]; int j; BKE_mask_point_normal(spline, point, 0.0f, n); weight = BKE_mask_point_weight(spline, point, 0.0f); madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight); fp++; for (j = 0; j < point->tot_uw; j++) { float u = point->uw[j].u; float co[2]; BKE_mask_point_segment_co(spline, point, u, co); BKE_mask_point_normal(spline, point, u, n); weight = BKE_mask_point_weight(spline, point, u); madd_v2_v2v2fl(*fp, co, n, weight); fp++; } } *tot_feather_point = tot; return feather; }
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist) { if (!equals_v2v2(v2, v1)) { float nor[2]; sub_v2_v2v2(nor, v1, v2); normalize_v2(nor); madd_v2_v2v2fl(v1, v2, nor, dist); } }
/* reduced copy of garbled calchandleNurb() code in curve.c */ static void calchandle_curvemap(BezTriple *bezt, BezTriple *prev, BezTriple *next, int UNUSED(mode)) { float *p1, *p2, *p3, pt[3]; float len, len_a, len_b; float dvec_a[2], dvec_b[2]; if (bezt->h1 == 0 && bezt->h2 == 0) { return; } p2 = bezt->vec[1]; if (prev == NULL) { p3 = next->vec[1]; pt[0] = 2.0f * p2[0] - p3[0]; pt[1] = 2.0f * p2[1] - p3[1]; p1 = pt; } else { p1 = prev->vec[1]; } if (next == NULL) { p1 = prev->vec[1]; pt[0] = 2.0f * p2[0] - p1[0]; pt[1] = 2.0f * p2[1] - p1[1]; p3 = pt; } else { p3 = next->vec[1]; } sub_v2_v2v2(dvec_a, p2, p1); sub_v2_v2v2(dvec_b, p3, p2); len_a = len_v2(dvec_a); len_b = len_v2(dvec_b); if (len_a == 0.0f) len_a = 1.0f; if (len_b == 0.0f) len_b = 1.0f; if (bezt->h1 == HD_AUTO || bezt->h2 == HD_AUTO) { /* auto */ float tvec[2]; tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a; tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a; len = len_v2(tvec) * 2.5614f; if (len != 0.0f) { if (bezt->h1 == HD_AUTO) { len_a /= len; madd_v2_v2v2fl(p2 - 3, p2, tvec, -len_a); } if (bezt->h2 == HD_AUTO) { len_b /= len; madd_v2_v2v2fl(p2 + 3, p2, tvec, len_b); } } } if (bezt->h1 == HD_VECT) { /* vector */ madd_v2_v2v2fl(p2 - 3, p2, dvec_a, -1.0f / 3.0f); } if (bezt->h2 == HD_VECT) { madd_v2_v2v2fl(p2 + 3, p2, dvec_b, 1.0f / 3.0f); } }
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; }
static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg) { Scene *scene = CTX_data_scene(C); UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; RegionView3D *rv3d = ruler_info->ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; const float bg_radius = 4.0f * U.pixelsize; const float arc_size = 64.0f * U.pixelsize; #define ARC_STEPS 24 const int arc_steps = ARC_STEPS; int i; //unsigned int color_act = 0x666600; unsigned int color_act = 0xffffff; unsigned int color_base = 0x0; unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80}; unsigned char color_text[3]; unsigned char color_wire[3]; /* anti-aliased lines for more consistent appearance */ glEnable(GL_LINE_SMOOTH); BLF_enable(blf_mono_font, BLF_ROTATION); BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); BLF_rotation(blf_mono_font, 0.0f); UI_GetThemeColor3ubv(TH_TEXT, color_text); UI_GetThemeColor3ubv(TH_WIRE, color_wire); for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) { const bool is_act = (i == ruler_info->item_active); float dir_ruler[2]; float co_ss[3][2]; int j; /* should these be checked? - ok for now not to */ for (j = 0; j < 3; j++) { ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); } glEnable(GL_BLEND); cpack(is_act ? color_act : color_base); if (ruler_item->flag & RULERITEM_USE_ANGLE) { glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j++) { glVertex2fv(co_ss[j]); } glEnd(); cpack(0xaaaaaa); setlinestyle(3); glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j++) { glVertex2fv(co_ss[j]); } glEnd(); setlinestyle(0); /* arc */ { float dir_tmp[3]; float co_tmp[3]; float arc_ss_coords[ARC_STEPS + 1][2]; float dir_a[3]; float dir_b[3]; float quat[4]; float axis[3]; float angle; const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) * min_fff(arc_size, len_v2v2(co_ss[0], co_ss[1]) / 2.0f, len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); normalize_v3(dir_a); normalize_v3(dir_b); cross_v3_v3v3(axis, dir_a, dir_b); angle = angle_normalized_v3v3(dir_a, dir_b); axis_angle_to_quat(quat, axis, angle / arc_steps); copy_v3_v3(dir_tmp, dir_a); glColor3ubv(color_wire); for (j = 0; j <= arc_steps; j++) { madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); mul_qt_v3(quat, dir_tmp); } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); glDisableClientState(GL_VERTEX_ARRAY); } /* text */ { char numstr[256]; float numstr_size[2]; float pos[2]; const int prec = 2; /* XXX, todo, make optional */ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); pos[0] = co_ss[1][0] + (cap_size * 2.0f); pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); /* draw text (bg) */ glColor4ubv(color_back); uiSetRoundBox(UI_CNR_ALL); uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], bg_radius); /* draw text */ glColor3ubv(color_text); BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); BLF_rotation(blf_mono_font, 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } /* capping */ { float rot_90_vec_a[2]; float rot_90_vec_b[2]; float cap[2]; sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); rot_90_vec_a[0] = -dir_ruler[1]; rot_90_vec_a[1] = dir_ruler[0]; normalize_v2(rot_90_vec_a); sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); rot_90_vec_b[0] = -dir_ruler[1]; rot_90_vec_b[1] = dir_ruler[0]; normalize_v2(rot_90_vec_b); glEnable(GL_BLEND); glColor3ubv(color_wire); glBegin(GL_LINES); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); glVertex2fv(cap); /* angle vertex */ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); glEnd(); glDisable(GL_BLEND); } } else { glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j += 2) { glVertex2fv(co_ss[j]); } glEnd(); cpack(0xaaaaaa); setlinestyle(3); glBegin(GL_LINE_STRIP); for (j = 0; j < 3; j += 2) { glVertex2fv(co_ss[j]); } glEnd(); setlinestyle(0); sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); /* text */ { char numstr[256]; float numstr_size[2]; const int prec = 6; /* XXX, todo, make optional */ float pos[2]; ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); mid_v2_v2v2(pos, co_ss[0], co_ss[2]); /* center text */ pos[0] -= numstr_size[0] / 2.0f; pos[1] -= numstr_size[1] / 2.0f; /* draw text (bg) */ glColor4ubv(color_back); uiSetRoundBox(UI_CNR_ALL); uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], bg_radius); /* draw text */ glColor3ubv(color_text); BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); BLF_draw(blf_mono_font, numstr, sizeof(numstr)); } /* capping */ { float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; float cap[2]; normalize_v2(rot_90_vec); glEnable(GL_BLEND); glColor3ubv(color_wire); glBegin(GL_LINES); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); glVertex2fv(cap); madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); glVertex2fv(cap); glEnd(); glDisable(GL_BLEND); } } } glDisable(GL_LINE_SMOOTH); BLF_disable(blf_mono_font, BLF_ROTATION); #undef ARC_STEPS /* draw snap */ if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG)) { ruler_item = ruler_item_active_get(ruler_info); if (ruler_item) { /* size from drawSnapping */ const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); float co_ss[3]; ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP); cpack(color_act); circ(co_ss[0], co_ss[1], size * U.pixelsize); } } }
/** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ static float (*mask_spline_feather_differentiated_points_with_resolution__even( MaskSpline *spline, unsigned int *tot_feather_point, const unsigned int resol, const bool do_feather_isect))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point_curr, *point_prev; float (*feather)[2], (*fp)[2]; const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol); int a; /* tot+1 because of 'forward_diff_bezier' function */ feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points"); a = spline->tot_point - 1; if (spline->flag & MASK_SPLINE_CYCLIC) a++; point_prev = points_array; point_curr = point_prev + 1; while (a--) { /* BezTriple *bezt_prev; */ /* UNUSED */ /* BezTriple *bezt_curr; */ /* UNUSED */ int j; if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC)) point_curr = points_array; /* bezt_prev = &point_prev->bezt; */ /* bezt_curr = &point_curr->bezt; */ for (j = 0; j < resol; j++, fp++) { float u = (float) j / resol, weight; float co[2], n[2]; /* TODO - these calls all calculate similar things * could be unified for some speed */ BKE_mask_point_segment_co(spline, point_prev, u, co); BKE_mask_point_normal(spline, point_prev, u, n); weight = BKE_mask_point_weight(spline, point_prev, u); madd_v2_v2v2fl(*fp, co, n, weight); } if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) { float u = 1.0f, weight; float co[2], n[2]; BKE_mask_point_segment_co(spline, point_prev, u, co); BKE_mask_point_normal(spline, point_prev, u, n); weight = BKE_mask_point_weight(spline, point_prev, u); madd_v2_v2v2fl(*fp, co, n, weight); } point_prev = point_curr; point_curr++; } *tot_feather_point = tot; if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); } return feather; }
/** * reduced copy of #calchandleNurb_intern code in curve.c */ static void calchandle_curvemap( BezTriple *bezt, const BezTriple *prev, const BezTriple *next) { /* defines to avoid confusion */ #define p2_h1 ((p2) - 3) #define p2_h2 ((p2) + 3) const float *p1, *p3; float *p2; float pt[3]; float len, len_a, len_b; float dvec_a[2], dvec_b[2]; if (bezt->h1 == 0 && bezt->h2 == 0) { return; } p2 = bezt->vec[1]; if (prev == NULL) { p3 = next->vec[1]; pt[0] = 2.0f * p2[0] - p3[0]; pt[1] = 2.0f * p2[1] - p3[1]; p1 = pt; } else { p1 = prev->vec[1]; } if (next == NULL) { p1 = prev->vec[1]; pt[0] = 2.0f * p2[0] - p1[0]; pt[1] = 2.0f * p2[1] - p1[1]; p3 = pt; } else { p3 = next->vec[1]; } sub_v2_v2v2(dvec_a, p2, p1); sub_v2_v2v2(dvec_b, p3, p2); len_a = len_v2(dvec_a); len_b = len_v2(dvec_b); if (len_a == 0.0f) len_a = 1.0f; if (len_b == 0.0f) len_b = 1.0f; if (bezt->h1 == HD_AUTO || bezt->h2 == HD_AUTO) { /* auto */ float tvec[2]; tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a; tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a; len = len_v2(tvec) * 2.5614f; if (len != 0.0f) { if (bezt->h1 == HD_AUTO) { len_a /= len; madd_v2_v2v2fl(p2_h1, p2, tvec, -len_a); } if (bezt->h2 == HD_AUTO) { len_b /= len; madd_v2_v2v2fl(p2_h2, p2, tvec, len_b); } } } if (bezt->h1 == HD_VECT) { /* vector */ madd_v2_v2v2fl(p2_h1, p2, dvec_a, -1.0f / 3.0f); } if (bezt->h2 == HD_VECT) { madd_v2_v2v2fl(p2_h2, p2, dvec_b, 1.0f / 3.0f); } #undef p2_h1 #undef p2_h2 }
/** * reduced copy of #calchandleNurb_intern code in curve.c */ static void calchandle_curvemap( BezTriple *bezt, const BezTriple *prev, const BezTriple *next) { /* defines to avoid confusion */ #define p2_h1 ((p2) - 3) #define p2_h2 ((p2) + 3) const float *p1, *p3; float *p2; float pt[3]; float len, len_a, len_b; float dvec_a[2], dvec_b[2]; if (bezt->h1 == 0 && bezt->h2 == 0) { return; } p2 = bezt->vec[1]; if (prev == NULL) { p3 = next->vec[1]; pt[0] = 2.0f * p2[0] - p3[0]; pt[1] = 2.0f * p2[1] - p3[1]; p1 = pt; } else { p1 = prev->vec[1]; } if (next == NULL) { p1 = prev->vec[1]; pt[0] = 2.0f * p2[0] - p1[0]; pt[1] = 2.0f * p2[1] - p1[1]; p3 = pt; } else { p3 = next->vec[1]; } sub_v2_v2v2(dvec_a, p2, p1); sub_v2_v2v2(dvec_b, p3, p2); len_a = len_v2(dvec_a); len_b = len_v2(dvec_b); if (len_a == 0.0f) len_a = 1.0f; if (len_b == 0.0f) len_b = 1.0f; if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) || ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */ float tvec[2]; tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a; tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a; len = len_v2(tvec) * 2.5614f; if (len != 0.0f) { if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { len_a /= len; madd_v2_v2v2fl(p2_h1, p2, tvec, -len_a); if ((bezt->h1 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */ const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1]; const float ydiff2 = next->vec[1][1] - bezt->vec[1][1]; if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) { bezt->vec[0][1] = bezt->vec[1][1]; } else { /* handles should not be beyond y coord of two others */ if (ydiff1 <= 0.0f) { if (prev->vec[1][1] > bezt->vec[0][1]) { bezt->vec[0][1] = prev->vec[1][1]; } } else { if (prev->vec[1][1] < bezt->vec[0][1]) { bezt->vec[0][1] = prev->vec[1][1]; } } } } } if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { len_b /= len; madd_v2_v2v2fl(p2_h2, p2, tvec, len_b); if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */ const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1]; const float ydiff2 = next->vec[1][1] - bezt->vec[1][1]; if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) { bezt->vec[2][1] = bezt->vec[1][1]; } else { /* handles should not be beyond y coord of two others */ if (ydiff1 <= 0.0f) { if (next->vec[1][1] < bezt->vec[2][1]) { bezt->vec[2][1] = next->vec[1][1]; } } else { if (next->vec[1][1] > bezt->vec[2][1]) { bezt->vec[2][1] = next->vec[1][1]; } } } } } } } if (bezt->h1 == HD_VECT) { /* vector */ madd_v2_v2v2fl(p2_h1, p2, dvec_a, -1.0f / 3.0f); } if (bezt->h2 == HD_VECT) { madd_v2_v2v2fl(p2_h2, p2, dvec_b, 1.0f / 3.0f); } #undef p2_h1 #undef p2_h2 }