Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/mesh/editmesh_rip.c
| Show First 20 Lines • Show All 339 Lines • ▼ Show 20 Lines | |||||
| static BMVert *edbm_ripsel_edloop_pair_start_vert(BMEdge *e) | static BMVert *edbm_ripsel_edloop_pair_start_vert(BMEdge *e) | ||||
| { | { | ||||
| /* try step in a direction, if it fails we know do go the other way */ | /* try step in a direction, if it fails we know do go the other way */ | ||||
| BMVert *v_test = e->v1; | BMVert *v_test = e->v1; | ||||
| return (edbm_ripsel_edge_uid_step(e, &v_test)) ? e->v1 : e->v2; | return (edbm_ripsel_edge_uid_step(e, &v_test)) ? e->v1 : e->v2; | ||||
| } | } | ||||
| static void edbm_ripsel_deselect_helper( | static void edbm_ripsel_deselect_helper(BMesh *bm, | ||||
| BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *ar, float projectMat[4][4], float fmval[2]) | EdgeLoopPair *eloop_pairs, | ||||
| ARegion *ar, | |||||
| float projectMat[4][4], | |||||
| const float fmval[2]) | |||||
| { | { | ||||
| EdgeLoopPair *lp; | EdgeLoopPair *lp; | ||||
| for (lp = eloop_pairs; lp->l_a; lp++) { | for (lp = eloop_pairs; lp->l_a; lp++) { | ||||
| BMEdge *e; | BMEdge *e; | ||||
| BMVert *v_prev; | BMVert *v_prev; | ||||
| float score_a = 0.0f; | float score_a = 0.0f; | ||||
| ▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *uloop_pairs) | ||||
| } | } | ||||
| } | } | ||||
| /* --- end 'face-fill' code --- */ | /* --- end 'face-fill' code --- */ | ||||
| /** | /** | ||||
| * This is the main vert ripping function (rip when one vertex is selected) | * This is the main vert ripping function (rip when one vertex is selected) | ||||
| */ | */ | ||||
| static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obedit, bool do_fill) | static int edbm_rip_invoke__vert(bContext *C, const float fmval[2], Object *obedit, bool do_fill) | ||||
| { | { | ||||
| UnorderedLoopPair *fill_uloop_pairs = NULL; | UnorderedLoopPair *fill_uloop_pairs = NULL; | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| RegionView3D *rv3d = CTX_wm_region_view3d(C); | RegionView3D *rv3d = CTX_wm_region_view3d(C); | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| BMIter iter, liter; | BMIter iter, liter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMEdge *e_best; | BMEdge *e_best; | ||||
| BMVert *v; | BMVert *v; | ||||
| const int totvert_orig = bm->totvert; | const int totvert_orig = bm->totvert; | ||||
| int i; | int i; | ||||
| float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; | float projectMat[4][4]; | ||||
| float dist_sq = FLT_MAX; | float dist_sq = FLT_MAX; | ||||
| float d; | float d; | ||||
| bool is_wire, is_manifold_region; | bool is_wire, is_manifold_region; | ||||
| BMEditSelection ese; | BMEditSelection ese; | ||||
| int totboundary_edge = 0; | int totboundary_edge = 0; | ||||
| ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); | ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); | ||||
| ▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | static int edbm_rip_invoke__vert(bContext *C, const float fmval[2], Object *obedit, bool do_fill) | ||||
| } | } | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| /** | /** | ||||
| * This is the main edge ripping function | * This is the main edge ripping function | ||||
| */ | */ | ||||
| static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obedit, bool do_fill) | static int edbm_rip_invoke__edge(bContext *C, const float fmval[2], Object *obedit, bool do_fill) | ||||
| { | { | ||||
| UnorderedLoopPair *fill_uloop_pairs = NULL; | UnorderedLoopPair *fill_uloop_pairs = NULL; | ||||
| ARegion *ar = CTX_wm_region(C); | ARegion *ar = CTX_wm_region(C); | ||||
| RegionView3D *rv3d = CTX_wm_region_view3d(C); | RegionView3D *rv3d = CTX_wm_region_view3d(C); | ||||
| BMEditMesh *em = BKE_editmesh_from_object(obedit); | BMEditMesh *em = BKE_editmesh_from_object(obedit); | ||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| BMIter iter, eiter; | BMIter iter, eiter; | ||||
| BMLoop *l; | BMLoop *l; | ||||
| BMEdge *e_best; | BMEdge *e_best; | ||||
| BMVert *v; | BMVert *v; | ||||
| const int totedge_orig = bm->totedge; | const int totedge_orig = bm->totedge; | ||||
| float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; | float projectMat[4][4]; | ||||
| EdgeLoopPair *eloop_pairs; | EdgeLoopPair *eloop_pairs; | ||||
| ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); | ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); | ||||
| /* important this runs on the original selection, before tampering with tagging */ | /* important this runs on the original selection, before tampering with tagging */ | ||||
| eloop_pairs = edbm_ripsel_looptag_helper(bm); | eloop_pairs = edbm_ripsel_looptag_helper(bm); | ||||
| ▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | if (totedge_orig == bm->totedge) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| BM_select_history_validate(bm); | BM_select_history_validate(bm); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| union RipMval { | |||||
| void *data; | |||||
| float fmval[2]; | |||||
| }; | |||||
| /* based on mouse cursor position, it defines how is being ripped */ | /* based on mouse cursor position, it defines how is being ripped */ | ||||
| static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int edbm_rip_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| uint objects_len = 0; | uint objects_len = 0; | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( | ||||
| view_layer, CTX_wm_view3d(C), &objects_len); | view_layer, CTX_wm_view3d(C), &objects_len); | ||||
| const bool do_fill = RNA_boolean_get(op->ptr, "use_fill"); | const bool do_fill = RNA_boolean_get(op->ptr, "use_fill"); | ||||
| bool no_vertex_selected = true; | bool no_vertex_selected = true; | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | for (uint ob_index = 0; ob_index < objects_len; ob_index++) { | ||||
| */ | */ | ||||
| /* BM_ELEM_SELECT --> BM_ELEM_TAG */ | /* BM_ELEM_SELECT --> BM_ELEM_TAG */ | ||||
| BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { | BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { | ||||
| BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); | BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); | ||||
| } | } | ||||
| /* split 2 main parts of this operator out into vertex and edge ripping */ | /* split 2 main parts of this operator out into vertex and edge ripping */ | ||||
| union RipMval data; | |||||
| data.data = op->customdata; | |||||
| if (singlesel) { | if (singlesel) { | ||||
| ret = edbm_rip_invoke__vert(C, event, obedit, do_fill); | ret = edbm_rip_invoke__vert(C, data.fmval, obedit, do_fill); | ||||
| } | } | ||||
| else { | else { | ||||
| ret = edbm_rip_invoke__edge(C, event, obedit, do_fill); | ret = edbm_rip_invoke__edge(C, data.fmval, obedit, do_fill); | ||||
| } | } | ||||
| if (ret != OPERATOR_FINISHED) { | if (ret != OPERATOR_FINISHED) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0)); | BLI_assert(singlesel ? (bm->totvertsel > 0) : (bm->totedgesel > 0)); | ||||
| Show All 22 Lines | static int edbm_rip_exec(bContext *C, wmOperator *op) | ||||
| else if (error_rip_failed) { | else if (error_rip_failed) { | ||||
| BKE_report(op->reports, RPT_ERROR, "Rip failed"); | BKE_report(op->reports, RPT_ERROR, "Rip failed"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| /* No errors, everything went fine. */ | /* No errors, everything went fine. */ | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) | |||||
| { | |||||
| union RipMval data; | |||||
| data.fmval[0] = event->mval[0]; | |||||
| data.fmval[1] = event->mval[1]; | |||||
| op->customdata = data.data; | |||||
| return edbm_rip_exec(C, op); | |||||
| } | |||||
| void MESH_OT_rip(wmOperatorType *ot) | void MESH_OT_rip(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Rip"; | ot->name = "Rip"; | ||||
| ot->idname = "MESH_OT_rip"; | ot->idname = "MESH_OT_rip"; | ||||
| ot->description = "Disconnect vertex or edges from connected geometry"; | ot->description = "Disconnect vertex or edges from connected geometry"; | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->invoke = edbm_rip_invoke; | ot->invoke = edbm_rip_invoke; | ||||
| ot->exec = edbm_rip_exec; | |||||
| ot->poll = EDBM_view3d_poll; | ot->poll = EDBM_view3d_poll; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| /* to give to transform */ | /* to give to transform */ | ||||
| Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); | Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY); | ||||
| RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region"); | RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill the ripped region"); | ||||
| } | } | ||||