Multi-Object Editing

This adds initial multi-object editing support.

- Selected objects are used when entering edit & pose modes.
- Selection & tools work on all objects however many tools need porting
  See: T54641 for remaining tasks.

Indentation will be done separately.

See patch: D3101
This commit is contained in:
2018-04-16 16:27:55 +02:00
parent 80bb4254c6
commit bfc9d426bb
58 changed files with 3786 additions and 1486 deletions

View File

@@ -93,7 +93,14 @@
static int edbm_subdivide_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cuts = RNA_int_get(op->ptr, "number_cuts");
float smooth = RNA_float_get(op->ptr, "smoothness");
@@ -116,6 +123,9 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
RNA_int_get(op->ptr, "seed"));
EDBM_update_generic(em, true, true);
}
MEM_SAFE_FREE(objects);
return OPERATOR_FINISHED;
}
@@ -367,16 +377,22 @@ enum {
MESH_DELETE_ONLY_FACE = 4,
};
static void edbm_report_delete_info(ReportList *reports, BMesh *bm, const int totelem[3])
static void edbm_report_delete_info(ReportList *reports, const int totelem_old[3], const int totelem_new[3])
{
BKE_reportf(reports, RPT_INFO,
"Removed: %d vertices, %d edges, %d faces",
totelem[0] - bm->totvert, totelem[1] - bm->totedge, totelem[2] - bm->totface);
totelem_old[0] - totelem_new[0], totelem_old[1] - totelem_new[1], totelem_old[2] - totelem_new[2]);
}
static int edbm_delete_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int type = RNA_enum_get(op->ptr, "type");
@@ -412,6 +428,8 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, true);
} /* objects */
return OPERATOR_FINISHED;
}
@@ -467,18 +485,26 @@ static bool bm_face_is_loose(BMFace *f)
static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
int totelem_old_sel[3];
int totelem_old[3];
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel);
const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]);
const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]);
const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMIter iter;
const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && bm->totvertsel);
const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && bm->totedgesel);
const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && bm->totfacesel);
const int totelem[3] = {bm->totvert, bm->totedge, bm->totface};
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
if (use_faces) {
@@ -520,8 +546,14 @@ static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
}
edbm_report_delete_info(op->reports, bm, totelem);
int totelem_new[3];
EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL);
edbm_report_delete_info(op->reports, totelem_old, totelem_new);
MEM_SAFE_FREE(objects);
return OPERATOR_FINISHED;
}
@@ -4096,11 +4128,18 @@ void MESH_OT_poke(wmOperatorType *ot)
static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMOperator bmop;
const int quad_method = RNA_enum_get(op->ptr, "quad_method");
const int ngon_method = RNA_enum_get(op->ptr, "ngon_method");
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMOperator bmop;
BMOIter oiter;
BMFace *f;
@@ -4117,11 +4156,15 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
// XXX, TODO
#if 0
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}
#endif
EDBM_update_generic(em, true, true);
}
return OPERATOR_FINISHED;
}
@@ -4155,7 +4198,22 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
bool is_face_pair;
{
int totelem_sel[3];
EDBM_mesh_stats_multi(objects, objects_len, NULL, totelem_sel);
is_face_pair = (totelem_sel[2] == 2);
}
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
float angle_face_threshold, angle_shape_threshold;
@@ -4164,7 +4222,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
/* When joining exactly 2 faces, no limit.
* this is useful for one off joins while editing. */
prop = RNA_struct_find_property(op->ptr, "face_threshold");
if ((em->bm->totfacesel == 2) &&
if (is_face_pair &&
(RNA_property_is_set(op->ptr, prop) == false))
{
angle_face_threshold = DEG2RADF(180.0f);
@@ -4174,7 +4232,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
}
prop = RNA_struct_find_property(op->ptr, "shape_threshold");
if ((em->bm->totfacesel == 2) &&
if (is_face_pair &&
(RNA_property_is_set(op->ptr, prop) == false))
{
angle_shape_threshold = DEG2RADF(180.0f);
@@ -4197,10 +4255,11 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold,
do_seam, do_sharp, do_uvs, do_vcols, do_materials))
{
return OPERATOR_CANCELLED;
continue;
}
EDBM_update_generic(em, true, true);
}
return OPERATOR_FINISHED;
}
@@ -4727,11 +4786,28 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
ViewLayer *view_layer = CTX_data_view_layer(C);
int totelem_old[3] = {0, 0, 0};
int totelem_new[3] = {0, 0, 0};
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
totelem_old[0] += bm->totvert;
totelem_old[1] += bm->totedge;
totelem_old[2] += bm->totface;
} /* objects */
const float thresh = RNA_float_get(op->ptr, "threshold");
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const int totelem[3] = {bm->totvert, bm->totedge, bm->totface};
if (!EDBM_op_callf(
em, op,
@@ -4746,7 +4822,12 @@ static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
EDBM_update_generic(em, true, true);
edbm_report_delete_info(op->reports, bm, totelem);
totelem_new[0] += bm->totvert;
totelem_new[1] += bm->totedge;
totelem_new[2] += bm->totface;
}
edbm_report_delete_info(op->reports, totelem_old, totelem_new);
return OPERATOR_FINISHED;
}