[Bf-blender-cvs] [7a96eef] gsoc2016-improved_extrusion: Curves: Chamfer
João Araújo
noreply at git.blender.org
Sat Jul 30 21:59:29 CEST 2016
Commit: 7a96eef2def37562d188ef2d5e7b07e82ab98093
Author: João Araújo
Date: Sat Jul 30 20:58:34 2016 +0100
Branches: gsoc2016-improved_extrusion
https://developer.blender.org/rB7a96eef2def37562d188ef2d5e7b07e82ab98093
Curves: Chamfer
Implemented the chamfer operator for one selected vertex and with parameters controlled through the Tool Shelf.
===================================================================
M source/blender/editors/curve/curve_intern.h
M source/blender/editors/curve/curve_ops.c
M source/blender/editors/curve/editcurve.c
===================================================================
diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h
index 2cfb488..b4788cd 100644
--- a/source/blender/editors/curve/curve_intern.h
+++ b/source/blender/editors/curve/curve_intern.h
@@ -132,6 +132,7 @@ void CURVE_OT_extend_curve(struct wmOperatorType *ot);
void CURVE_OT_trim_curve(struct wmOperatorType *ot);
void CURVE_OT_offset_curve(struct wmOperatorType *ot);
void CURVE_OT_batch_extend(struct wmOperatorType *ot);
+void CURVE_OT_curve_chamfer(struct wmOperatorType *ot);
bool ED_curve_pick_vert(
struct ViewContext *vc, short sel, const int mval[2],
diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c
index 5772cbc..398f4dc 100644
--- a/source/blender/editors/curve/curve_ops.c
+++ b/source/blender/editors/curve/curve_ops.c
@@ -143,6 +143,7 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_trim_curve);
WM_operatortype_append(CURVE_OT_offset_curve);
WM_operatortype_append(CURVE_OT_batch_extend);
+ WM_operatortype_append(CURVE_OT_curve_chamfer);
WM_operatortype_append(CURVE_OT_match_texture_space);
}
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 571bf01..bddf5b8 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -7739,7 +7739,9 @@ static void extend_vertex(int i, Nurb *nu, ListBase *nubase, Object *obedit, flo
static void add_bezt(Nurb *nu, float *p, int position, Curve *cu)
{
- /* this function is a weaker version of the ed_editnurb_addvert function */
+ /* this function is a weaker version of the ed_editnurb_addvert function
+ * this function is just silly. BKE_nurb_bezierpoints_add seems to do exactly the same
+ * job. TODO: rewrite this */
Nurb *cu_actnu;
union {
BezTriple *bezt;
@@ -7866,3 +7868,220 @@ void CURVE_OT_batch_extend(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/******************** Chamfer operator ********************/
+
+static void chamfer_handle(BezTriple *bezt, BezTriple *r_new_bezt1, BezTriple *r_new_bezt2, float theta, float d)
+{
+ /* first, get the plane defined by the handle */
+ float v1[3], v2[3], k[3], plane[4], vrot[3], helper[3];
+ copy_v3_v3(v1, bezt->vec[1]);
+ sub_v3_v3v3(v1, v1, bezt->vec[0]);
+ copy_v3_v3(v2, bezt->vec[2]);
+ sub_v3_v3v3(v2, v2, bezt->vec[1]);
+ cross_v3_v3v3(k, v1, v2);
+ normalize_v3(k);
+
+ plane_from_point_normal_v3(plane, bezt->vec[0], k);
+
+ /* rotate v1 about k applied on point bezt->vec[0] the specified number of degrees */
+ /* apply Rodrigues' formula */
+ copy_v3_v3(vrot, v1);
+ mul_v3_fl(vrot, cos(theta));
+ cross_v3_v3v3(helper, k, v1);
+ mul_v3_fl(helper, sin(theta));
+ add_v3_v3(vrot, helper);
+ copy_v3_v3(helper, k);
+ mul_v3_fl(helper, dot_v3v3(k, v1) * (1-cos(theta)));
+ add_v3_v3(vrot, helper);
+ normalize_v3(vrot);
+
+ /* "translate" the first segment d units along vrot */
+ float p1[3], p2[3], ip1[3];
+ copy_v3_v3(p1, bezt->vec[0]);
+ copy_v3_v3(p2, bezt->vec[1]);
+ mul_v3_fl(vrot, d);
+ add_v3_v3(p1, vrot);
+ add_v3_v3(p2, vrot);
+
+ /* intersect the segments and get the control point for the second handle */
+ int result = isect_line_line_v3(bezt->vec[1], bezt->vec[2], p1, p2, ip1, ip1);
+ copy_v3_v3(r_new_bezt2->vec[1], ip1);
+
+ /* repeat the above process to get the control point for the first handle */
+ mul_v3_fl(vrot, -1); /* very important */
+ copy_v3_v3(p1, bezt->vec[2]);
+ copy_v3_v3(p2, bezt->vec[1]);
+ add_v3_v3(p1, vrot);
+ add_v3_v3(p2, vrot);
+
+ /* intersect the segments and get the control point for the first handle */
+ result = isect_line_line_v3(bezt->vec[0], bezt->vec[1], p1, p2, ip1, ip1);
+ copy_v3_v3(r_new_bezt1->vec[1], ip1);
+}
+
+static int curve_chamfer_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ListBase *nubase = object_editcurve_get(obedit);
+ Nurb *nu;
+ float distance = RNA_float_get(op->ptr, "distance");
+ float angle = RNA_float_get(op->ptr, "angle");
+
+ /* get selected spline */
+ int spline_id = get_selected_spline_id(nubase);
+ nu = BLI_findlink(nubase, spline_id);
+ if (!nu) {
+ BKE_report(op->reports, RPT_ERROR, "One spline must be selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* check if handles are vector type! */
+ BezTriple *bezt = nu->bezt, *bezt1, *bezt2, *helper;
+ bezt1 = MEM_callocN(sizeof(BezTriple), "curve_chamfer1");
+ bezt2 = MEM_callocN(sizeof(BezTriple), "curve_chamfer2");
+ int selected_point = 0;
+ for (int i = 0; i < nu->pntsu; i++) {
+ if (BEZT_ISSEL_ANY(bezt) && bezt->h1 == 2 && bezt->h2 == 2) {
+ chamfer_handle(bezt, bezt1, bezt2, angle, distance);
+ selected_point = i;
+ }
+ bezt++;
+ }
+
+ BKE_nurb_bezierPoints_add(nu, 1);
+
+ memcpy(&nu->bezt[selected_point + 1], &nu->bezt[selected_point], (nu->pntsu - selected_point - 1) * sizeof(BezTriple));
+ memcpy(&nu->bezt[selected_point], bezt1, sizeof(BezTriple));
+ memcpy(&nu->bezt[selected_point + 1], bezt2, sizeof(BezTriple));
+
+ /* set the handles for the first chamfered triple */
+ float v[3];
+ bezt1 = &nu->bezt[selected_point];
+ helper = &nu->bezt[selected_point - 1];
+ /* left handle */
+ sub_v3_v3v3(v, helper->vec[2], bezt1->vec[1]);
+ mul_v3_fl(v, 0.4 * len_v3(v));
+ copy_v3_v3(bezt1->vec[0], bezt1->vec[1]);
+ add_v3_v3(bezt1->vec[0], v);
+ /* right handle */
+ bezt2 = &nu->bezt[selected_point + 1];
+ sub_v3_v3v3(v, bezt2->vec[1], bezt1->vec[1]);
+ mul_v3_fl(v, 0.4 * len_v3(v));
+ copy_v3_v3(bezt1->vec[2], bezt1->vec[1]);
+ add_v3_v3(bezt1->vec[2], v);
+
+ /* second chamfered triple */
+ helper = &nu->bezt[selected_point + 2];
+ /* left handle */
+ sub_v3_v3v3(v, bezt1->vec[1], bezt2->vec[1]);
+ mul_v3_fl(v, 0.4 * len_v3(v));
+ copy_v3_v3(bezt2->vec[0], bezt2->vec[1]);
+ add_v3_v3(bezt2->vec[0], v);
+ /* right handle */
+ bezt2 = &nu->bezt[selected_point + 1];
+ sub_v3_v3v3(v, helper->vec[0], bezt2->vec[1]);
+ mul_v3_fl(v, 0.4 * len_v3(v));
+ copy_v3_v3(bezt2->vec[2], bezt2->vec[1]);
+ add_v3_v3(bezt2->vec[2], v);
+
+ MEM_freeN(bezt1);
+ MEM_freeN(bezt2);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_FINISHED;
+}
+
+static int curve_chamfer_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ char str[UI_MAX_DRAW_STR];
+ size_t ofs = 0;
+ ListBase *nubase = object_editcurve_get(obedit);
+ Nurb *nu, *new_nu;
+ int *init_mouse = op->customdata, changed = init_mouse[2];
+ float curr_mouse[2] = {event->x, event->y};
+ float prev_mouse[2] = {init_mouse[0], init_mouse[1]};
+ float distance = 1.0;
+ int spline_id = get_selected_spline_id(nubase);
+ nu = BLI_findlink(nubase, spline_id);
+ if (!nu) {
+ BKE_report(op->reports, RPT_ERROR, "One spline must be selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (event->type == MOUSEMOVE) {
+ if (changed) {
+ new_nu = nubase->last;
+ BLI_poptail(nubase);
+ BKE_nurb_free(new_nu);
+ }
+ //float d = len_v2v2(prev_mouse, curr_mouse);
+ float dy = curr_mouse[1] - prev_mouse[1];
+ //RNA_float_set(op->ptr, "distance", d/1000);
+ RNA_float_set(op->ptr, "distance", dy/100);
+ distance = RNA_float_get(op->ptr, "distance");
+ new_nu = offset_curve(nu, nubase, distance);
+ BLI_addtail(nubase, new_nu);
+ init_mouse[2] = 1;
+ }
+ else if (event->type == LEFTMOUSE) {
+ //offset_curve_exec(C, op);
+ ED_area_headerprint(CTX_wm_area(C), NULL);
+ MEM_freeN(init_mouse);
+ return OPERATOR_FINISHED;
+ }
+ else if (event->type == ESCKEY) {
+ ED_area_headerprint(CTX_wm_area(C), NULL);
+ MEM_freeN(init_mouse);
+ return OPERATOR_CANCELLED;
+ }
+
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Offset distance: %.2f"), distance);
+ ED_area_headerprint(CTX_wm_area(C), str);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DAG_id_tag_update(obedit->data, 0);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int curve_chamfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int *mouse = MEM_callocN(3 * sizeof(int), "offset_curve_invoke");
+ mouse[0] = event->x;
+ mouse[1] = event->y;
+ mouse[2] = 0; /* this is a flag to check if the operator is currently running or if it has just been called */
+
+ op->customdata = mouse;
+
+ /* add modal handler */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void CURVE_OT_curve_chamfer(wmOperatorType *ot)
+{
+
+ /* identifiers */
+ ot->name = "Chamfer";
+ ot->description = "Chamfer selected points";
+ ot->idname = "CURVE_OT_curve_chamfer";
+
+ /* api callbacks */
+ ot->exec = curve_chamfer_exec;
+ ot->poll = ED_operator_editsurfcurve;
+ //ot->modal = curve_chamfer_modal;
+ //ot->invoke = curve_chamfer_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties */
+ RNA_def_float(ot->srna, "angle", DEG2RAD(45.0f), 0.0f, DEG2RAD(90.0f), "Chamfer angle", "", 0.0f, DEG2RAD(90.0f));
+ RNA_def_float(ot->srna, "distance", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Chamfer length", "", 0.0f, 10.0f);
+}
\ No newline at end of file
More information about the Bf-blender-cvs
mailing list