diff options
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r-- | source/blender/editors/object/object_add.c | 57 | ||||
-rw-r--r-- | source/blender/editors/object/object_bake_api.c | 7 | ||||
-rw-r--r-- | source/blender/editors/object/object_constraint.c | 41 | ||||
-rw-r--r-- | source/blender/editors/object/object_edit.c | 66 | ||||
-rw-r--r-- | source/blender/editors/object/object_facemap_ops.c | 128 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 131 | ||||
-rw-r--r-- | source/blender/editors/object/object_remesh.c | 4 | ||||
-rw-r--r-- | source/blender/editors/object/object_vgroup.c | 183 |
9 files changed, 374 insertions, 245 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 81b8cd70353..72180d58ecb 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1450,6 +1450,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -2647,7 +2648,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits); copy_v3_v3(ob_gpencil->rot, ob->rot); copy_v3_v3(ob_gpencil->scale, ob->scale); - BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, false, true); + BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, 1.0f, 0.0f); gpencilConverted = true; } } @@ -2783,6 +2784,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -3003,6 +3005,7 @@ static int duplicate_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); return OPERATOR_FINISHED; } @@ -3094,6 +3097,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); ED_outliner_select_sync_from_object_tag(C); return OPERATOR_FINISHED; @@ -3163,20 +3167,45 @@ static int object_join_exec(bContext *C, wmOperator *op) } } + int ret = OPERATOR_CANCELLED; if (ob->type == OB_MESH) { - return ED_mesh_join_objects_exec(C, op); - } - if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - return ED_curve_join_objects_exec(C, op); - } - if (ob->type == OB_ARMATURE) { - return ED_armature_join_objects_exec(C, op); - } - if (ob->type == OB_GPENCIL) { - return ED_gpencil_join_objects_exec(C, op); - } - - return OPERATOR_CANCELLED; + ret = ED_mesh_join_objects_exec(C, op); + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + ret = ED_curve_join_objects_exec(C, op); + } + else if (ob->type == OB_ARMATURE) { + ret = ED_armature_join_objects_exec(C, op); + } + else if (ob->type == OB_GPENCIL) { + ret = ED_gpencil_join_objects_exec(C, op); + } + + if (ret & OPERATOR_FINISHED) { + /* Even though internally failure to invert is accounted for with a fallback, + * show a warning since the result may not be what the user expects. See T80077. + * + * Failure to invert the matrix is typically caused by zero scaled axes + * (which can be caused by constraints, even if the input scale isn't zero). + * + * Internally the join functions use #invert_m4_m4_safe_ortho which creates + * an inevitable matrix from one that has one or more degenerate axes. + * + * In most cases we don't worry about special handling for non-inevitable matrices however for + * joining objects there may be flat 2D objects where it's not obvious the scale is zero. + * In this case, using #invert_m4_m4_safe_ortho works as well as we can expect, + * joining the contents, flattening on the axis that's zero scaled. + * If the zero scale is removed, the data on this axis remains un-scaled + * (something that wouldn't work for #invert_m4_m4_safe). */ + float imat_test[4][4]; + if (!invert_m4_m4(imat_test, ob->obmat)) { + BKE_report(op->reports, + RPT_WARNING, + "Active object final transform has one or more zero scaled axes"); + } + } + + return ret; } void OBJECT_OT_join(wmOperatorType *ot) diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index cb92fab3cb0..4d55aff1d1f 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -745,7 +745,7 @@ static int bake(Render *re, /* We build a depsgraph for the baking, * so we don't need to change the original data to adjust visibility and modifiers. */ Depsgraph *depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER); - DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer); + DEG_graph_build_from_view_layer(depsgraph); int op_result = OPERATOR_CANCELLED; bool ok = false; @@ -1596,9 +1596,8 @@ static void bake_set_props(wmOperator *op, Scene *scene) prop = RNA_struct_find_property(op->ptr, "cage_object"); if (!RNA_property_is_set(op->ptr, prop)) { - if (bake->cage_object) { - RNA_property_string_set(op->ptr, prop, bake->cage_object->id.name + 2); - } + RNA_property_string_set( + op->ptr, prop, (bake->cage_object) ? bake->cage_object->id.name + 2 : ""); } prop = RNA_struct_find_property(op->ptr, "normal_space"); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index bcb1b8afbdd..70404af6433 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -663,10 +663,13 @@ static const EnumPropertyItem constraint_owner_items[] = { {0, NULL, 0, NULL, NULL}, }; -static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) +static bool edit_constraint_poll_generic(bContext *C, + StructRNA *rna_type, + const bool is_liboverride_allowed) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type); Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C); + bConstraint *con = ptr.data; if (!ob) { CTX_wm_operator_poll_msg_set(C, "Context missing active object"); @@ -678,9 +681,11 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) return false; } - if (ID_IS_OVERRIDE_LIBRARY(ob) && ptr.data != NULL) { - CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override"); - return (((bConstraint *)ptr.data)->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0; + if (ID_IS_OVERRIDE_LIBRARY(ob) && !is_liboverride_allowed) { + if ((con == NULL) || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) != 0) { + CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from library override"); + return false; + } } return true; @@ -688,7 +693,14 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) static bool edit_constraint_poll(bContext *C) { - return edit_constraint_poll_generic(C, &RNA_Constraint); + return edit_constraint_poll_generic(C, &RNA_Constraint, false); +} + +/* Used by operators performing actions allowed also on constraints from the overridden linked + * object (not only from added 'local' ones). */ +static bool edit_constraint_liboverride_allowed_poll(bContext *C) +{ + return edit_constraint_poll_generic(C, &RNA_Constraint, true); } static void edit_constraint_properties(wmOperatorType *ot) @@ -864,7 +876,7 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot) /* callbacks */ ot->invoke = stretchto_reset_invoke; ot->exec = stretchto_reset_exec; - ot->poll = edit_constraint_poll; + ot->poll = edit_constraint_liboverride_allowed_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -919,7 +931,7 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) /* callbacks */ ot->invoke = limitdistance_reset_invoke; ot->exec = limitdistance_reset_exec; - ot->poll = edit_constraint_poll; + ot->poll = edit_constraint_liboverride_allowed_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -997,7 +1009,7 @@ void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot) /* callbacks */ ot->invoke = childof_set_inverse_invoke; ot->exec = childof_set_inverse_exec; - ot->poll = edit_constraint_poll; + ot->poll = edit_constraint_liboverride_allowed_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1046,7 +1058,7 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot) /* callbacks */ ot->invoke = childof_clear_inverse_invoke; ot->exec = childof_clear_inverse_exec; - ot->poll = edit_constraint_poll; + ot->poll = edit_constraint_liboverride_allowed_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1693,8 +1705,8 @@ void POSE_OT_constraints_clear(wmOperatorType *ot) /* callbacks */ ot->exec = pose_constraints_clear_exec; - ot->poll = - ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too? + ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected + // bones too? } static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) @@ -1942,7 +1954,8 @@ static bool get_new_constraint_target( /* perform some special operations on the target */ if (only_curve) { - /* Curve-Path option must be enabled for follow-path constraints to be able to work */ + /* Curve-Path option must be enabled for follow-path constraints to be able to work + */ Curve *cu = (Curve *)ob->data; cu->flag |= CU_PATH; } @@ -2214,8 +2227,8 @@ void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot) /* identifiers */ ot->name = "Add Constraint (with Targets)"; ot->description = - "Add a constraint to the active object, with target (where applicable) set to the selected " - "Objects/Bones"; + "Add a constraint to the active object, with target (where applicable) set to the " + "selected Objects/Bones"; ot->idname = "OBJECT_OT_constraint_add_with_targets"; /* api callbacks */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 04113f70e52..966aeed75ab 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -145,6 +145,72 @@ Object *ED_object_active_context(const bContext *C) return ob; } +/** + * Return an array of objects: + * - When in the property space, return the pinned or active object. + * - When in edit-mode/pose-mode, return an array of objects in the mode. + * - Otherwise return selected objects, + * the callers \a filter_fn needs to check of they are editable + * (assuming they need to be modified). + */ +Object **ED_object_array_in_mode_or_selected(bContext *C, + bool (*filter_fn)(Object *ob, void *user_data), + void *filter_user_data, + uint *r_objects_len) +{ + ScrArea *area = CTX_wm_area(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob_active = OBACT(view_layer); + Object **objects; + + Object *ob = NULL; + bool use_ob = true; + if (area && (area->spacetype == SPACE_PROPERTIES)) { + /* May return pinned object. */ + ob = ED_object_context(C); + } + else if (ob_active && (ob_active->mode & + (OB_MODE_ALL_PAINT | OB_MODE_ALL_SCULPT | OB_MODE_ALL_PAINT_GPENCIL))) { + /* When painting, limit to active. */ + ob = ob_active; + } + else { + /* Otherwise use full selection. */ + use_ob = false; + } + + if (use_ob) { + if ((ob != NULL) && !filter_fn(ob, filter_user_data)) { + ob = NULL; + } + *r_objects_len = (ob != NULL) ? 1 : 0; + objects = MEM_mallocN(sizeof(*objects) * *r_objects_len, __func__); + if (ob != NULL) { + objects[0] = ob; + } + } + else { + const View3D *v3d = (area && area->spacetype == SPACE_VIEW3D) ? area->spacedata.first : NULL; + /* When in a mode that supports multiple active objects, use "objects in mode" + * instead of the object's selection. */ + if ((ob_active != NULL) && (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE))) { + objects = BKE_view_layer_array_from_objects_in_mode( + view_layer, + v3d, + r_objects_len, + {.no_dup_data = true, .filter_fn = filter_fn, .filter_userdata = filter_user_data}); + } + else { + objects = BKE_view_layer_array_selected_objects( + view_layer, + v3d, + r_objects_len, + {.no_dup_data = true, .filter_fn = filter_fn, .filter_userdata = filter_user_data}); + } + } + return objects; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index 6e0376358bb..32668598df1 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "DNA_mesh_types.h" @@ -99,71 +100,61 @@ void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum) } } -static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2) +static void object_fmap_remap_edit_mode(Object *ob, const int *remap) { - if (ob->type == OB_MESH) { - Mesh *me = ob->data; + if (ob->type != OB_MESH) { + return; + } + + Mesh *me = ob->data; + if (me->edit_mesh) { + BMEditMesh *em = me->edit_mesh; + const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); - if (me->edit_mesh) { - BMEditMesh *em = me->edit_mesh; - const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); - - if (cd_fmap_offset != -1) { - BMFace *efa; - BMIter iter; - int *map; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); - - if (map) { - if (num1 != -1) { - if (*map == num1) { - *map = num2; - } - else if (*map == num2) { - *map = num1; - } - } - } + if (cd_fmap_offset != -1) { + BMFace *efa; + BMIter iter; + int *map; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (map && *map != -1) { + *map = remap[*map]; } } } } } -static void object_fmap_swap_object_mode(Object *ob, int num1, int num2) +static void object_fmap_remap_object_mode(Object *ob, const int *remap) { - if (ob->type == OB_MESH) { - Mesh *me = ob->data; + if (ob->type != OB_MESH) { + return; + } - if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { - int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP); - int i; - - if (map) { - for (i = 0; i < me->totpoly; i++) { - if (num1 != -1) { - if (map[i] == num1) { - map[i] = num2; - } - else if (map[i] == num2) { - map[i] = num1; - } - } + Mesh *me = ob->data; + if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP); + int i; + + if (map) { + for (i = 0; i < me->totpoly; i++) { + if (map[i] != -1) { + map[i] = remap[map[i]]; } } } } } -static void object_facemap_swap(Object *ob, int num1, int num2) +static void object_facemap_remap(Object *ob, const int *remap) { if (BKE_object_is_in_editmode(ob)) { - object_fmap_swap_edit_mode(ob, num1, num2); + object_fmap_remap_edit_mode(ob, remap); } else { - object_fmap_swap_object_mode(ob, num1, num2); + object_fmap_remap_object_mode(ob, remap); } } @@ -432,45 +423,46 @@ static int face_map_move_exec(bContext *C, wmOperator *op) Object *ob = ED_object_context(C); bFaceMap *fmap; int dir = RNA_enum_get(op->ptr, "direction"); - int pos1, pos2 = -1, count; fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); if (!fmap) { return OPERATOR_CANCELLED; } - count = BLI_listbase_count(&ob->fmaps); - pos1 = BLI_findindex(&ob->fmaps, fmap); + if (!fmap->prev && !fmap->next) { + return OPERATOR_CANCELLED; + } - if (dir == 1) { /*up*/ - void *prev = fmap->prev; + int pos1 = BLI_findindex(&ob->fmaps, fmap); + int pos2 = pos1 - dir; + int len = BLI_listbase_count(&ob->fmaps); + int *map = MEM_mallocN(len * sizeof(*map), __func__); - if (prev) { - pos2 = pos1 - 1; - } - else { - pos2 = count - 1; + if (!IN_RANGE(pos2, -1, len)) { + const int offset = len - dir; + for (int i = 0; i < len; i++) { + map[i] = (i + offset) % len; } + pos2 = map[pos1]; + } + else { + range_vn_i(map, len, 0); + SWAP(int, map[pos1], map[pos2]); + } - BLI_remlink(&ob->fmaps, fmap); + void *prev = fmap->prev; + void *next = fmap->next; + BLI_remlink(&ob->fmaps, fmap); + if (dir == 1) { /*up*/ BLI_insertlinkbefore(&ob->fmaps, prev, fmap); } else { /*down*/ - void *next = fmap->next; - - if (next) { - pos2 = pos1 + 1; - } - else { - pos2 = 0; - } - - BLI_remlink(&ob->fmaps, fmap); BLI_insertlinkafter(&ob->fmaps, next, fmap); } - /* iterate through mesh and substitute the indices as necessary */ - object_facemap_swap(ob, pos2, pos1); + /* Iterate through mesh and substitute the indices as necessary. */ + object_facemap_remap(ob, map); + MEM_freeN(map); ob->actfmap = pos2 + 1; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index ceb6553bdf6..14882ab8ffc 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -107,7 +107,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_object_eval_reset(ob_eval); if (ob->type == OB_MESH) { - Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + Mesh *me_eval = mesh_create_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); BKE_mesh_eval_delete(me_eval); } else if (ob->type == OB_LATTICE) { diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 732d2f6ad52..d9196425098 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -134,13 +134,11 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = CTX_data_edit_object(C); - BMVert *eve; - BMIter iter; - Nurb *nu; - BezTriple *bezt; - BPoint *bp; Object *par; - int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1; + +#define INDEX_UNSET -1 + int par1, par2, par3, par4; + par1 = par2 = par3 = par4 = INDEX_UNSET; /* we need 1 to 3 selected vertices */ @@ -165,114 +163,108 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) * objects are also up to date. */ BKE_scene_graph_update_tagged(depsgraph, bmain); - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + BMVert *eve; + BMIter iter; + int curr_index; + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, curr_index) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - if (v1 == 0) { - v1 = nr; + if (par1 == INDEX_UNSET) { + par1 = curr_index; } - else if (v2 == 0) { - v2 = nr; + else if (par2 == INDEX_UNSET) { + par2 = curr_index; } - else if (v3 == 0) { - v3 = nr; + else if (par3 == INDEX_UNSET) { + par3 = curr_index; } - else if (v4 == 0) { - v4 = nr; + else if (par4 == INDEX_UNSET) { + par4 = curr_index; } else { break; } } - nr++; } } else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) { ListBase *editnurb = object_editcurve_get(obedit); - nu = editnurb->first; - while (nu) { + for (Nurb *nu = editnurb->first; nu != NULL; nu = nu->next) { if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { + BezTriple *bezt = nu->bezt; + for (int curr_index = 0; curr_index < nu->pntsu; curr_index++, bezt++) { if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - if (v1 == 0) { - v1 = nr; + if (par1 == INDEX_UNSET) { + par1 = curr_index; } - else if (v2 == 0) { - v2 = nr; + else if (par2 == INDEX_UNSET) { + par2 = curr_index; } - else if (v3 == 0) { - v3 = nr; + else if (par3 == INDEX_UNSET) { + par3 = curr_index; } - else if (v4 == 0) { - v4 = nr; + else if (par4 == INDEX_UNSET) { + par4 = curr_index; } else { break; } } - nr++; - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { + BPoint *bp = nu->bp; + const int num_points = nu->pntsu * nu->pntsv; + for (int curr_index = 0; curr_index < num_points; curr_index++, bp++) { if (bp->f1 & SELECT) { - if (v1 == 0) { - v1 = nr; + if (par1 == INDEX_UNSET) { + par1 = curr_index; } - else if (v2 == 0) { - v2 = nr; + else if (par2 == INDEX_UNSET) { + par2 = curr_index; } - else if (v3 == 0) { - v3 = nr; + else if (par3 == INDEX_UNSET) { + par3 = curr_index; } - else if (v4 == 0) { - v4 = nr; + else if (par4 == INDEX_UNSET) { + par4 = curr_index; } else { break; } } - nr++; - bp++; } } - nu = nu->next; } } else if (obedit->type == OB_LATTICE) { Lattice *lt = obedit->data; - a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - bp = lt->editlatt->latt->def; - while (a--) { + const int num_points = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * + lt->editlatt->latt->pntsw; + BPoint *bp = lt->editlatt->latt->def; + for (int curr_index = 0; curr_index < num_points; curr_index++, bp++) { if (bp->f1 & SELECT) { - if (v1 == 0) { - v1 = nr; + if (par1 == INDEX_UNSET) { + par1 = curr_index; } - else if (v2 == 0) { - v2 = nr; + else if (par2 == INDEX_UNSET) { + par2 = curr_index; } - else if (v3 == 0) { - v3 = nr; + else if (par3 == INDEX_UNSET) { + par3 = curr_index; } - else if (v4 == 0) { - v4 = nr; + else if (par4 == INDEX_UNSET) { + par4 = curr_index; } else { break; } } - nr++; - bp++; } } - if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) { + if (par4 != INDEX_UNSET || par1 == INDEX_UNSET || (par2 != INDEX_UNSET && par3 == INDEX_UNSET)) { BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to"); return OPERATOR_CANCELLED; } @@ -289,11 +281,11 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) Object workob; ob->parent = BASACT(view_layer)->object; - if (v3) { + if (par3 != INDEX_UNSET) { ob->partype = PARVERT3; - ob->par1 = v1 - 1; - ob->par2 = v2 - 1; - ob->par3 = v3 - 1; + ob->par1 = par1; + ob->par2 = par2; + ob->par3 = par3; /* inverse parent matrix */ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); @@ -301,7 +293,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } else { ob->partype = PARVERT1; - ob->par1 = v1 - 1; + ob->par1 = par1; /* inverse parent matrix */ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob); @@ -317,6 +309,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT, NULL); return OPERATOR_FINISHED; + +#undef INDEX_UNSET } void OBJECT_OT_vertex_parent_set(wmOperatorType *ot) @@ -1474,7 +1468,8 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) /* redraw the 3D view because the object center points are colored differently */ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); - /* one day multiple scenes will be visible, then we should have some update function for them */ + /* one day multiple scenes will be visible, then we should have some update function for them + */ return OPERATOR_FINISHED; } @@ -1794,9 +1789,9 @@ static Collection *single_object_users_collection(Main *bmain, if (is_master_collection && copy_collections && child->collection != collection_child_new) { /* We do not want a collection sync here, our collections are in a complete uninitialized - * state currently. With current code, that would lead to a memory leak - because of reasons. - * It would be a useless loss of computing anyway, since caller has to fully refresh - * view-layers/collections caching at the end. */ + * state currently. With current code, that would lead to a memory leak - because of + * reasons. It would be a useless loss of computing anyway, since caller has to fully + * refresh view-layers/collections caching at the end. */ BKE_collection_child_add_no_sync(collection, collection_child_new); BLI_remlink(&collection->children, child); MEM_freeN(child); diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 8d8f01dd61a..f14c734da4e 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -294,7 +294,7 @@ static void voxel_size_edit_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), { VoxelSizeEditCustomData *cd = arg; - GPU_blend(true); + GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); uint pos3d = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); @@ -363,7 +363,7 @@ static void voxel_size_edit_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), GPU_matrix_pop(); - GPU_blend(false); + GPU_blend(GPU_BLEND_NONE); GPU_line_smooth(false); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 253287c382e..de9cca38a6e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -72,15 +72,32 @@ #include "ED_mesh.h" #include "ED_object.h" +#include "ED_screen.h" #include "UI_resources.h" #include "object_intern.h" +static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob); + /* -------------------------------------------------------------------- */ -/** \name Public Utility Functions +/** \name Local Utility Functions * \{ */ +static bool object_array_for_wpaint_filter(Object *ob, void *user_data) +{ + bContext *C = user_data; + if (vertex_group_supported_poll_ex(C, ob)) { + return true; + } + return false; +} + +static Object **object_array_for_wpaint(bContext *C, uint *r_objects_len) +{ + return ED_object_array_in_mode_or_selected(C, object_array_for_wpaint_filter, C, r_objects_len); +} + static bool vertex_group_use_vert_sel(Object *ob) { if (ob->mode == OB_MODE_EDIT) { @@ -100,6 +117,12 @@ static Lattice *vgroup_edit_lattice(Object *ob) return (lt->editlatt) ? lt->editlatt->latt : lt; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Utility Functions + * \{ */ + bool ED_vgroup_sync_from_pose(Object *ob) { Object *armobj = BKE_object_pose_armature_get(ob); @@ -2407,7 +2430,7 @@ void ED_vgroup_mirror(Object *ob, goto cleanup; } - EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology); + EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology); BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); @@ -2659,14 +2682,21 @@ static void vgroup_assign_verts(Object *ob, const float weight) /** \name Shared Operator Poll Functions * \{ */ +static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob) +{ + if (!ED_operator_object_active_local_editable_ex(C, ob)) { + return false; + } + const ID *data = ob->data; + return (OB_TYPE_SUPPORT_VGROUP(ob->type) && + /* Data checks. */ + (data != NULL) && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); +} + static bool vertex_group_supported_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - - return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && - !ID_IS_OVERRIDE_LIBRARY(ob) && data && !ID_IS_LINKED(data) && - !ID_IS_OVERRIDE_LIBRARY(data)); + return vertex_group_supported_poll_ex(C, ob); } static bool vertex_group_poll(bContext *C) @@ -3077,6 +3107,12 @@ void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy Operator + * \{ */ + static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -3090,12 +3126,6 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Group Copy Operator - * \{ */ - void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) { /* identifiers */ @@ -3111,6 +3141,12 @@ void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Levels Operator + * \{ */ + static int vertex_group_levels_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3133,12 +3169,6 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Group Levels Operator - * \{ */ - void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) { /* identifiers */ @@ -3161,6 +3191,12 @@ void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize Operator + * \{ */ + static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -3178,12 +3214,6 @@ static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Group Normalize Operator - * \{ */ - void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot) { /* identifiers */ @@ -3200,6 +3230,12 @@ void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize All Operator + * \{ */ + static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3226,12 +3262,6 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Vertex Group Normalize All Operator - * \{ */ - void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) { /* identifiers */ @@ -3512,22 +3542,11 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op) { const float fac = RNA_float_get(op->ptr, "factor"); const int repeat = RNA_int_get(op->ptr, "repeat"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); const float fac_expand = RNA_float_get(op->ptr, "expand"); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob_ctx = ED_object_context(C); uint objects_len; - Object **objects; - if (ob_ctx->mode == OB_MODE_WEIGHT_PAINT) { - /* Until weight paint supports multi-edit, use only the active. */ - objects_len = 1; - objects = &ob_ctx; - } - else { - objects = BKE_view_layer_array_from_objects_in_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode); - } + Object **objects = object_array_for_wpaint(C, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; @@ -3544,9 +3563,7 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } - if (objects != &ob_ctx) { - MEM_freeN(objects); - } + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3588,22 +3605,29 @@ void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot) static int vertex_group_clean_exec(bContext *C, wmOperator *op) { - Object *ob = ED_object_context(C); + const float limit = RNA_float_get(op->ptr, "limit"); + const bool keep_single = RNA_boolean_get(op->ptr, "keep_single"); + const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); - float limit = RNA_float_get(op->ptr, "limit"); - bool keep_single = RNA_boolean_get(op->ptr, "keep_single"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + uint objects_len; + Object **objects = object_array_for_wpaint(C, &objects_len); - int subset_count, vgroup_tot; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; - const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type( - ob, subset_type, &vgroup_tot, &subset_count); - vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single); - MEM_freeN((void *)vgroup_validmap); + int subset_count, vgroup_tot; - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type( + ob, subset_type, &vgroup_tot, &subset_count); + + vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single); + MEM_freeN((void *)vgroup_validmap); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + } + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3611,7 +3635,7 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op) void OBJECT_OT_vertex_group_clean(wmOperatorType *ot) { /* identifiers */ - ot->name = "Clean Vertex Group"; + ot->name = "Clean Vertex Group Weights"; ot->idname = "OBJECT_OT_vertex_group_clean"; ot->description = "Remove vertex group assignments which are not required"; @@ -3692,25 +3716,36 @@ void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot) static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) { - Object *ob = ED_object_context(C); - const int limit = RNA_int_get(op->ptr, "limit"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + int remove_multi_count = 0; - int subset_count, vgroup_tot; + uint objects_len; + Object **objects = object_array_for_wpaint(C, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; - const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type( - ob, subset_type, &vgroup_tot, &subset_count); - int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit); - MEM_freeN((void *)vgroup_validmap); + int subset_count, vgroup_tot; + const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type( + ob, subset_type, &vgroup_tot, &subset_count); + const int remove_count = vgroup_limit_total_subset( + ob, vgroup_validmap, vgroup_tot, subset_count, limit); + MEM_freeN((void *)vgroup_validmap); - BKE_reportf( - op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot); + if (remove_count != 0) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + } + remove_multi_count += remove_count; + } + MEM_freeN(objects); - if (remove_tot) { - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + if (remove_multi_count) { + BKE_reportf(op->reports, + remove_multi_count ? RPT_INFO : RPT_WARNING, + "%d vertex weights limited", + remove_multi_count); return OPERATOR_FINISHED; } |