mesh bisect can now be defined with mouse input
authorCampbell Barton <ideasman42@gmail.com>
Thu, 29 Aug 2013 18:45:04 +0000 (18:45 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 29 Aug 2013 18:45:04 +0000 (18:45 +0000)
(using cursor + numeric values was too clumsy for defining orientation).

once the cut is done numeric input still works as before

release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/editors/mesh/CMakeLists.txt
source/blender/editors/mesh/editmesh_bisect.c [new file with mode: 0644]
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_intern.h
source/blender/windowmanager/intern/wm_operators.c

index bc33d3b77736e2bc5fc627c56233a763b6a97513..b3f139e5377e8af271c0543381a8c7dd64d5a648 100644 (file)
@@ -174,8 +174,9 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
         col.operator("mesh.subdivide")
         col.operator("mesh.loopcut_slide")
         col.operator("mesh.duplicate_move", text="Duplicate")
-        col.operator("mesh.spin")
-        col.operator("mesh.screw")
+        row = col.row(align=True)
+        row.operator("mesh.spin")
+        row.operator("mesh.screw")
 
         row = col.row(align=True)
         props = row.operator("mesh.knife_tool", text="Knife")
@@ -185,6 +186,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
         props.use_occlude_geometry = False
         props.only_selected = True
         col.operator("mesh.knife_project")
+        col.operator("mesh.bisect")
 
         col = layout.column(align=True)
         col.label(text="Remove:")
index 69ef4715df6e6a5fc228dd68995571861d5d8f10..8d91b300ff36c34e09dd0fe726a8dd33a5292852 100644 (file)
@@ -42,6 +42,7 @@ set(SRC
        editface.c
        editmesh_add.c
        editmesh_bevel.c
+       editmesh_bisect.c
        editmesh_extrude.c
        editmesh_inset.c
        editmesh_knife.c
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
new file mode 100644 (file)
index 0000000..b8d5311
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_bisect.c
+ *  \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+
+#include "BKE_global.h"
+#include "BKE_context.h"
+#include "BKE_editmesh.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+#include "mesh_intern.h"  /* own include */
+
+
+
+/* -------------------------------------------------------------------- */
+/* Model Helpers */
+
+typedef struct {
+       /* modal only */
+       BMBackup mesh_backup;
+       bool is_first;
+       short twtype;
+} BisectData;
+
+static bool mesh_bisect_interactive_calc(
+        bContext *C, wmOperator *op,
+        BMEditMesh *em,
+        float plane_co[3], float plane_no[3])
+{
+       wmGesture *gesture = op->customdata;
+       BisectData *opdata;
+
+       ARegion *ar = CTX_wm_region(C);
+       RegionView3D *rv3d = ar->regiondata;
+
+       int x_start = RNA_int_get(op->ptr, "xstart");
+       int y_start = RNA_int_get(op->ptr, "ystart");
+       int x_end = RNA_int_get(op->ptr, "xend");
+       int y_end = RNA_int_get(op->ptr, "yend");
+
+       const float *co_ref = rv3d->ofs;
+       float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2];
+       float co_a[3], co_b[3];
+       float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL);
+
+       opdata = gesture->userdata;
+
+       /* view vector */
+       ED_view3d_win_to_vector(ar, co_a_ss, co_a);
+
+       /* view delta */
+       sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss);
+       ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac);
+
+       /* cross both to get a normal */
+       cross_v3_v3v3(plane_no, co_a, co_b);
+
+       /* point on plane, can use either start or endpoint */
+       ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co);
+
+       if (opdata->is_first == false)
+               EDBM_redo_state_restore(opdata->mesh_backup, em, false);
+
+       opdata->is_first = false;
+
+       return true;
+}
+
+static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       int ret;
+
+       ret = WM_gesture_straightline_invoke(C, op, event);
+       if (ret & OPERATOR_RUNNING_MODAL) {
+               View3D *v3d = CTX_wm_view3d(C);
+
+               wmGesture *gesture = op->customdata;
+               BisectData *opdata;
+
+               Object *obedit = CTX_data_edit_object(C);
+               BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+               opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
+               opdata->mesh_backup = EDBM_redo_state_store(em);
+               opdata->is_first = true;
+               gesture->userdata = opdata;
+
+               /* misc other vars */
+               G.moving = G_TRANSFORM_EDIT;
+               opdata->twtype = v3d->twtype;
+               v3d->twtype = 0;
+       }
+       return ret;
+}
+
+static void edbm_bisect_exit(bContext *C, BisectData *opdata)
+{
+       View3D *v3d = CTX_wm_view3d(C);
+       EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+       v3d->twtype = opdata->twtype;
+       G.moving = 0;
+}
+
+static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       wmGesture *gesture = op->customdata;
+       BisectData *opdata = gesture->userdata;
+       BisectData opdata_back = *opdata;  /* annoyance, WM_gesture_straightline_modal, frees */
+       int ret;
+
+       ret = WM_gesture_straightline_modal(C, op, event);
+
+       if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) {
+               if (opdata)
+                       edbm_bisect_exit(C, &opdata_back);
+       }
+
+       return ret;
+}
+
+/* End Model Helpers */
+/* -------------------------------------------------------------------- */
+
+
+
+static int mesh_bisect_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+
+       /* both can be NULL, fallbacks values are used */
+       View3D *v3d = CTX_wm_view3d(C);
+       RegionView3D *rv3d = ED_view3d_context_rv3d(C);
+
+       Object *obedit = CTX_data_edit_object(C);
+       BMEditMesh *em = BKE_editmesh_from_object(obedit);
+       BMesh *bm;
+       BMOperator bmop;
+       float plane_co[3];
+       float plane_no[3];
+       float imat[4][4];
+
+       const float thresh = RNA_float_get(op->ptr, "threshold");
+       const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
+       const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
+       const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
+
+       PropertyRNA *prop_plane_co;
+       PropertyRNA *prop_plane_no;
+
+       prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co");
+       if (RNA_property_is_set(op->ptr, prop_plane_co)) {
+               RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co);
+       }
+       else {
+               copy_v3_v3(plane_co, give_cursor(scene, v3d));
+               RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+       }
+
+       prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no");
+       if (RNA_property_is_set(op->ptr, prop_plane_no)) {
+               RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no);
+       }
+       else {
+               if (rv3d) {
+                       copy_v3_v3(plane_no, rv3d->viewinv[1]);
+               }
+               else {
+                       /* fallback... */
+                       plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
+               }
+               RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+       }
+
+
+
+       /* -------------------------------------------------------------------- */
+       /* Modal support */
+       /* Note: keep this isolated, exec can work wihout this */
+       if ((op->customdata != NULL) &&
+           mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no))
+       {
+               /* write back to the props */
+               RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no);
+               RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co);
+       }
+       /* End Modal */
+       /* -------------------------------------------------------------------- */
+
+
+
+       bm = em->bm;
+
+       invert_m4_m4(imat, obedit->obmat);
+       mul_m4_v3(imat, plane_co);
+       mul_mat3_m4_v3(imat, plane_no);
+
+       EDBM_op_init(em, &bmop, op,
+                    "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
+                    BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
+       BMO_op_exec(bm, &bmop);
+
+       EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+       if (use_fill) {
+               float normal_fill[3];
+               BMOperator bmop_fill;
+               BMOperator bmop_attr;
+
+               normalize_v3_v3(normal_fill, plane_no);
+               if (clear_outer == true && clear_inner == false) {
+                       negate_v3(normal_fill);
+               }
+
+               /* Fill */
+               BMO_op_initf(
+                       bm, &bmop_fill, op->flag,
+                       "triangle_fill edges=%S normal=%v use_dissolve=%b",
+                       &bmop, "geom_cut.out", normal_fill, true);
+               BMO_op_exec(bm, &bmop_fill);
+
+               /* Copy Attributes */
+               BMO_op_initf(bm, &bmop_attr, op->flag,
+                            "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+                            &bmop_fill, "geom.out", false, true);
+               BMO_op_exec(bm, &bmop_attr);
+
+               BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
+
+               BMO_op_finish(bm, &bmop_attr);
+               BMO_op_finish(bm, &bmop_fill);
+       }
+
+       BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
+
+       if (!EDBM_op_finish(em, &bmop, op, true)) {
+               return OPERATOR_CANCELLED;
+       }
+       else {
+               EDBM_update_generic(em, true, true);
+               EDBM_selectmode_flush(em);
+               return OPERATOR_FINISHED;
+       }
+}
+
+
+void MESH_OT_bisect(struct wmOperatorType *ot)
+{
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name = "Bisect";
+       ot->description = "Enforce symmetry (both form and topological) across an axis";
+       ot->idname = "MESH_OT_bisect";
+
+       /* api callbacks */
+       ot->exec = mesh_bisect_exec;
+       ot->invoke = mesh_bisect_invoke;
+       ot->modal = mesh_bisect_modal;
+       ot->cancel = WM_gesture_straightline_cancel;
+       ot->poll = ED_operator_editmesh;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+
+       prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
+                                   "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+       prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
+                                   "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+       RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
+       RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
+       RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry infront of the plane");
+
+       RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
+
+       WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT);
+}
index d23cee407b6edf6d659ebf9d2168b50f0956c804..f384ac9c44803ee3f46363cc8eb948758539b3e1 100644 (file)
@@ -4435,138 +4435,6 @@ void MESH_OT_convex_hull(wmOperatorType *ot)
 }
 #endif
 
-
-static int mesh_bisect_exec(bContext *C, wmOperator *op)
-{
-       Scene *scene = CTX_data_scene(C);
-
-       /* both can be NULL, fallbacks values are used */
-       View3D *v3d = CTX_wm_view3d(C);
-       RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
-       Object *obedit = CTX_data_edit_object(C);
-       BMEditMesh *em = BKE_editmesh_from_object(obedit);
-       BMesh *bm = em->bm;
-       BMOperator bmop;
-       float plane_co[3];
-       float plane_no[3];
-       float imat[4][4];
-
-       const float thresh = RNA_float_get(op->ptr, "threshold");
-       const bool use_fill = RNA_boolean_get(op->ptr, "use_fill");
-       const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner");
-       const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer");
-
-       PropertyRNA *prop;
-
-       prop = RNA_struct_find_property(op->ptr, "plane_co");
-       if (RNA_property_is_set(op->ptr, prop)) {
-               RNA_property_float_get_array(op->ptr, prop, plane_co);
-       }
-       else {
-               copy_v3_v3(plane_co, give_cursor(scene, v3d));
-               RNA_property_float_set_array(op->ptr, prop, plane_co);
-       }
-
-       prop = RNA_struct_find_property(op->ptr, "plane_no");
-       if (RNA_property_is_set(op->ptr, prop)) {
-               RNA_property_float_get_array(op->ptr, prop, plane_no);
-       }
-       else {
-               if (rv3d) {
-                       copy_v3_v3(plane_no, rv3d->viewinv[1]);
-               }
-               else {
-                       /* fallback... */
-                       plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f;
-               }
-               RNA_property_float_set_array(op->ptr, prop, plane_no);
-       }
-
-       invert_m4_m4(imat, obedit->obmat);
-       mul_m4_v3(imat, plane_co);
-       mul_mat3_m4_v3(imat, plane_no);
-
-       EDBM_op_init(em, &bmop, op,
-                    "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b",
-                    BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer);
-       BMO_op_exec(bm, &bmop);
-
-       EDBM_flag_disable_all(em, BM_ELEM_SELECT);
-
-       if (use_fill) {
-               float normal_fill[3];
-               BMOperator bmop_fill;
-               BMOperator bmop_attr;
-
-               normalize_v3_v3(normal_fill, plane_no);
-               if (clear_outer == true && clear_inner == false) {
-                       negate_v3(normal_fill);
-               }
-
-               /* Fill */
-               BMO_op_initf(
-                       bm, &bmop_fill, op->flag,
-                       "triangle_fill edges=%S normal=%v use_dissolve=%b",
-                       &bmop, "geom_cut.out", normal_fill, true);
-               BMO_op_exec(bm, &bmop_fill);
-
-               /* Copy Attributes */
-               BMO_op_initf(bm, &bmop_attr, op->flag,
-                            "face_attribute_fill faces=%S use_normals=%b use_data=%b",
-                            &bmop_fill, "geom.out", false, true);
-               BMO_op_exec(bm, &bmop_attr);
-
-               BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true);
-
-               BMO_op_finish(bm, &bmop_attr);
-               BMO_op_finish(bm, &bmop_fill);
-       }
-
-       BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true);
-
-       if (!EDBM_op_finish(em, &bmop, op, true)) {
-               return OPERATOR_CANCELLED;
-       }
-       else {
-               EDBM_update_generic(em, true, true);
-               EDBM_selectmode_flush(em);
-               return OPERATOR_FINISHED;
-       }
-}
-
-void MESH_OT_bisect(struct wmOperatorType *ot)
-{
-       PropertyRNA *prop;
-
-       /* identifiers */
-       ot->name = "Bisect";
-       ot->description = "Enforce symmetry (both form and topological) across an axis";
-       ot->idname = "MESH_OT_bisect";
-
-       /* api callbacks */
-       ot->exec = mesh_bisect_exec;
-       ot->poll = ED_operator_editmesh;
-
-       /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-
-       prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX,
-                                   "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX);
-       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-       prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX,
-                                   "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX);
-       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
-       RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut");
-       RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane");
-       RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry infront of the plane");
-
-       RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1);
-
-}
-
 static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
index be9243dc7ef5975f87f3357c86af7c75e503702c..ed026258e4b87c9238d3a33dc6cd3c968c5c39f1 100644 (file)
@@ -95,6 +95,8 @@ void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot);
 /* *** editmesh_bevel.c *** */
 void MESH_OT_bevel(struct wmOperatorType *ot);
 
+/* *** editmesh_bisect.c *** */
+void MESH_OT_bisect(struct wmOperatorType *ot);
 
 /* *** editmesh_extrude.c *** */
 void MESH_OT_extrude_repeat(struct wmOperatorType *ot);
@@ -171,7 +173,6 @@ void MESH_OT_edge_split(struct wmOperatorType *ot);
 void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
 void MESH_OT_wireframe(struct wmOperatorType *ot);
 void MESH_OT_convex_hull(struct wmOperatorType *ot);
-void MESH_OT_bisect(struct wmOperatorType *ot);
 void MESH_OT_symmetrize(struct wmOperatorType *ot);
 void MESH_OT_symmetry_snap(struct wmOperatorType *ot);
 void MESH_OT_shape_propagate_to_all(struct wmOperatorType *ot);
index fbb51702844bc9a22ffb18d8f3f3704fc6fcb3a9..b52357a8f46733c6958e679b8a431be170b3770c 100644 (file)
@@ -4256,6 +4256,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
        /* assign map to operators */
        WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line");
        WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
+       WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
 }