Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-07-20 14:33:15 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-07-20 14:33:15 +0400
commit3b26b46631eefe5a38b54c6465dc5dd82f2c6294 (patch)
tree559e2fb642498619d461c94bd18bb8f06677d3b0 /source/blender/editors/mesh
parentc8db1e832d26e7b34ace2f36ff66b40d1195cb7c (diff)
Separate meshes by loose parts and materials now works in object mode as well as editmode.
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c165
1 files changed, 98 insertions, 67 deletions
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 5657cef4fd2..53744a01b8c 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2790,121 +2790,110 @@ void MESH_OT_knife_cut(wmOperatorType *ot)
RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
}
-static int mesh_separate_selected(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
+static int mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
- Base *basenew;
+ Base *base_new;
BMIter iter;
BMVert *v;
BMEdge *e;
- Object *obedit = editbase->object;
- Mesh *me = obedit->data;
- BMEditMesh *em = me->edit_btmesh;
+ Object *obedit = base_old->object;
BMesh *bm_new;
-
- if (!em)
- return FALSE;
-
+
bm_new = BM_mesh_create(&bm_mesh_allocsize_default);
- CustomData_copy(&em->bm->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&em->bm->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&em->bm->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
- CustomData_copy(&em->bm->pdata, &bm_new->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
+ CustomData_copy(&bm_old->pdata, &bm_new->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
CustomData_bmesh_init_pool(&bm_new->vdata, bm_mesh_allocsize_default.totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_new->edata, bm_mesh_allocsize_default.totedge, BM_EDGE);
CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
-
- basenew = ED_object_add_duplicate(bmain, scene, editbase, USER_DUP_MESH);
+
+ base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
/* DAG_scene_sort(bmain, scene); */ /* normally would call directly after but in this case delay recalc */
- assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
+ assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
- ED_base_object_select(basenew, BA_DESELECT);
-
- EDBM_op_callf(em, wmop, "duplicate geom=%hvef dest=%p", BM_ELEM_SELECT, bm_new);
- EDBM_op_callf(em, wmop, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_FACES);
+ ED_base_object_select(base_new, BA_SELECT);
+
+ BMO_op_callf(bm_old, "duplicate geom=%hvef dest=%p", BM_ELEM_SELECT, bm_new);
+ BMO_op_callf(bm_old, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_FACES);
/* clean up any loose edges */
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH (e, &iter, bm_old, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN))
continue;
if (!BM_edge_is_wire(e)) {
- BM_edge_select_set(em->bm, e, FALSE);
+ BM_edge_select_set(bm_old, e, FALSE);
}
}
- EDBM_op_callf(em, wmop, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_EDGES);
+ BMO_op_callf(bm_old, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_EDGES);
/* clean up any loose verts */
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, bm_old, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(v, BM_ELEM_HIDDEN))
continue;
if (BM_vert_edge_count(v) != 0) {
- BM_vert_select_set(em->bm, v, FALSE);
+ BM_vert_select_set(bm_old, v, FALSE);
}
}
- EDBM_op_callf(em, wmop, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_VERTS);
+ BMO_op_callf(bm_old, "delete geom=%hvef context=%i", BM_ELEM_SELECT, DEL_VERTS);
BM_mesh_normals_update(bm_new, TRUE);
- BM_mesh_bm_to_me(bm_new, basenew->object->data, FALSE);
-
+ BM_mesh_bm_to_me(bm_new, base_new->object->data, FALSE);
+
BM_mesh_free(bm_new);
- ((Mesh *)basenew->object->data)->edit_btmesh = NULL;
+ ((Mesh *)base_new->object->data)->edit_btmesh = NULL;
return TRUE;
}
-static int mesh_separate_material(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
+static int mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
int result = FALSE;
- Object *obedit = editbase->object;
- BMEditMesh *em = BMEdit_FromObject(obedit);
- BMesh *bm = em->bm;
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
- while ((f_cmp = BM_iter_at_index(bm, BM_FACES_OF_MESH, NULL, 0))) {
+ while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
const short mat_nr = f_cmp->mat_nr;
int tot = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) {
if (f->mat_nr == mat_nr) {
- BM_face_select_set(bm, f, TRUE);
+ BM_face_select_set(bm_old, f, TRUE);
tot++;
}
}
/* leave the current object with some materials */
- if (tot == bm->totface) {
+ if (tot == bm_old->totface) {
break;
}
/* Move selection into a separate object */
- result |= mesh_separate_selected(bmain, scene, editbase, wmop);
+ result |= mesh_separate_selected(bmain, scene, base_old, bm_old);
}
return result;
}
-static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOperator *wmop)
+static int mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
BMVert *v_seed;
BMWalker walker;
int result = FALSE;
- Object *obedit = editbase->object;
- BMEditMesh *em = BMEdit_FromObject(obedit);
- BMesh *bm = em->bm;
- int max_iter = bm->totvert;
+ int max_iter = bm_old->totvert;
/* Clear all selected vertices */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE);
/* A "while (true)" loop should work here as each iteration should
* select and remove at least one vertex and when all vertices
@@ -2913,7 +2902,7 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOper
* original mesh.*/
for (i = 0; i < max_iter; i++) {
/* Get a seed vertex to start the walk */
- v_seed = BM_iter_at_index(bm, BM_VERTS_OF_MESH, NULL, 0);
+ v_seed = BM_iter_at_index(bm_old, BM_VERTS_OF_MESH, NULL, 0);
/* No vertices available, can't do anything */
if (v_seed == NULL) {
@@ -2921,33 +2910,33 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *editbase, wmOper
}
/* Select the seed explicitly, in case it has no edges */
- BM_vert_select_set(bm, v_seed, TRUE);
+ BM_vert_select_set(bm_old, v_seed, TRUE);
/* Walk from the single vertex, selecting everything connected
* to it */
- BMW_init(&walker, bm, BMW_SHELL,
+ BMW_init(&walker, bm_old, BMW_SHELL,
BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP,
BMW_FLAG_NOP, /* BMESH_TODO - should be BMW_FLAG_TEST_HIDDEN ? */
BMW_NIL_LAY);
e = BMW_begin(&walker, v_seed);
for (; e; e = BMW_step(&walker)) {
- BM_vert_select_set(bm, e->v1, TRUE);
- BM_vert_select_set(bm, e->v2, TRUE);
+ BM_vert_select_set(bm_old, e->v1, TRUE);
+ BM_vert_select_set(bm_old, e->v2, TRUE);
}
BMW_end(&walker);
-
+
/* Flush the selection to get edge/face selections matching
* the vertex selection */
- EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX);
+ BM_mesh_select_mode_flush_ex(bm_old, SCE_SELECT_VERTEX);
- if (bm->totvert == bm->totvertsel) {
+ if (bm_old->totvert == bm_old->totvertsel) {
/* Every vertex selected, nothing to separate, work is done */
break;
}
/* Move selection into a separate object */
- result |= mesh_separate_selected(bmain, scene, editbase, wmop);
+ result |= mesh_separate_selected(bmain, scene, base_old, bm_old);
}
return result;
@@ -2957,24 +2946,66 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Base *base = CTX_data_active_base(C);
int retval = 0, type = RNA_enum_get(op->ptr, "type");
- if (type == 0)
- retval = mesh_separate_selected(bmain, scene, base, op);
- else if (type == 1)
- retval = mesh_separate_material(bmain, scene, base, op);
- else if (type == 2)
- retval = mesh_separate_loose(bmain, scene, base, op);
-
- if (retval) {
+ if (ED_operator_editmesh(C)) {
+ Base *base = CTX_data_active_base(C);
BMEditMesh *em = BMEdit_FromObject(base->object);
+ /* editmode separate */
+ if (type == 0) retval = mesh_separate_selected(bmain, scene, base, em->bm);
+ else if (type == 1) retval = mesh_separate_material(bmain, scene, base, em->bm);
+ else if (type == 2) retval = mesh_separate_loose(bmain, scene, base, em->bm);
+ else BLI_assert(0);
+
+ if (retval) {
+ EDBM_update_generic(C, em, TRUE);
+ }
+ }
+ else {
+ if (type == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Selecton not supported in object mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* object mode separate */
+ CTX_DATA_BEGIN(C, Base *, base_iter, selected_editable_bases)
+ {
+ Object *ob = base_iter->object;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ if (me->id.lib == NULL) {
+ BMesh *bm_old = NULL;
+ int retval_iter = 0;
+
+ bm_old = BM_mesh_create(&bm_mesh_allocsize_default);
+
+ BM_mesh_bm_from_me(bm_old, me, FALSE, 0);
+
+ if (type == 1) retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
+ else if (type == 2) retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
+ else BLI_assert(0);
+
+ if (retval_iter) {
+ BM_mesh_bm_to_me(bm_old, me, FALSE);
+
+ DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
+
+ BM_mesh_free(bm_old);
+
+ retval |= retval_iter;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ if (retval) {
/* delay depsgraph recalc until all objects are duplicated */
DAG_scene_sort(bmain, scene);
- EDBM_update_generic(C, em, TRUE);
-
return OPERATOR_FINISHED;
}
@@ -3000,7 +3031,7 @@ void MESH_OT_separate(wmOperatorType *ot)
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = edbm_separate_exec;
- ot->poll = ED_operator_editmesh;
+ ot->poll = ED_operator_scene_editable; /* object and editmode */
/* flags */
ot->flag = OPTYPE_UNDO;
@@ -5106,7 +5137,7 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMOperator bmop;
-
+
EDBM_op_init(em, &bmop, op, "convex_hull input=%hvef "
"use_existing_faces=%b",
BM_ELEM_SELECT,