diff options
Diffstat (limited to 'source/blender/editors/object')
21 files changed, 969 insertions, 578 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 97376a495c1..17365cc5488 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC ../../shader_fx ../../windowmanager ../../../../intern/clog - ../../../../intern/glew-mx ../../../../intern/guardedalloc # dna_type_offsets.h in BLO_read_write.h @@ -53,7 +52,7 @@ set(SRC object_shapekey.c object_transform.cc object_utils.c - object_vgroup.c + object_vgroup.cc object_volume.c object_warp.c @@ -76,7 +75,6 @@ endif() if(WITH_EXPERIMENTAL_FEATURES) add_definitions(-DWITH_SIMULATION_DATABLOCK) add_definitions(-DWITH_POINT_CLOUD) - add_definitions(-DWITH_NEW_CURVES_TYPE) endif() blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 041a1383b28..1068da6816f 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -24,6 +24,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_fluidsim_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" @@ -36,6 +37,7 @@ #include "BLI_math.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" #include "BLT_translation.h" @@ -71,6 +73,7 @@ #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_nla.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcloud.h" @@ -113,6 +116,10 @@ #include "object_intern.h" +using blender::float3; +using blender::float4x4; +using blender::Vector; + /* -------------------------------------------------------------------- */ /** \name Local Enum Declarations * \{ */ @@ -602,7 +609,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit != nullptr) { ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } @@ -622,7 +629,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, ob = BKE_object_add(bmain, view_layer, type, name); } - Base *ob_base_act = BASACT(view_layer); + Base *ob_base_act = view_layer->basact; /* While not getting a valid base is not a good thing, it can happen in convoluted corner cases, * better not crash on it in releases. */ BLI_assert(ob_base_act != nullptr); @@ -650,8 +657,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - /* TODO(sergey): Use proper flag for tagging here. */ - DEG_id_tag_update(&scene->id, 0); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); ED_outliner_select_sync_from_object_tag(C); @@ -984,7 +990,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } bool newob = false; - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit == nullptr || obedit->type != OB_MBALL) { obedit = ED_object_add_type(C, OB_MBALL, nullptr, loc, rot, true, local_view_bits); newob = true; @@ -1093,7 +1099,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; @@ -1328,21 +1334,21 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) const char *ob_name = nullptr; switch (type) { case GP_EMPTY: { - ob_name = "GPencil"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "GPencil"); break; } case GP_MONKEY: { - ob_name = "Suzanne"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Suzanne"); break; } case GP_STROKE: { - ob_name = "Stroke"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Stroke"); break; } case GP_LRT_OBJECT: case GP_LRT_SCENE: case GP_LRT_COLLECTION: { - ob_name = "Line Art"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "LineArt"); break; } default: { @@ -1984,7 +1990,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) AnimData *adt = BKE_animdata_ensure_id(&ob->id); NlaTrack *nlt = BKE_nlatrack_add(adt, nullptr, is_liboverride); NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, static_cast<Speaker *>(ob->data)); - strip->start = CFRA; + strip->start = scene->r.cfra; strip->end += strip->start; /* hook them up */ @@ -2023,14 +2029,6 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot) /** \name Add Curves Operator * \{ */ -static bool object_curves_add_poll(bContext *C) -{ - if (!U.experimental.use_new_curves_type) { - return false; - } - return ED_operator_objectmode(C); -} - static int object_curves_random_add_exec(bContext *C, wmOperator *op) { using namespace blender; @@ -2043,7 +2041,6 @@ static int object_curves_random_add_exec(bContext *C, wmOperator *op) } Object *object = ED_object_add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits); - object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ Curves *curves_id = static_cast<Curves *>(object->data); bke::CurvesGeometry::wrap(curves_id->geometry) = ed::curves::primitive_random_sphere(500, 8); @@ -2060,7 +2057,7 @@ void OBJECT_OT_curves_random_add(wmOperatorType *ot) /* api callbacks */ ot->exec = object_curves_random_add_exec; - ot->poll = object_curves_add_poll; + ot->poll = ED_operator_objectmode; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2070,38 +2067,48 @@ void OBJECT_OT_curves_random_add(wmOperatorType *ot) static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); + ushort local_view_bits; - float loc[3], rot[3]; if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { + C, op, 'Z', nullptr, nullptr, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } Object *surface_ob = CTX_data_active_object(C); + BLI_assert(surface_ob != nullptr); - Object *object = ED_object_add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits); - object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ + Object *curves_ob = ED_object_add_type( + C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits); + BKE_object_apply_mat4(curves_ob, surface_ob->obmat, false, false); - if (surface_ob != nullptr && surface_ob->type == OB_MESH) { - Curves *curves_id = static_cast<Curves *>(object->data); - curves_id->surface = surface_ob; - id_us_plus(&surface_ob->id); + /* Set surface object. */ + Curves *curves_id = static_cast<Curves *>(curves_ob->data); + curves_id->surface = surface_ob; - Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data); - const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_MLOOPUV); - if (uv_name != nullptr) { - curves_id->surface_uv_map = BLI_strdup(uv_name); - } + /* Parent to surface object. */ + ED_object_parent_set( + op->reports, C, scene, curves_ob, surface_ob, PAR_OBJECT, false, true, nullptr); + + /* Decide which UV map to use for attachment. */ + Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data); + const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_MLOOPUV); + if (uv_name != nullptr) { + curves_id->surface_uv_map = BLI_strdup(uv_name); } + /* Add deformation modifier. */ + blender::ed::curves::ensure_surface_deformation_node_exists(*C, *curves_ob); + + /* Make sure the surface object has a rest position attribute which is necessary for + * deformations. */ + surface_ob->modifier_flag |= OB_MODIFIER_FLAG_ADD_REST_POSITION; + return OPERATOR_FINISHED; } static bool object_curves_empty_hair_add_poll(bContext *C) { - if (!U.experimental.use_new_curves_type) { - return false; - } if (!ED_operator_objectmode(C)) { return false; } @@ -2763,47 +2770,6 @@ static const EnumPropertyItem convert_target_items[] = { {0, nullptr, 0, nullptr, nullptr}, }; -static const EnumPropertyItem *convert_target_items_fn(bContext *UNUSED(C), - PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), - bool *r_free) -{ - EnumPropertyItem *items = nullptr; - int items_num = 0; - for (const EnumPropertyItem *item = convert_target_items; item->identifier != nullptr; item++) { - if (item->value == OB_CURVES) { - if (U.experimental.use_new_curves_type) { - RNA_enum_item_add(&items, &items_num, item); - } - } - else { - RNA_enum_item_add(&items, &items_num, item); - } - } - RNA_enum_item_end(&items, &items_num); - *r_free = true; - return items; -} - -static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) -{ - if (ob->runtime.curve_cache == nullptr) { - /* Force creation. This is normally not needed but on operator - * redo we might end up with an object which isn't evaluated yet. - * Also happens in case we are working on a copy of the object - * (all its caches have been nuked then). - */ - if (ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY, OB_FONT)) { - /* We need 'for render' ON here, to enable computing bevel #DispList if needed. - * Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true); - } - else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(depsgraph, scene, ob); - } - } -} - static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); @@ -2922,7 +2888,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) const bool use_faces = RNA_boolean_get(op->ptr, "faces"); const float offset = RNA_float_get(op->ptr, "offset"); - int a, mballConverted = 0; + int mballConverted = 0; bool gpencilConverted = false; bool gpencilCurveConverted = false; @@ -3192,9 +3158,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } /* Anonymous attributes shouldn't be available on the applied geometry. */ - MeshComponent component; - component.replace(new_mesh, GeometryOwnershipType::Editable); - component.attributes_remove_anonymous(); + new_mesh->attributes_for_write().remove_anonymous(); BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ } @@ -3272,7 +3236,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ object_data_convert_curve_to_mesh(bmain, depsgraph, newob); - /* meshes doesn't use displist */ + /* Meshes doesn't use the "curve cache". */ BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { @@ -3307,7 +3271,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ object_data_convert_curve_to_mesh(bmain, depsgraph, newob); - /* meshes doesn't use displist */ + /* Meshes don't use the "curve cache". */ BKE_object_free_curve_cache(newob); } else if (target == OB_GPENCIL) { @@ -3348,21 +3312,13 @@ static int object_convert_exec(bContext *C, wmOperator *op) MetaBall *mb = static_cast<MetaBall *>(newob->data); id_us_min(&mb->id); - newob->data = BKE_mesh_add(bmain, "Mesh"); - newob->type = OB_MESH; + /* Find the evaluated mesh of the basis metaball object. */ + Object *object_eval = DEG_get_evaluated_object(depsgraph, baseob); + Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true); - Mesh *me = static_cast<Mesh *>(newob->data); - me->totcol = mb->totcol; - if (newob->totcol) { - me->mat = static_cast<Material **>(MEM_dupallocN(mb->mat)); - for (a = 0; a < newob->totcol; a++) { - id_us_plus((ID *)me->mat[a]); - } - } - - object_data_convert_ensure_curve_cache(depsgraph, scene, baseob); - BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, - static_cast<Mesh *>(newob->data)); + id_us_plus(&mesh->id); + newob->data = mesh; + newob->type = OB_MESH; if (obact->type == OB_MBALL) { basact = basen; @@ -3411,7 +3367,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* If the original object is active then make this object active */ if (basen) { if (ob == obact) { - /* store new active base to update BASACT */ + /* Store new active base to update view layer. */ basact = basen; } @@ -3485,11 +3441,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) if (basact) { /* active base was changed */ ED_object_base_activate(C, basact); - BASACT(view_layer) = basact; + view_layer->basact = basact; } - else if (BASACT(view_layer)->object->flag & OB_DONE) { - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object); + else if (view_layer->basact->object->flag & OB_DONE) { + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, view_layer->basact->object); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, view_layer->basact->object); } DEG_relations_tag_update(bmain); @@ -3544,7 +3500,6 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum( ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to"); - RNA_def_enum_funcs(ot->prop, convert_target_items_fn); RNA_def_boolean(ot->srna, "keep_original", false, @@ -3600,7 +3555,8 @@ static Base *object_add_duplicate_internal(Main *bmain, ViewLayer *view_layer, Object *ob, const eDupli_ID_Flags dupflag, - const eLibIDDuplicateFlags duplicate_options) + const eLibIDDuplicateFlags duplicate_options, + Object **r_ob_new) { Base *base, *basen = nullptr; Object *obn; @@ -3611,6 +3567,9 @@ static Base *object_add_duplicate_internal(Main *bmain, else { obn = static_cast<Object *>( ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); + if (r_ob_new) { + *r_ob_new = obn; + } DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); base = BKE_view_layer_base_find(view_layer, ob); @@ -3623,7 +3582,7 @@ static Base *object_add_duplicate_internal(Main *bmain, } basen = BKE_view_layer_base_find(view_layer, obn); - if (base != nullptr) { + if (base != nullptr && basen != nullptr) { basen->local_view_bits = base->local_view_bits; } @@ -3654,7 +3613,8 @@ Base *ED_object_add_duplicate( base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS | - LIB_ID_DUPLICATE_IS_ROOT_ID); + LIB_ID_DUPLICATE_IS_ROOT_ID, + nullptr); if (basen == nullptr) { return nullptr; } @@ -3687,46 +3647,75 @@ static int duplicate_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag; - bool changed = false; /* We need to handle that here ourselves, because we may duplicate several objects, in which case * we also want to remap pointers between those... */ BKE_main_id_newptr_and_tag_clear(bmain); - CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, - scene, - view_layer, - base->object, - dupflag, - LIB_ID_DUPLICATE_IS_SUBPROCESS | - LIB_ID_DUPLICATE_IS_ROOT_ID); + /* Do not do collection re-syncs for each object; will do it once afterwards. + * However this means we can't get to new duplicated Base's immediately, will + * have to process them after the sync. */ + BKE_layer_collection_resync_forbid(); - /* note that this is safe to do with this context iterator, - * the list is made in advance */ - ED_object_base_select(base, BA_DESELECT); - ED_object_base_select(basen, BA_SELECT); - changed = true; + /* Duplicate the selected objects, remember data needed to process + * after the sync (the base of the original object, and the copy of the + * original object). */ + blender::Vector<std::pair<Base *, Object *>> source_bases_new_objects; + Object *ob_new_active = nullptr; - if (basen == nullptr) { + CTX_DATA_BEGIN (C, Base *, base, selected_bases) { + Object *ob_new = nullptr; + object_add_duplicate_internal(bmain, + scene, + view_layer, + base->object, + dupflag, + LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID, + &ob_new); + if (ob_new == nullptr) { continue; } + source_bases_new_objects.append({base, ob_new}); - /* new object becomes active */ - if (BASACT(view_layer) == base) { - ED_object_base_activate(C, basen); - } + /* note that this is safe to do with this context iterator, + * the list is made in advance */ + ED_object_base_select(base, BA_DESELECT); - if (basen->object->data) { - DEG_id_tag_update(static_cast<ID *>(basen->object->data), 0); + /* new object will become active */ + if (view_layer->basact == base) { + ob_new_active = ob_new; } } CTX_DATA_END; + BKE_layer_collection_resync_allow(); - if (!changed) { + if (source_bases_new_objects.is_empty()) { return OPERATOR_CANCELLED; } + /* Sync the collection now, after everything is duplicated. */ + BKE_main_collection_sync(bmain); + + /* After sync we can get to the new Base data, process it here. */ + for (const auto &item : source_bases_new_objects) { + Object *ob_new = item.second; + Base *base_source = item.first; + Base *base_new = BKE_view_layer_base_find(view_layer, ob_new); + if (base_new == nullptr) { + continue; + } + ED_object_base_select(base_new, BA_SELECT); + if (ob_new == ob_new_active) { + ED_object_base_activate(C, base_new); + } + if (base_new->object->data) { + DEG_id_tag_update(static_cast<ID *>(base_new->object->data), 0); + } + /* #object_add_duplicate_internal will not have done this, since + * before the collection sync it would not have found the new base yet. */ + base_new->local_view_bits = base_source->local_view_bits; + } + /* Note that this will also clear newid pointers and tags. */ copy_object_set_idnew(C); @@ -3808,7 +3797,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op) * the case here. So we have to do the new-ID relinking ourselves * (#copy_object_set_idnew()). */ - LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID); + LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID, + nullptr); if (basen == nullptr) { BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); @@ -3904,7 +3894,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_OB)); if (!ob) { - ob = OBACT(view_layer); + ob = BKE_view_layer_active_object_get(view_layer); } if (ob == nullptr) { @@ -3976,7 +3966,7 @@ void OBJECT_OT_transform_to_mouse(wmOperatorType *ot) /* api callbacks */ ot->invoke = object_add_drop_xy_generic_invoke; ot->exec = object_transform_to_mouse_exec; - ot->poll = ED_operator_objectmode; + ot->poll = ED_operator_objectmode_poll_msg; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index effbde41c38..8d505bbca3e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -155,15 +155,16 @@ static bool multiresbake_check(bContext *C, wmOperator *op) break; } - if (!me->mloopuv) { + if (!CustomData_has_layer(&me->ldata, CD_MLOOPUV)) { BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); ok = false; } else { + const int *material_indices = BKE_mesh_material_indices(me); a = me->totpoly; while (ok && a--) { - Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr); + Image *ima = bake_object_image_get(ob, material_indices ? material_indices[a] : 0); if (!ima) { BKE_report( diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 006379123f8..8db699cceb8 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -21,8 +21,10 @@ #include "BLI_path_util.h" #include "BLI_string.h" +#include "BKE_attribute.h" #include "BKE_callbacks.h" #include "BKE_context.h" +#include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_image_format.h" @@ -323,7 +325,7 @@ static bool write_external_bake_pixels(const char *filepath, const int height, const int margin, const int margin_type, - ImageFormatData *im_format, + ImageFormatData const *im_format, const bool is_noncolor, Mesh const *mesh_eval, char const *uv_layer, @@ -447,14 +449,11 @@ static bool bake_object_check(ViewLayer *view_layer, } if (target == R_BAKE_TARGET_VERTEX_COLORS) { - const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL); - const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); - if (mloopcol == NULL && !mcol_valid) { + if (BKE_id_attributes_active_color_get(&me->id) == NULL) { BKE_reportf(reports, RPT_ERROR, - "No vertex colors layer found in the object \"%s\"", - ob->id.name + 2); + "Mesh does not have an active color attribute \"%s\"", + me->id.name + 2); return false; } } @@ -935,23 +934,25 @@ static bool bake_targets_output_external(const BakeAPIRender *bkr, /* Vertex Color Bake Targets */ -static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, ReportList *reports) +static bool bake_targets_init_vertex_colors(Main *bmain, + BakeTargets *targets, + Object *ob, + ReportList *reports) { if (ob->type != OB_MESH) { - BKE_report( - reports, RPT_ERROR, "Vertex color baking not support with object types other than mesh"); + BKE_report(reports, RPT_ERROR, "Color attribute baking is only supported for mesh objects"); return false; } Mesh *me = ob->data; - const MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL); - const MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); - if (mloopcol == NULL && !mcol_valid) { - BKE_report(reports, RPT_ERROR, "No vertex colors layer found to bake to"); + if (BKE_id_attributes_active_color_get(&me->id) == NULL) { + BKE_report(reports, RPT_ERROR, "No active color attribute to bake to"); return false; } + /* Ensure mesh and editmesh topology are in sync. */ + ED_object_editmode_load(bmain, ob); + targets->images = MEM_callocN(sizeof(BakeImage), "BakeTargets.images"); targets->images_num = 1; @@ -970,7 +971,8 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re return true; } -static int find_original_loop(const Mesh *me_orig, +static int find_original_loop(const MPoly *orig_polys, + const MLoop *orig_loops, const int *vert_origindex, const int *poly_origindex, const int poly_eval, @@ -986,8 +988,8 @@ static int find_original_loop(const Mesh *me_orig, } /* Find matching loop with original vertex in original polygon. */ - MPoly *mpoly_orig = me_orig->mpoly + poly_orig; - MLoop *mloop_orig = me_orig->mloop + mpoly_orig->loopstart; + const MPoly *mpoly_orig = orig_polys + poly_orig; + const MLoop *mloop_orig = orig_loops + mpoly_orig->loopstart; for (int j = 0; j < mpoly_orig->totloop; ++j, ++mloop_orig) { if (mloop_orig->v == vert_orig) { return mpoly_orig->loopstart + j; @@ -997,10 +999,10 @@ static int find_original_loop(const Mesh *me_orig, return ORIGINDEX_NONE; } -static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, - Object *ob, - Mesh *me_eval, - BakePixel *pixel_array) +static void bake_targets_populate_pixels_color_attributes(BakeTargets *targets, + Object *ob, + Mesh *me_eval, + BakePixel *pixel_array) { Mesh *me = ob->data; const int pixels_num = targets->pixels_num; @@ -1024,23 +1026,31 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets, const int tottri = poly_to_tri_count(me_eval->totpoly, me_eval->totloop); MLoopTri *looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__); - BKE_mesh_recalc_looptri( - me_eval->mloop, me_eval->mpoly, me_eval->mvert, me_eval->totloop, me_eval->totpoly, looptri); + const MLoop *loops = BKE_mesh_loops(me_eval); + BKE_mesh_recalc_looptri(loops, + BKE_mesh_polys(me_eval), + BKE_mesh_verts(me_eval), + me_eval->totloop, + me_eval->totpoly, + looptri); /* For mapping back to original mesh in case there are modifiers. */ const int *vert_origindex = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); const int *poly_origindex = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); + const MPoly *orig_polys = BKE_mesh_polys(me); + const MLoop *orig_loops = BKE_mesh_loops(me); for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; for (int j = 0; j < 3; j++) { unsigned int l = lt->tri[j]; - unsigned int v = me_eval->mloop[l].v; + unsigned int v = loops[l].v; /* Map back to original loop if there are modifiers. */ if (vert_origindex != NULL && poly_origindex != NULL) { - l = find_original_loop(me, vert_origindex, poly_origindex, lt->poly, v); + l = find_original_loop( + orig_polys, orig_loops, vert_origindex, poly_origindex, lt->poly, v); if (l == ORIGINDEX_NONE || l >= me->totloop) { continue; } @@ -1095,24 +1105,46 @@ static void bake_result_add_to_rgba(float rgba[4], const float *result, const in } } +static void convert_float_color_to_byte_color(const MPropCol *float_colors, + const int num, + const bool is_noncolor, + MLoopCol *byte_colors) +{ + if (is_noncolor) { + for (int i = 0; i < num; i++) { + unit_float_to_uchar_clamp_v4(&byte_colors->r, float_colors[i].color); + } + } + else { + for (int i = 0; i < num; i++) { + linearrgb_to_srgb_uchar4(&byte_colors[i].r, float_colors[i].color); + } + } +} + static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) { Mesh *me = ob->data; - MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR); - const bool mcol_valid = (mcol != NULL); - MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_PROP_BYTE_COLOR); + BMEditMesh *em = me->edit_mesh; + CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id); + BLI_assert(active_color_layer != NULL); + const eAttrDomain domain = BKE_id_attribute_domain(&me->id, active_color_layer); + const int channels_num = targets->channels_num; + const bool is_noncolor = targets->is_noncolor; const float *result = targets->result; - if (mcol_valid) { + if (domain == ATTR_DOMAIN_POINT) { const int totvert = me->totvert; const int totloop = me->totloop; + MPropCol *mcol = MEM_malloc_arrayN(totvert, sizeof(MPropCol), __func__); + /* Accumulate float vertex colors in scene linear color space. */ int *num_loops_for_vertex = MEM_callocN(sizeof(int) * me->totvert, "num_loops_for_vertex"); memset(mcol, 0, sizeof(MPropCol) * me->totvert); - MLoop *mloop = me->mloop; + const MLoop *mloop = BKE_mesh_loops(me); for (int i = 0; i < totloop; i++, mloop++) { const int v = mloop->v; bake_result_add_to_rgba(mcol[v].color, &result[i * channels_num], channels_num); @@ -1126,24 +1158,82 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob) } } - MEM_SAFE_FREE(num_loops_for_vertex); - } - else { - /* Byte loop colors in sRGB colors space. */ - MLoop *mloop = me->mloop; - const int totloop = me->totloop; - const bool is_noncolor = targets->is_noncolor; + if (em) { + /* Copy to bmesh. */ + const int active_color_offset = CustomData_get_offset_named( + &em->bm->vdata, active_color_layer->type, active_color_layer->name); + BMVert *v; + BMIter viter; + int i = 0; + BM_ITER_MESH (v, &viter, em->bm, BM_VERTS_OF_MESH) { + void *data = BM_ELEM_CD_GET_VOID_P(v, active_color_offset); + if (active_color_layer->type == CD_PROP_COLOR) { + memcpy(data, &mcol[i], sizeof(MPropCol)); + } + else { + convert_float_color_to_byte_color(&mcol[i], 1, is_noncolor, data); + } + i++; + } + } + else { + /* Copy to mesh. */ + if (active_color_layer->type == CD_PROP_COLOR) { + memcpy(active_color_layer->data, mcol, sizeof(MPropCol) * me->totvert); + } + else { + convert_float_color_to_byte_color(mcol, totvert, is_noncolor, active_color_layer->data); + } + } - for (int i = 0; i < totloop; i++, mloop++, mloopcol++) { - float rgba[4]; - zero_v4(rgba); - bake_result_add_to_rgba(rgba, &result[i * channels_num], channels_num); + MEM_freeN(mcol); - if (is_noncolor) { - unit_float_to_uchar_clamp_v4(&mloopcol->r, rgba); + MEM_SAFE_FREE(num_loops_for_vertex); + } + else if (domain == ATTR_DOMAIN_CORNER) { + if (em) { + /* Copy to bmesh. */ + const int active_color_offset = CustomData_get_offset_named( + &em->bm->ldata, active_color_layer->type, active_color_layer->name); + BMFace *f; + BMIter fiter; + int i = 0; + BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) { + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + MPropCol color; + zero_v4(color.color); + bake_result_add_to_rgba(color.color, &result[i * channels_num], channels_num); + i++; + + void *data = BM_ELEM_CD_GET_VOID_P(l, active_color_offset); + if (active_color_layer->type == CD_PROP_COLOR) { + memcpy(data, &color, sizeof(MPropCol)); + } + else { + convert_float_color_to_byte_color(&color, 1, is_noncolor, data); + } + } + } + } + else { + /* Copy to mesh. */ + if (active_color_layer->type == CD_PROP_COLOR) { + MPropCol *colors = active_color_layer->data; + for (int i = 0; i < me->totloop; i++) { + zero_v4(colors[i].color); + bake_result_add_to_rgba(colors[i].color, &result[i * channels_num], channels_num); + } } else { - linearrgb_to_srgb_uchar4(&mloopcol->r, rgba); + MLoopCol *colors = active_color_layer->data; + for (int i = 0; i < me->totloop; i++) { + MPropCol color; + zero_v4(color.color); + bake_result_add_to_rgba(color.color, &result[i * channels_num], channels_num); + convert_float_color_to_byte_color(&color, 1, is_noncolor, &colors[i]); + } } } } @@ -1174,7 +1264,7 @@ static bool bake_targets_init(const BakeAPIRender *bkr, } } else if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) { - if (!bake_targets_init_vertex_colors(targets, ob, reports)) { + if (!bake_targets_init_vertex_colors(bkr->main, targets, ob, reports)) { return false; } } @@ -1198,7 +1288,7 @@ static void bake_targets_populate_pixels(const BakeAPIRender *bkr, BakePixel *pixel_array) { if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) { - bake_targets_populate_pixels_vertex_colors(targets, ob, me_eval, pixel_array); + bake_targets_populate_pixels_color_attributes(targets, ob, me_eval, pixel_array); } else { RE_bake_pixels_populate(me_eval, pixel_array, targets->pixels_num, targets, bkr->uv_layer); diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 39951c2ab6e..426f33e53ca 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -16,6 +16,7 @@ #include "BKE_collection.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_object.h" @@ -202,7 +203,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); int single_collection_index = RNA_enum_get(op->ptr, "collection"); Collection *single_collection = collection_object_active_find_index( bmain, scene, ob, single_collection_index); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index bf3b71178e8..28ba2b04b6f 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -50,6 +50,7 @@ #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" +#include "RNA_path.h" #include "RNA_prototypes.h" #include "ED_keyframing.h" @@ -2313,7 +2314,7 @@ static bool get_new_constraint_target( if ((found == false) && (add)) { Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + Base *base = view_layer->basact; Object *obt; /* add new target object */ @@ -2335,7 +2336,7 @@ static bool get_new_constraint_target( } /* restore, BKE_object_add sets active */ - BASACT(view_layer) = base; + view_layer->basact = base; ED_object_base_select(base, BA_SELECT); /* make our new target the new object */ diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4837b538bf6..78b059d5514 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -45,7 +45,7 @@ * Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */ /* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */ static const EnumPropertyItem DT_layer_items[] = { - RNA_ENUM_ITEM_HEADING("Vertex Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Vertex Data"), NULL), {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, @@ -61,7 +61,7 @@ static const EnumPropertyItem DT_layer_items[] = { #endif {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"}, - RNA_ENUM_ITEM_HEADING("Edge Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Edge Data"), NULL), {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"}, {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"}, {DT_TYPE_CREASE, "CREASE", 0, "Subdivision Crease", "Transfer crease values"}, @@ -72,12 +72,12 @@ static const EnumPropertyItem DT_layer_items[] = { "Freestyle Mark", "Transfer Freestyle edge mark"}, - RNA_ENUM_ITEM_HEADING("Face Corner Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Face Corner Data"), NULL), {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"}, {DT_TYPE_MPROPCOL_LOOP | DT_TYPE_MLOOPCOL_LOOP, "VCOL", 0, "Colors", "Color Attributes"}, {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"}, - RNA_ENUM_ITEM_HEADING("Face Data", NULL), + RNA_ENUM_ITEM_HEADING(N_("Face Data"), NULL), {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"}, {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index e5dd9fb2c8b..1bfb0c5f260 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -141,7 +141,7 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, { ScrArea *area = CTX_wm_area(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob_active = OBACT(view_layer); + Object *ob_active = BKE_view_layer_active_object_get(view_layer); ID *id_pin = NULL; const bool use_objects_in_mode = (ob_active != NULL) && (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE)); @@ -194,13 +194,13 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, /* When in a mode that supports multiple active objects, use "objects in mode" * instead of the object's selection. */ if (use_objects_in_mode) { - objects = BKE_view_layer_array_from_objects_in_mode(view_layer, - v3d, - r_objects_len, - {.object_mode = ob_active->mode, - .no_dup_data = true, - .filter_fn = filter_fn, - .filter_userdata = filter_user_data}); + struct ObjectsInModeParams params = {0}; + params.object_mode = ob_active->mode; + params.no_dup_data = true; + params.filter_fn = filter_fn; + params.filter_userdata = filter_user_data; + objects = BKE_view_layer_array_from_objects_in_mode_params( + view_layer, v3d, r_objects_len, ¶ms); } else { objects = BKE_view_layer_array_selected_objects( @@ -701,7 +701,7 @@ bool ED_object_editmode_free_ex(Main *bmain, Object *obedit) bool ED_object_editmode_exit_multi_ex(Main *bmain, Scene *scene, ViewLayer *view_layer, int flag) { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit == NULL) { return false; } @@ -841,7 +841,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); const int mode_flag = OB_MODE_EDIT; const bool is_mode_set = (obact->mode & mode_flag) != 0; struct wmMsgBus *mbus = CTX_wm_message_bus(C); @@ -889,13 +889,13 @@ static bool editmode_toggle_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - /* covers proxies too */ + /* Covers liboverrides too. */ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } - /* if hidden but in edit mode, we still display */ + /* If hidden but in edit mode, we still display. */ if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { return false; } @@ -953,7 +953,7 @@ static int posemode_exec(bContext *C, wmOperator *op) } { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obact == obedit) { ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); is_mode_set = false; @@ -1244,7 +1244,7 @@ static int object_calculate_paths_exec(bContext *C, wmOperator *op) /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW_ANIMVIZ, NULL); - /* Note: the notifier below isn't actually correct, but kept around just to be on the safe side. + /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side. * If further testing shows it's not necessary (for both bones and objects) removal is fine. */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM | ND_POSE, NULL); @@ -1316,7 +1316,7 @@ static int object_update_paths_exec(bContext *C, wmOperator *op) /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW_ANIMVIZ, NULL); - /* Note: the notifier below isn't actually correct, but kept around just to be on the safe side. + /* NOTE: the notifier below isn't actually correct, but kept around just to be on the safe side. * If further testing shows it's not necessary (for both bones and objects) removal is fine. */ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM | ND_POSE, NULL); @@ -1469,8 +1469,6 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) static int shade_smooth_exec(bContext *C, wmOperator *op) { const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth"); - const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth"); - const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); bool changed_multi = false; bool has_linked_data = false; @@ -1480,7 +1478,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) /* For modes that only use an active object, don't handle the whole selection. */ { ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { ctx_ob_single_active.ptr.data = obact; BLI_addtail(&ctx_objects, &ctx_ob_single_active); @@ -1518,7 +1516,11 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) bool changed = false; if (ob->type == OB_MESH) { BKE_mesh_smooth_flag_set(ob->data, use_smooth); - BKE_mesh_auto_smooth_flag_set(ob->data, use_auto_smooth, auto_smooth_angle); + if (use_smooth) { + const bool use_auto_smooth = RNA_boolean_get(op->ptr, "use_auto_smooth"); + const float auto_smooth_angle = RNA_float_get(op->ptr, "auto_smooth_angle"); + BKE_mesh_auto_smooth_flag_set(ob->data, use_auto_smooth, auto_smooth_angle); + } BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); changed = true; } @@ -1549,7 +1551,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) static bool shade_poll(bContext *C) { ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + Object *obact = BKE_view_layer_active_object_get(view_layer); if (obact != NULL) { /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == NULL || diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index dddf5e40e87..4364375a4e3 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -53,7 +53,7 @@ void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum) /* if there's is no facemap layer then create one */ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) { - facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly); + facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_SET_DEFAULT, NULL, me->totpoly); } facemap[facenum] = fmap_nr; diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 573f048e6b6..42ac6d166b4 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -680,8 +680,7 @@ static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); int index = RNA_int_get(op->ptr, "index"); - - if (!ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index)) { + if (!(md && ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index))) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b5862d4d957..63f010cd526 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -49,10 +49,14 @@ void OBJECT_OT_vertex_parent_set(struct wmOperatorType *ot); void OBJECT_OT_track_set(struct wmOperatorType *ot); void OBJECT_OT_track_clear(struct wmOperatorType *ot); void OBJECT_OT_make_local(struct wmOperatorType *ot); -void OBJECT_OT_make_override_library(struct wmOperatorType *ot); void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); + +void OBJECT_OT_make_override_library(struct wmOperatorType *ot); +void OBJECT_OT_reset_override_library(struct wmOperatorType *ot); +void OBJECT_OT_clear_override_library(struct wmOperatorType *ot); + /** * Used for drop-box. * Assigns to object under cursor, only first material slot. @@ -259,7 +263,7 @@ void CONSTRAINT_OT_objectsolver_set_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_objectsolver_clear_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_followpath_path_animate(struct wmOperatorType *ot); -/* object_vgroup.c */ +/* object_vgroup.cc */ void OBJECT_OT_vertex_group_add(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_remove(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index 0055cdf9ea1..27d8c326d41 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -191,7 +191,7 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL { wmWindowManager *wm = CTX_wm_manager(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { return (mode == OB_MODE_OBJECT); } diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index 202c6d96a47..9bb82cc086c 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -47,9 +47,11 @@ #include "BKE_gpencil_modifier.h" #include "BKE_key.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" @@ -92,6 +94,8 @@ #include "object_intern.h" +using blender::Span; + static void modifier_skin_customdata_delete(struct Object *ob); /* ------------------------------------------------------------------- */ @@ -111,7 +115,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval); } else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); + BKE_mball_data_update(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) { BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false); @@ -486,6 +490,9 @@ bool ED_object_modifier_move_to_index(ReportList *reports, } } + /* NOTE: Dependency graph only uses modifier nodes for visibility updates, and exact order of + * modifier nodes in the graph does not matter. */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); @@ -582,12 +589,14 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), me->totvert = verts_num; me->totedge = edges_num; - me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, verts_num); - me->medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, nullptr, edges_num); - me->mface = (MFace *)CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, nullptr, 0); + CustomData_add_layer(&me->vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, verts_num); + CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, edges_num); + CustomData_add_layer(&me->fdata, CD_MFACE, CD_SET_DEFAULT, nullptr, 0); - MVert *mvert = me->mvert; - MEdge *medge = me->medge; + blender::MutableSpan<MVert> verts = me->verts_for_write(); + blender::MutableSpan<MEdge> edges = me->edges_for_write(); + MVert *mvert = verts.data(); + MEdge *medge = edges.data(); /* copy coordinates */ cache = psys_eval->pathcache; @@ -757,9 +766,7 @@ static bool modifier_apply_obdata( BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true); /* Anonymous attributes shouldn't be available on the applied geometry. */ - MeshComponent component; - component.replace(me, GeometryOwnershipType::Editable); - component.attributes_remove_anonymous(); + me->attributes_for_write().remove_anonymous(); if (md_eval->type == eModifierType_Multires) { multires_customdata_delete(me); @@ -820,7 +827,7 @@ static bool modifier_apply_obdata( /* Create a temporary geometry set and component. */ GeometrySet geometry_set; geometry_set.get_component_for_write<CurveComponent>().replace( - &curves, GeometryOwnershipType::Editable); + &curves, GeometryOwnershipType::ReadOnly); ModifierEvalContext mectx = {depsgraph, ob, (ModifierApplyFlag)0}; mti->modifyGeometrySet(md_eval, &mectx, &geometry_set); @@ -828,20 +835,18 @@ static bool modifier_apply_obdata( BKE_report(reports, RPT_ERROR, "Evaluated geometry from modifier does not contain curves"); return false; } - CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>(); Curves &curves_eval = *geometry_set.get_curves_for_write(); /* Anonymous attributes shouldn't be available on the applied geometry. */ - component.attributes_remove_anonymous(); + blender::bke::CurvesGeometry::wrap(curves_eval.geometry) + .attributes_for_write() + .remove_anonymous(); - /* If the modifier's output is a different curves data-block, copy the relevant information to - * the original. */ - if (&curves_eval != &curves) { - blender::bke::CurvesGeometry::wrap(curves.geometry) = std::move( - blender::bke::CurvesGeometry::wrap(curves_eval.geometry)); - Main *bmain = DEG_get_bmain(depsgraph); - BKE_object_material_from_eval_data(bmain, ob, &curves_eval.id); - } + /* Copy the relevant information to the original. */ + blender::bke::CurvesGeometry::wrap(curves.geometry) = std::move( + blender::bke::CurvesGeometry::wrap(curves_eval.geometry)); + Main *bmain = DEG_get_bmain(depsgraph); + BKE_object_material_from_eval_data(bmain, ob, &curves_eval.id); } else { /* TODO: implement for point clouds and volumes. */ @@ -1227,7 +1232,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) /* if cloth/softbody was removed, particle mode could be cleared */ if (mode_orig & OB_MODE_PARTICLE_EDIT) { if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { - if (ob == OBACT(view_layer)) { + if (ob == BKE_view_layer_active_object_get(view_layer)) { WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, nullptr); } } @@ -1367,7 +1372,7 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int index = RNA_int_get(op->ptr, "index"); - if (!ED_object_modifier_move_to_index(op->reports, ob, md, index)) { + if (!(md && ED_object_modifier_move_to_index(op->reports, ob, md, index))) { return OPERATOR_CANCELLED; } @@ -1440,7 +1445,6 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); - const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); const bool do_report = RNA_boolean_get(op->ptr, "report"); const bool do_single_user = RNA_boolean_get(op->ptr, "single_user"); const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata"); @@ -1449,6 +1453,8 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo return OPERATOR_CANCELLED; } + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + if (do_single_user && ID_REAL_USERS(ob->data) > 1) { ED_object_single_obdata_user(bmain, scene, ob); BKE_main_id_newptr_and_tag_clear(bmain); @@ -1671,6 +1677,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) } DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -2586,8 +2593,8 @@ void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) } static void skin_armature_bone_create(Object *skin_ob, - MVert *mvert, - MEdge *medge, + const MVert *mvert, + const MEdge *medge, bArmature *arm, BLI_bitmap *edges_visited, const MeshElemMap *emap, @@ -2632,15 +2639,18 @@ static void skin_armature_bone_create(Object *skin_ob, static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Object *skin_ob) { Mesh *me = static_cast<Mesh *>(skin_ob->data); + const Span<MVert> me_verts = me->verts(); + const Span<MEdge> me_edges = me->edges(); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob); - Mesh *me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - MVert *mvert = me_eval_deform->mvert; + const Mesh *me_eval_deform = mesh_get_eval_deform( + depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + const Span<MVert> verts_eval = me_eval_deform->verts(); /* add vertex weights to original mesh */ - CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, nullptr, me->totvert); + CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, me->totvert); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); Object *arm_ob = BKE_object_add(bmain, view_layer, OB_ARMATURE, nullptr); @@ -2655,7 +2665,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, CustomData_get_layer(&me->vdata, CD_MVERT_SKIN)); int *emap_mem; MeshElemMap *emap; - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge); + BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me_edges.data(), me->totvert, me->totedge); BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); @@ -2671,15 +2681,16 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, if (emap[v].count > 1) { bone = ED_armature_ebone_add(arm, "Bone"); - copy_v3_v3(bone->head, me->mvert[v].co); - copy_v3_v3(bone->tail, me->mvert[v].co); + copy_v3_v3(bone->head, me_verts[v].co); + copy_v3_v3(bone->tail, me_verts[v].co); bone->head[1] = 1.0f; bone->rad_head = bone->rad_tail = 0.25; } if (emap[v].count >= 1) { - skin_armature_bone_create(skin_ob, mvert, me->medge, arm, edges_visited, emap, bone, v); + skin_armature_bone_create( + skin_ob, verts_eval.data(), me_edges.data(), arm, edges_visited, emap, bone, v); } } } @@ -3347,6 +3358,7 @@ void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot) ot->idname = "OBJECT_OT_geometry_nodes_input_attribute_toggle"; ot->exec = geometry_nodes_input_attribute_toggle_exec; + ot->poll = ED_operator_object_active; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; @@ -3364,9 +3376,8 @@ static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *UNUSED(o { Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); - ModifierData *md = BKE_object_active_modifier(ob); - if (md->type != eModifierType_Nodes) { + if (!(md && md->type == eModifierType_Nodes)) { return OPERATOR_CANCELLED; } @@ -3398,6 +3409,7 @@ void OBJECT_OT_geometry_node_tree_copy_assign(wmOperatorType *ot) ot->idname = "OBJECT_OT_geometry_node_tree_copy_assign"; ot->exec = geometry_node_tree_copy_assign_exec; + ot->poll = ED_operator_object_active; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 8a0d380ff2f..24a4556b075 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -58,11 +58,14 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_track_set); WM_operatortype_append(OBJECT_OT_track_clear); WM_operatortype_append(OBJECT_OT_make_local); - WM_operatortype_append(OBJECT_OT_make_override_library); WM_operatortype_append(OBJECT_OT_make_single_user); WM_operatortype_append(OBJECT_OT_make_links_scene); WM_operatortype_append(OBJECT_OT_make_links_data); + WM_operatortype_append(OBJECT_OT_make_override_library); + WM_operatortype_append(OBJECT_OT_reset_override_library); + WM_operatortype_append(OBJECT_OT_clear_override_library); + WM_operatortype_append(OBJECT_OT_select_random); WM_operatortype_append(OBJECT_OT_select_all); WM_operatortype_append(OBJECT_OT_select_same_collection); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f55ffdf0fcd..40dbd6b7bd8 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -263,7 +263,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) else { Object workob; - ob->parent = BASACT(view_layer)->object; + ob->parent = view_layer->basact->object; if (par3 != INDEX_UNSET) { ob->partype = PARVERT3; ob->par1 = par1; @@ -951,7 +951,7 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot) 1); struct { - bool mesh, gpencil; + bool mesh, gpencil, curves; } has_children_of_type = {0}; CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) { @@ -964,6 +964,9 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot) if (child->type == OB_GPENCIL) { has_children_of_type.gpencil = true; } + if (child->type == OB_CURVES) { + has_children_of_type.curves = true; + } } CTX_DATA_END; @@ -987,6 +990,11 @@ static int parent_set_invoke_menu(bContext *C, wmOperatorType *ot) else if (parent->type == OB_LATTICE) { uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE); } + else if (parent->type == OB_MESH) { + if (has_children_of_type.curves) { + uiItemO(layout, "Object (Attach Curves to Surface)", ICON_NONE, "CURVES_OT_surface_set"); + } + } /* vertex parenting */ if (OB_TYPE_SUPPORT_PARVERT(parent->type)) { @@ -1822,6 +1830,11 @@ static void single_obdata_users( DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); switch (ob->type) { + case OB_EMPTY: + ob->data = ID_NEW_SET( + ob->data, + BKE_id_copy_ex(bmain, ob->data, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS)); + break; case OB_LAMP: ob->data = la = ID_NEW_SET( ob->data, @@ -2267,12 +2280,6 @@ static int make_override_library_exec(bContext *C, wmOperator *op) ID *id_root = NULL; bool is_override_instancing_object = false; - const bool do_fully_editable = RNA_boolean_get(op->ptr, "do_fully_editable"); - - GSet *user_overrides_objects_uids = do_fully_editable ? NULL : - BLI_gset_new(BLI_ghashutil_inthash_p, - BLI_ghashutil_intcmp, - __func__); bool user_overrides_from_selected_objects = false; if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && @@ -2312,6 +2319,21 @@ static int make_override_library_exec(bContext *C, wmOperator *op) user_overrides_from_selected_objects = true; } + const bool do_fully_editable = !user_overrides_from_selected_objects; + + GSet *user_overrides_objects_uids = do_fully_editable ? NULL : + BLI_gset_new(BLI_ghashutil_inthash_p, + BLI_ghashutil_intcmp, + __func__); + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) { + ob_iter->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; + } + } + FOREACH_SELECTED_OBJECT_END; + if (do_fully_editable) { /* Pass. */ } @@ -2334,6 +2356,25 @@ static int make_override_library_exec(bContext *C, wmOperator *op) BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + /* For the time being, replace selected linked objects by their overrides in all collections. + * While this may not be the absolute best behavior in all cases, in most common one this should + * match the expected result. */ + if (user_overrides_objects_uids != NULL) { + LISTBASE_FOREACH (Collection *, coll_iter, &bmain->collections) { + if (ID_IS_LINKED(coll_iter)) { + continue; + } + LISTBASE_FOREACH (CollectionObject *, coll_ob_iter, &coll_iter->gobject) { + if (BLI_gset_haskey(user_overrides_objects_uids, + POINTER_FROM_UINT(coll_ob_iter->ob->id.session_uuid))) { + /* Tag for remapping when creating overrides. */ + coll_iter->id.tag |= LIB_TAG_DOIT; + break; + } + } + } + } + ID *id_root_override; const bool success = BKE_lib_override_library_create(bmain, scene, @@ -2398,6 +2439,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } @@ -2422,6 +2465,9 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve } if (!ID_IS_LINKED(obact)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(obact)) { + return make_override_library_exec(C, op); + } BKE_report(op->reports, RPT_ERROR, "Cannot make library override from a local object"); return OPERATOR_CANCELLED; } @@ -2460,17 +2506,20 @@ static bool make_override_library_poll(bContext *C) Object *obact = CTX_data_active_object(C); /* Object must be directly linked to be overridable. */ - return (ED_operator_objectmode(C) && obact != NULL && - (ID_IS_LINKED(obact) || (obact->instance_collection != NULL && - ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection) && - !ID_IS_OVERRIDE_LIBRARY(obact)))); + return ( + ED_operator_objectmode(C) && obact != NULL && + (ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) || + (obact->instance_collection != NULL && + ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection) && !ID_IS_OVERRIDE_LIBRARY(obact)))); } void OBJECT_OT_make_override_library(wmOperatorType *ot) { /* identifiers */ ot->name = "Make Library Override"; - ot->description = "Make a local override of this library linked data-block"; + ot->description = + "Create a local override of the selected linked objects, and their hierarchy of " + "dependencies"; ot->idname = "OBJECT_OT_make_override_library"; /* api callbacks */ @@ -2495,13 +2544,129 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot) INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); ot->prop = prop; +} - prop = RNA_def_boolean(ot->srna, - "do_fully_editable", - false, - "Create Fully Editable", - "Make all created override data-blocks fully editable"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Reset Library Override Operator + * \{ */ + +static bool reset_clear_override_library_poll(bContext *C) +{ + Object *obact = CTX_data_active_object(C); + + /* Object must be local and an override. */ + return (ED_operator_objectmode(C) && obact != NULL && !ID_IS_LINKED(obact) && + ID_IS_OVERRIDE_LIBRARY(obact)); +} + +static int reset_override_library_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (CTX_data_view_layer(C), CTX_wm_view3d(C), ob_iter) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) { + BKE_lib_override_library_id_reset(bmain, &ob_iter->id, false); + } + } + FOREACH_SELECTED_OBJECT_END; + + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_reset_override_library(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Reset Library Override"; + ot->description = "Reset the selected local overrides to their linked references values"; + ot->idname = "OBJECT_OT_reset_override_library"; + + /* api callbacks */ + ot->exec = reset_override_library_exec; + ot->poll = reset_clear_override_library_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear Library Override Operator + * \{ */ + +static int clear_override_library_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); + LinkNode *todo_objects = NULL, *todo_object_iter; + + /* Make already existing selected liboverrides editable. */ + FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) { + if (ID_IS_LINKED(ob_iter)) { + continue; + } + BLI_linklist_prepend_alloca(&todo_objects, ob_iter); + } + FOREACH_SELECTED_OBJECT_END; + + for (todo_object_iter = todo_objects; todo_object_iter != NULL; + todo_object_iter = todo_object_iter->next) { + Object *ob_iter = todo_object_iter->link; + if (BKE_lib_override_library_is_hierarchy_leaf(bmain, &ob_iter->id)) { + bool do_remap_active = false; + if (BKE_view_layer_active_object_get(view_layer) == ob_iter) { + do_remap_active = true; + } + BKE_libblock_remap(bmain, + &ob_iter->id, + ob_iter->id.override_library->reference, + ID_REMAP_SKIP_INDIRECT_USAGE); + if (do_remap_active) { + Object *ref_object = (Object *)ob_iter->id.override_library->reference; + Base *basact = BKE_view_layer_base_find(view_layer, ref_object); + if (basact != NULL) { + view_layer->basact = basact; + } + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + BKE_id_delete(bmain, &ob_iter->id); + } + else { + BKE_lib_override_library_id_reset(bmain, &ob_iter->id, true); + } + } + + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_clear_override_library(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Library Override"; + ot->description = + "Delete the selected local overrides and relink their usages to the linked data-blocks if " + "possible, else reset them and mark them as non editable"; + ot->idname = "OBJECT_OT_clear_override_library"; + + /* api callbacks */ + ot->exec = clear_override_library_exec; + ot->poll = reset_clear_override_library_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 71b757b66ff..09489c50e9d 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -73,6 +73,9 @@ #include "object_intern.h" /* own include */ +using blender::IndexRange; +using blender::Span; + /* TODO(sebpa): unstable, can lead to unrecoverable errors. */ // #define USE_MESH_CURVATURE @@ -128,7 +131,8 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } /* Output mesh will be all smooth or all flat shading. */ - const bool smooth_normals = mesh->mpoly[0].flag & ME_SMOOTH; + const Span<MPoly> polys = mesh->polys(); + const bool smooth_normals = polys.first().flag & ME_SMOOTH; float isovalue = 0.0f; if (mesh->flag & ME_REMESH_REPROJECT_VOLUME) { @@ -144,7 +148,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_begin(ob, op->type->name); + ED_sculpt_undo_geometry_begin(ob, op); } if (mesh->flag & ME_REMESH_FIX_POLES && mesh->remesh_voxel_adaptivity <= 0.0f) { @@ -415,15 +419,15 @@ static int voxel_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *eve } if (event->modifier & KM_CTRL) { - /* Linear mode, enables jumping to any voxel size. */ - d = d * 0.0005f; - } - else { /* Multiply d by the initial voxel size to prevent uncontrollable speeds when using low voxel * sizes. */ /* When the voxel size is slower, it needs more precision. */ d = d * min_ff(pow2f(cd->init_voxel_size), 0.1f) * 0.05f; } + else { + /* Linear mode, enables jumping to any voxel size. */ + d = d * 0.0005f; + } if (cd->slow_mode) { cd->voxel_size = cd->slow_voxel_size + d * 0.05f; } @@ -577,10 +581,18 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Use the Bounding Box face normal as the basis Z. */ normal_tri_v3(cd->text_mat[2], cd->preview_plane[0], cd->preview_plane[1], cd->preview_plane[2]); + /* Invert object scale. */ + float scale[3]; + mat4_to_size(scale, active_object->obmat); + invert_v3(scale); + size_to_mat4(scale_mat, scale); + + mul_m4_m4_pre(cd->text_mat, scale_mat); + /* Write the text position into the matrix. */ copy_v3_v3(cd->text_mat[3], text_pos); - /* Scale the text. */ + /* Scale the text to constant viewport size. */ float text_pos_word_space[3]; mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos); const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space); @@ -592,7 +604,8 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev ED_region_tag_redraw(region); const char *status_str = TIP_( - "Move the mouse to change the voxel size. LMB: confirm size, ESC/RMB: cancel"); + "Move the mouse to change the voxel size. CTRL: Relative Scale, SHIFT: Precision Mode, " + "ENTER/LMB: Confirm Size, ESC/RMB: Cancel"); ED_workspace_status_text(C, status_str); return OPERATOR_RUNNING_MODAL; @@ -645,6 +658,7 @@ struct QuadriFlowJob { short *stop, *do_update; float *progress; + const struct wmOperator *op; Scene *scene; int target_faces; int seed; @@ -668,9 +682,11 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) * check that the direction of the faces are consistent and doesn't suddenly * flip */ + const Span<MVert> verts = mesh->verts(); + const Span<MEdge> edges = mesh->edges(); + const Span<MLoop> loops = mesh->loops(); bool is_manifold_consistent = true; - const MLoop *mloop = mesh->mloop; char *edge_faces = (char *)MEM_callocN(mesh->totedge * sizeof(char), "remesh_manifold_check"); int *edge_vert = (int *)MEM_malloc_arrayN( mesh->totedge, sizeof(uint), "remesh_consistent_check"); @@ -679,18 +695,17 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) edge_vert[i] = -1; } - for (uint loop_idx = 0; loop_idx < mesh->totloop; loop_idx++) { - const MLoop *loop = &mloop[loop_idx]; - edge_faces[loop->e] += 1; - if (edge_faces[loop->e] > 2) { + for (const MLoop &loop : loops) { + edge_faces[loop.e] += 1; + if (edge_faces[loop.e] > 2) { is_manifold_consistent = false; break; } - if (edge_vert[loop->e] == -1) { - edge_vert[loop->e] = loop->v; + if (edge_vert[loop.e] == -1) { + edge_vert[loop.e] = loop.v; } - else if (edge_vert[loop->e] == loop->v) { + else if (edge_vert[loop.e] == loop.v) { /* Mesh has flips in the surface so it is non consistent */ is_manifold_consistent = false; break; @@ -698,16 +713,16 @@ static bool mesh_is_manifold_consistent(Mesh *mesh) } if (is_manifold_consistent) { - for (uint i = 0; i < mesh->totedge; i++) { + for (const int i : edges.index_range()) { /* Check for wire edges. */ if (edge_faces[i] == 0) { is_manifold_consistent = false; break; } /* Check for zero length edges */ - MVert *v1 = &mesh->mvert[mesh->medge[i].v1]; - MVert *v2 = &mesh->mvert[mesh->medge[i].v2]; - if (compare_v3v3(v1->co, v2->co, 1e-4f)) { + const MVert &v1 = verts[edges[i].v1]; + const MVert &v2 = verts[edges[i].v2]; + if (compare_v3v3(v1.co, v2.co, 1e-4f)) { is_manifold_consistent = false; break; } @@ -882,7 +897,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update new_mesh = remesh_symmetry_mirror(qj->owner, new_mesh, qj->symmetry_axes); if (ob->mode == OB_MODE_SCULPT) { - ED_sculpt_undo_geometry_begin(ob, "QuadriFlow Remesh"); + ED_sculpt_undo_geometry_begin(ob, qj->op); } if (qj->preserve_paint_mask) { @@ -940,6 +955,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) { QuadriFlowJob *job = (QuadriFlowJob *)MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob"); + job->op = op; job->owner = CTX_data_active_object(C); job->scene = CTX_data_scene(C); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index c3d8fb9cfe5..82c39d38d74 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -120,7 +120,7 @@ void ED_object_base_activate_with_mode_exit_if_needed(bContext *C, Base *base) ViewLayer *view_layer = CTX_data_view_layer(C); /* Currently we only need to be concerned with edit-mode. */ - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit) { Object *ob = base->object; if (((ob->mode & OB_MODE_EDIT) == 0) || (obedit->type != ob->type)) { @@ -626,7 +626,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -777,7 +777,8 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv return changed; } -static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ +/* Makes parent active and de-selected BKE_view_layer_active_object_get. */ +static bool select_grouped_parent(bContext *C) { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -785,7 +786,8 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel bool changed = false; if (!basact || !(basact->object->parent)) { - return 0; /* we know OBACT is valid */ + /* We know BKE_view_layer_active_object_get is valid. */ + return 0; } baspar = BKE_view_layer_base_find(view_layer, basact->object->parent); @@ -1021,7 +1023,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; @@ -1128,7 +1130,7 @@ static int object_select_all_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } if (any_visible == false) { - /* TODO(campbell): Looks like we could remove this, + /* TODO(@campbellbarton): Looks like we could remove this, * if not comment should say why its needed. */ return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index dd7fc192dc1..4b721cb65a1 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -481,12 +481,15 @@ static int shaderfx_remove_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Object *ob = ED_object_active_context(C); ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); + if (!fx) { + return OPERATOR_CANCELLED; + } /* Store name temporarily for report. */ char name[MAX_NAME]; strcpy(name, fx->name); - if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx)) { + if (!ED_object_shaderfx_remove(op->reports, bmain, ob, fx)) { return OPERATOR_CANCELLED; } @@ -671,7 +674,9 @@ static int shaderfx_copy_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); - + if (!fx) { + return OPERATOR_CANCELLED; + } ShaderFxData *nfx = BKE_shaderfx_new(fx->type); if (!nfx) { return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index ebcf8573ccd..0328f6a6230 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -20,6 +20,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -112,14 +114,13 @@ static bool object_shape_key_mirror( if (ob->type == OB_MESH) { Mesh *me = ob->data; - MVert *mv; int i1, i2; float *fp1, *fp2; float tvec[3]; ED_mesh_mirror_spatial_table_begin(ob, NULL, NULL); - for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) { + for (i1 = 0; i1 < me->totvert; i1++) { i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology); if (i2 == i1) { fp1 = ((float *)kb->data) + i1 * 3; @@ -299,6 +300,10 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op) bool changed = false; if (RNA_boolean_get(op->ptr, "all")) { + if (RNA_boolean_get(op->ptr, "apply_mix")) { + float *arr = BKE_key_evaluate_object_ex(ob, NULL, NULL, 0, ob->data); + MEM_freeN(arr); + } changed = BKE_object_shapekey_free(bmain, ob); } else { @@ -315,6 +320,34 @@ static int shape_key_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } +static bool shape_key_remove_poll_property(const bContext *UNUSED(C), + wmOperator *op, + const PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + const bool do_all = RNA_enum_get(op->ptr, "all"); + + /* Only show seed for randomize action! */ + if (STREQ(prop_id, "apply_mix") && !do_all) { + return false; + } + return true; +} + +static char *shape_key_remove_get_description(bContext *UNUSED(C), + wmOperatorType *UNUSED(ot), + PointerRNA *ptr) +{ + const bool do_apply_mix = RNA_boolean_get(ptr, "apply_mix"); + + if (do_apply_mix) { + return BLI_strdup( + TIP_("Apply current visible shape to the object data, and delete all shape keys")); + } + + return NULL; +} + void OBJECT_OT_shape_key_remove(wmOperatorType *ot) { /* identifiers */ @@ -325,12 +358,19 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot) /* api callbacks */ ot->poll = shape_key_mode_exists_poll; ot->exec = shape_key_remove_exec; + ot->poll_property = shape_key_remove_poll_property; + ot->get_description = shape_key_remove_get_description; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys"); + RNA_def_boolean(ot->srna, "all", false, "All", "Remove all shape keys"); + RNA_def_boolean(ot->srna, + "apply_mix", + false, + "Apply Mix", + "Apply current mix of shape keys to the geometry before removing them"); } /** \} */ diff --git a/source/blender/editors/object/object_transform.cc b/source/blender/editors/object/object_transform.cc index 82e67231ec1..e4f96d95173 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -855,7 +855,7 @@ static int apply_objects_internal(bContext *C, /* calculate translation */ if (apply_loc) { - copy_v3_v3(mat[3], ob->loc); + add_v3_v3v3(mat[3], ob->loc, ob->dloc); if (!(apply_scale && apply_rot)) { float tmat[3][3]; @@ -1023,14 +1023,19 @@ static int apply_objects_internal(bContext *C, else { if (apply_loc) { zero_v3(ob->loc); + zero_v3(ob->dloc); } if (apply_scale) { - ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; + copy_v3_fl(ob->scale, 1.0f); + copy_v3_fl(ob->dscale, 1.0f); } if (apply_rot) { zero_v3(ob->rot); + zero_v3(ob->drot); unit_qt(ob->quat); + unit_qt(ob->dquat); unit_axis_angle(ob->rotAxis, &ob->rotAngle); + unit_axis_angle(ob->drotAxis, &ob->drotAngle); } } @@ -1598,6 +1603,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } } } + BKE_gpencil_stroke_geometry_update(gpd, gps); } } } @@ -2219,7 +2225,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const bool is_finished = false; - if (ISMOUSE(xfd->init_event)) { + if (ISMOUSE_BUTTON(xfd->init_event)) { if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) { is_finished = true; } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.cc index 9ad36cacc7d..d2cb7ad4b43 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.cc @@ -5,9 +5,9 @@ * \ingroup edobj */ -#include <math.h> -#include <stddef.h> -#include <string.h> +#include <cmath> +#include <cstddef> +#include <cstring> #include "MEM_guardedalloc.h" @@ -21,14 +21,15 @@ #include "DNA_scene_types.h" #include "DNA_workspace_types.h" -#include "BLI_alloca.h" #include "BLI_array.h" +#include "BLI_array.hh" #include "BLI_bitmap.h" #include "BLI_blenlib.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_utildefines_stack.h" +#include "BLI_vector.hh" #include "BKE_context.h" #include "BKE_customdata.h" @@ -66,6 +67,9 @@ #include "object_intern.h" +using blender::MutableSpan; +using blender::Span; + static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob); /* -------------------------------------------------------------------- */ @@ -74,7 +78,7 @@ static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob); static bool object_array_for_wpaint_filter(const Object *ob, void *user_data) { - bContext *C = user_data; + bContext *C = static_cast<bContext *>(user_data); if (vertex_group_supported_poll_ex(C, ob)) { return true; } @@ -100,7 +104,7 @@ static bool vertex_group_use_vert_sel(Object *ob) static Lattice *vgroup_edit_lattice(Object *ob) { - Lattice *lt = ob->data; + Lattice *lt = static_cast<Lattice *>(ob->data); BLI_assert(ob->type == OB_LATTICE); return (lt->editlatt) ? lt->editlatt->latt : lt; } @@ -115,7 +119,7 @@ bool ED_vgroup_sync_from_pose(Object *ob) { Object *armobj = BKE_object_pose_armature_get(ob); if (armobj && (armobj->mode & OB_MODE_POSE)) { - struct bArmature *arm = armobj->data; + bArmature *arm = static_cast<bArmature *>(armobj->data); if (arm->act_bone) { int def_num = BKE_object_defgroup_name_index(ob, arm->act_bone->name); if (def_num != -1) { @@ -151,7 +155,7 @@ bool ED_vgroup_parray_alloc(ID *id, const bool use_vert_sel) { *dvert_tot = 0; - *dvert_arr = NULL; + *dvert_arr = nullptr; if (id) { switch (GS(id->name)) { @@ -172,42 +176,45 @@ bool ED_vgroup_parray_alloc(ID *id, i = em->bm->totvert; - *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me"); + *dvert_arr = static_cast<MDeformVert **>(MEM_mallocN(sizeof(void *) * i, __func__)); *dvert_tot = i; i = 0; if (use_vert_sel) { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ? - BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) : - NULL; + static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)) : + nullptr; i++; } } else { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + (*dvert_arr)[i] = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); i++; } } return true; } - if (me->dvert) { - MVert *mvert = me->mvert; - MDeformVert *dvert = me->dvert; + if (!me->deform_verts().is_empty()) { + const Span<MVert> verts = me->verts(); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); *dvert_tot = me->totvert; - *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me"); + *dvert_arr = static_cast<MDeformVert **>( + MEM_mallocN(sizeof(void *) * me->totvert, __func__)); if (use_vert_sel) { for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : NULL; + (*dvert_arr)[i] = (verts[i].flag & SELECT) ? &dverts[i] : nullptr; } } else { for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = me->dvert + i; + (*dvert_arr)[i] = &dverts[i]; } } @@ -222,11 +229,12 @@ bool ED_vgroup_parray_alloc(ID *id, if (lt->dvert) { BPoint *def = lt->def; *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw; - *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me"); + *dvert_arr = static_cast<MDeformVert **>( + MEM_mallocN(sizeof(void *) * (*dvert_tot), __func__)); if (use_vert_sel) { for (int i = 0; i < *dvert_tot; i++) { - (*dvert_arr)[i] = (def->f1 & SELECT) ? <->dvert[i] : NULL; + (*dvert_arr)[i] = (def->f1 & SELECT) ? <->dvert[i] : nullptr; } } else { @@ -255,11 +263,12 @@ void ED_vgroup_parray_mirror_sync(Object *ob, const int vgroup_tot) { BMEditMesh *em = BKE_editmesh_from_object(ob); - MDeformVert **dvert_array_all = NULL; + MDeformVert **dvert_array_all = nullptr; int dvert_tot_all; /* get an array of all verts, not only selected */ - if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) { + if (ED_vgroup_parray_alloc( + static_cast<ID *>(ob->data), &dvert_array_all, &dvert_tot_all, false) == false) { BLI_assert(0); return; } @@ -271,10 +280,10 @@ void ED_vgroup_parray_mirror_sync(Object *ob, const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); for (int i_src = 0; i_src < dvert_tot; i_src++) { - if (dvert_array[i_src] != NULL) { + if (dvert_array[i_src] != nullptr) { /* its selected, check if its mirror exists */ int i_dst = ED_mesh_mirror_get_vert(ob, i_src); - if (i_dst != -1 && dvert_array_all[i_dst] != NULL) { + if (i_dst != -1 && dvert_array_all[i_dst] != nullptr) { /* we found a match! */ const MDeformVert *dv_src = dvert_array[i_src]; MDeformVert *dv_dst = dvert_array_all[i_dst]; @@ -294,11 +303,12 @@ void ED_vgroup_parray_mirror_sync(Object *ob, void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot) { BMEditMesh *em = BKE_editmesh_from_object(ob); - MDeformVert **dvert_array_all = NULL; + MDeformVert **dvert_array_all = nullptr; int dvert_tot_all; /* get an array of all verts, not only selected */ - if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) { + if (ED_vgroup_parray_alloc( + static_cast<ID *>(ob->data), &dvert_array_all, &dvert_tot_all, false) == false) { BLI_assert(0); return; } @@ -308,7 +318,7 @@ void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const } for (int i = 0; i < dvert_tot; i++) { - if (dvert_array[i] == NULL) { + if (dvert_array[i] == nullptr) { /* its unselected, check if its mirror is */ int i_sel = ED_mesh_mirror_get_vert(ob, i); if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) { @@ -357,8 +367,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, bool ED_vgroup_array_copy(Object *ob, Object *ob_from) { - MDeformVert **dvert_array_from = NULL, **dvf; - MDeformVert **dvert_array = NULL, **dv; + MDeformVert **dvert_array_from = nullptr, **dvf; + MDeformVert **dvert_array = nullptr, **dv; int dvert_tot_from; int dvert_tot; int i; @@ -378,17 +388,18 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) /* In case we copy vgroup between two objects using same data, * we only have to care about object side of things. */ if (ob->data != ob_from->data) { - ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + ED_vgroup_parray_alloc( + static_cast<ID *>(ob_from->data), &dvert_array_from, &dvert_tot_from, false); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, false); - if ((dvert_array == NULL) && (dvert_array_from != NULL) && - BKE_object_defgroup_data_create(ob->data)) { - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + if ((dvert_array == nullptr) && (dvert_array_from != nullptr) && + BKE_object_defgroup_data_create(static_cast<ID *>(ob->data))) { + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, false); new_vgroup = true; } - if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || - dvert_array == NULL) { + if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == nullptr || + dvert_array == nullptr) { if (dvert_array) { MEM_freeN(dvert_array); } @@ -413,7 +424,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) if (defbase_tot_from < defbase_tot) { /* correct vgroup indices because the number of vgroups is being reduced. */ - int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__); + blender::Array<int> remap(defbase_tot + 1); for (i = 0; i <= defbase_tot_from; i++) { remap[i] = i; } @@ -421,11 +432,10 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) remap[i] = 0; /* can't use these, so disable */ } - BKE_object_defgroup_remap_update_users(ob, remap); - MEM_freeN(remap); + BKE_object_defgroup_remap_update_users(ob, remap.data()); } - if (dvert_array_from != NULL && dvert_array != NULL) { + if (dvert_array_from != nullptr && dvert_array != nullptr) { dvf = dvert_array_from; dv = dvert_array; @@ -434,7 +444,7 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) *(*dv) = *(*dvf); if ((*dv)->dw) { - (*dv)->dw = MEM_dupallocN((*dv)->dw); + (*dv)->dw = static_cast<MDeformWeight *>(MEM_dupallocN((*dv)->dw)); } } @@ -503,7 +513,7 @@ static void mesh_defvert_mirror_update_internal(Object *ob, else { /* Single vgroup. */ MDeformWeight *dw = BKE_defvert_ensure_index(dvert_dst, - BKE_object_defgroup_flip_index(ob, def_nr, 1)); + BKE_object_defgroup_flip_index(ob, def_nr, true)); if (dw) { dw->weight = BKE_defvert_find_weight(dvert_src, def_nr); } @@ -513,7 +523,7 @@ static void mesh_defvert_mirror_update_internal(Object *ob, static void ED_mesh_defvert_mirror_update_em( Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; BMVert *eve_mirr; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; @@ -521,8 +531,10 @@ static void ED_mesh_defvert_mirror_update_em( eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology); if (eve_mirr && eve_mirr != eve) { - MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); - MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset); + MDeformVert *dvert_src = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); + MDeformVert *dvert_dst = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset)); mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr); } } @@ -530,25 +542,26 @@ static void ED_mesh_defvert_mirror_update_em( static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx) { int vidx_mirr; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; if (vidx == -1) { return; } - vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology); + vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) { - MDeformVert *dvert_src = &me->dvert[vidx]; - MDeformVert *dvert_dst = &me->dvert[vidx_mirr]; + MDeformVert *dvert_src = &dverts[vidx]; + MDeformVert *dvert_dst = &dverts[vidx_mirr]; mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr); } } void ED_vgroup_vert_active_mirror(Object *ob, int def_nr) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; @@ -584,7 +597,7 @@ static void vgroup_remove_weight(Object *ob, const int def_nr) static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; BMVert *eve_act; int v_act; @@ -599,7 +612,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); } - if (dvert_act == NULL) { + if (dvert_act == nullptr) { return false; } @@ -623,7 +636,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; int i, vgroup_tot, subset_count; @@ -639,7 +652,8 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) if (dvert_act) { BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) { - MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + MDeformVert *dv = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset); @@ -649,15 +663,15 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) } } else { - MDeformVert *dv; + const Span<MVert> verts = me->verts(); int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); if (dvert_act) { - dv = me->dvert; - for (i = 0; i < me->totvert; i++, dv++) { - if ((me->mvert[i].flag & SELECT) && dv != dvert_act) { - BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + for (i = 0; i < me->totvert; i++) { + if ((verts[i].flag & SELECT) && &dverts[i] != dvert_act) { + BKE_defvert_copy_subset(&dverts[i], dvert_act, vgroup_validmap, vgroup_tot); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); } @@ -688,20 +702,20 @@ static const EnumPropertyItem WT_vertex_group_select_item[] = { "Deform Pose Bones", "All Vertex Groups assigned to Deform Bones"}, {WT_VGROUP_ALL, "ALL", 0, "All Groups", "All Vertex Groups"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *C, PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), + PropertyRNA *prop, bool *r_free, const uint selection_mask) { Object *ob; - EnumPropertyItem *item = NULL; + EnumPropertyItem *item = nullptr; int totitem = 0; - if (C == NULL) { + if (C == nullptr) { /* needed for docs and i18n tools */ return WT_vertex_group_select_item; } @@ -731,6 +745,12 @@ const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext * RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL); } + /* Set `Deform Bone` as default selection if armature is present. */ + if (ob) { + RNA_def_property_enum_default( + prop, BKE_modifiers_is_deformed_by_armature(ob) ? WT_VGROUP_BONE_DEFORM : WT_VGROUP_ALL); + } + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -791,13 +811,13 @@ static void ED_vgroup_nr_vert_add( Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode) { /* Add the vert to the deform group with the specified number. */ - MDeformVert *dvert = NULL; + MDeformVert *dvert = nullptr; int tot; /* Get the vert. */ - BKE_object_defgroup_array_get(ob->data, &dvert, &tot); + BKE_object_defgroup_array_get(static_cast<ID *>(ob->data), &dvert, &tot); - if (dvert == NULL) { + if (dvert == nullptr) { return; } @@ -859,7 +879,7 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, const ListBase *defbase = BKE_object_defgroup_list(ob); const int def_nr = BLI_findindex(defbase, dg); - MDeformVert *dv = NULL; + MDeformVert *dv = nullptr; int tot; /* get the deform group number, exit if @@ -869,8 +889,8 @@ void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, /* if there's no deform verts then create some, */ - if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL) { - BKE_object_defgroup_data_create(ob->data); + if (BKE_object_defgroup_array_get(static_cast<ID *>(ob->data), &dv, &tot) && dv == nullptr) { + BKE_object_defgroup_data_create(static_cast<ID *>(ob->data)); } /* call another function to do the work @@ -885,37 +905,37 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) * deform group. */ - /* TODO(campbell): This is slow in a loop, better pass def_nr directly, + /* TODO(@campbellbarton): This is slow in a loop, better pass def_nr directly, * but leave for later. */ const ListBase *defbase = BKE_object_defgroup_list(ob); const int def_nr = BLI_findindex(defbase, dg); if (def_nr != -1) { - MDeformVert *dvert = NULL; + MDeformVert *dvert = nullptr; int tot; /* get the deform vertices corresponding to the * vertnum */ - BKE_object_defgroup_array_get(ob->data, &dvert, &tot); + BKE_object_defgroup_array_get(static_cast<ID *>(ob->data), &dvert, &tot); if (dvert) { MDeformVert *dv = &dvert[vertnum]; MDeformWeight *dw; dw = BKE_defvert_find_index(dv, def_nr); - BKE_defvert_remove_group(dv, dw); /* dw can be NULL */ + BKE_defvert_remove_group(dv, dw); /* dw can be nullptr */ } } } static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) { - MDeformVert *dv = NULL; + const MDeformVert *dv = nullptr; /* get the deform vertices corresponding to the vertnum */ if (ob->type == OB_MESH) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); if (me->edit_mesh) { BMEditMesh *em = me->edit_mesh; @@ -926,18 +946,19 @@ static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) BMVert *eve; BM_mesh_elem_table_ensure(em->bm, BM_VERT); eve = BM_vert_at_index(em->bm, vertnum); - dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + dv = static_cast<const MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); } else { return 0.0f; } } else { - if (me->dvert) { + const Span<MDeformVert> dverts = me->deform_verts(); + if (!dverts.is_empty()) { if (vertnum >= me->totvert) { return 0.0f; } - dv = &me->dvert[vertnum]; + dv = &dverts[vertnum]; } } } @@ -998,7 +1019,7 @@ static void vgroup_select_verts(Object *ob, int select) } if (ob->type == OB_MESH) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); if (me->edit_mesh) { BMEditMesh *em = me->edit_mesh; @@ -1010,7 +1031,8 @@ static void vgroup_select_verts(Object *ob, int select) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + MDeformVert *dv = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); if (BKE_defvert_find_index(dv, def_nr)) { BM_vert_select_set(em->bm, eve, select); } @@ -1027,17 +1049,18 @@ static void vgroup_select_verts(Object *ob, int select) } } else { - if (me->dvert) { + const Span<MDeformVert> dverts = me->deform_verts(); + if (!dverts.is_empty()) { + const bool *hide_vert = (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert"); MVert *mv; - MDeformVert *dv; int i; - mv = me->mvert; - dv = me->dvert; + mv = me->verts_for_write().data(); - for (i = 0; i < me->totvert; i++, mv++, dv++) { - if (!(mv->flag & ME_HIDE)) { - if (BKE_defvert_find_index(dv, def_nr)) { + for (i = 0; i < me->totvert; i++, mv++) { + if (!(hide_vert != nullptr && hide_vert[i])) { + if (BKE_defvert_find_index(&dverts[i], def_nr)) { if (select) { mv->flag |= SELECT; } @@ -1085,12 +1108,13 @@ static void vgroup_duplicate(Object *ob) bDeformGroup *dg, *cdg; char name[sizeof(dg->name)]; MDeformWeight *dw_org, *dw_cpy; - MDeformVert **dvert_array = NULL; + MDeformVert **dvert_array = nullptr; int i, idg, icdg, dvert_tot = 0; ListBase *defbase = BKE_object_defgroup_list_mutable(ob); - dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); + dg = static_cast<bDeformGroup *>( + BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1)); if (!dg) { return; } @@ -1112,8 +1136,8 @@ static void vgroup_duplicate(Object *ob) BKE_object_defgroup_active_index_set(ob, BLI_listbase_count(defbase)); icdg = BKE_object_defgroup_active_index_get(ob) - 1; - /* TODO(campbell): we might want to allow only copy selected verts here? */ - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + /* TODO(@campbellbarton): we might want to allow only copy selected verts here? */ + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, false); if (dvert_array) { for (i = 0; i < dvert_tot; i++) { @@ -1134,7 +1158,7 @@ static void vgroup_duplicate(Object *ob) static bool vgroup_normalize(Object *ob) { MDeformWeight *dw; - MDeformVert *dv, **dvert_array = NULL; + MDeformVert *dv, **dvert_array = nullptr; int dvert_tot = 0; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; @@ -1145,7 +1169,7 @@ static bool vgroup_normalize(Object *ob) return false; } - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { float weight_max = 0.0f; @@ -1192,21 +1216,18 @@ static bool vgroup_normalize(Object *ob) /* This finds all of the vertices face-connected to vert by an edge and returns a * MEM_allocated array of indices of size count. * count is an int passed by reference so it can be assigned the value of the length here. */ -static int *getSurroundingVerts(Mesh *me, int vert, int *count) +static blender::Vector<int> getSurroundingVerts(Mesh *me, int vert) { - MPoly *mp = me->mpoly; + const MPoly *mp = me->polys().data(); + const MLoop *loops = me->loops().data(); int i = me->totpoly; - /* Instead of looping twice on all polys and loops, and use a temp array, let's rather - * use a BLI_array, with a reasonable starting/reserved size (typically, there are not - * many vertices face-linked to another one, even 8 might be too high...). */ - int *verts = NULL; - BLI_array_declare(verts); - BLI_array_reserve(verts, 8); + blender::Vector<int> verts; + while (i--) { int j = mp->totloop; int first_l = mp->totloop - 1; - MLoop *ml = &me->mloop[mp->loopstart]; + const MLoop *ml = &loops[mp->loopstart]; while (j--) { /* XXX This assume a vert can only be once in a poly, even though * it seems logical to me, not totally sure of that. */ @@ -1220,7 +1241,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) else if (!j) { /* We are on the last corner. */ a = (ml - 1)->v; - b = me->mloop[mp->loopstart].v; + b = loops[mp->loopstart].v; } else { a = (ml - 1)->v; @@ -1228,7 +1249,7 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) } /* Append a and b verts to array, if not yet present. */ - k = BLI_array_len(verts); + k = verts.size(); /* XXX Maybe a == b is enough? */ while (k-- && !(a == b && a == -1)) { if (verts[k] == a) { @@ -1239,10 +1260,10 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) } } if (a != -1) { - BLI_array_append(verts, a); + verts.append(a); } if (b != -1) { - BLI_array_append(verts, b); + verts.append(b); } /* Vert found in this poly, we can go to next one! */ @@ -1253,8 +1274,6 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) mp++; } - /* Do not free the array! */ - *count = BLI_array_len(verts); return verts; } @@ -1305,14 +1324,15 @@ static void getVerticalAndHorizontalChange(const float norm[3], changes[index][1] = len_v3v3(projA, projB); } -/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to - * distToBe distance away from the provided plane strength can change distToBe so that it moves - * towards distToBe by that percentage cp changes how much the weights are adjusted +/** + * By changing nonzero weights, try to move a vertex in `me->mverts` with index 'index' to + * `distToBe` distance away from the provided plane strength can change `distToBe` so that it moves + * towards `distToBe` by that percentage `cp` changes how much the weights are adjusted * to check the distance * - * index is the index of the vertex being moved - * norm and d are the plane's properties for the equation: ax + by + cz + d = 0 - * coord is a point on the plane + * `index` is the index of the vertex being moved. + * `norm` and `d` are the plane's properties for the equation: `ax + by + cz + d = 0`. + * `coord` is a point on the plane. */ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, Scene *UNUSED(scene), @@ -1333,20 +1353,21 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, Mesh *me_deform; MDeformWeight *dw, *dw_eval; MVert m; - MDeformVert *dvert = me->dvert + index; - MDeformVert *dvert_eval = mesh_eval->dvert + index; + MDeformVert *dvert = me->deform_verts_for_write().data() + index; + MDeformVert *dvert_eval = mesh_eval->deform_verts_for_write().data() + index; int totweight = dvert->totweight; float oldw = 0; float oldPos[3] = {0}; float vc, hc, dist = 0.0f; int i, k; - float(*changes)[2] = MEM_mallocN(sizeof(float[2]) * totweight, "vertHorzChange"); - float *dists = MEM_mallocN(sizeof(float) * totweight, "distance"); + float(*changes)[2] = static_cast<float(*)[2]>( + MEM_mallocN(sizeof(float[2]) * totweight, "vertHorzChange")); + float *dists = static_cast<float *>(MEM_mallocN(sizeof(float) * totweight, "distance")); /* track if up or down moved it closer for each bone */ - bool *upDown = MEM_callocN(sizeof(bool) * totweight, "upDownTracker"); + bool *upDown = static_cast<bool *>(MEM_callocN(sizeof(bool) * totweight, "upDownTracker")); - int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker"); + int *dwIndices = static_cast<int *>(MEM_callocN(sizeof(int) * totweight, "dwIndexTracker")); float distToStart; int bestIndex = 0; bool wasChange; @@ -1356,7 +1377,8 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, do { wasChange = false; me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); - m = me_deform->mvert[index]; + const Span<MVert> verts = me_deform->verts(); + m = verts[index]; copy_v3_v3(oldPos, m.co); distToStart = dot_v3v3(norm, oldPos) + d; @@ -1398,7 +1420,7 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, } dw_eval->weight = dw->weight; me_deform = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); - m = me_deform->mvert[index]; + m = verts[index]; getVerticalAndHorizontalChange( norm, d, coord, oldPos, distToStart, m.co, changes, dists, i); dw->weight = oldw; @@ -1502,25 +1524,26 @@ static void vgroup_fix( Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); int i; - Mesh *me = ob->data; - MVert *mvert = me->mvert; - int *verts = NULL; + Mesh *me = static_cast<Mesh *>(ob->data); + MVert *mvert = me->verts_for_write().data(); if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL)) { return; } for (i = 0; i < me->totvert && mvert; i++, mvert++) { if (mvert->flag & SELECT) { - int count = 0; - if ((verts = getSurroundingVerts(me, i, &count))) { + blender::Vector<int> verts = getSurroundingVerts(me, i); + const int count = verts.size(); + if (!verts.is_empty()) { MVert m; - MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints"); + MVert *p = static_cast<MVert *>(MEM_callocN(sizeof(MVert) * (count), "deformedPoints")); int k; Mesh *me_deform = mesh_get_eval_deform( depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH); + const Span<MVert> verts_deform = me_deform->verts(); k = count; while (k--) { - p[k] = me_deform->mvert[verts[k]]; + p[k] = verts_deform[verts[k]]; } if (count >= 3) { @@ -1528,7 +1551,7 @@ static void vgroup_fix( float coord[3]; float norm[3]; getSingleCoordinate(p, count, coord); - m = me_deform->mvert[i]; + m = verts_deform[i]; sub_v3_v3v3(norm, m.co, coord); mag = normalize_v3(norm); if (mag) { /* zeros fix */ @@ -1539,7 +1562,6 @@ static void vgroup_fix( } } - MEM_freeN(verts); MEM_freeN(p); } } @@ -1554,7 +1576,7 @@ static void vgroup_levels_subset(Object *ob, const float gain) { MDeformWeight *dw; - MDeformVert *dv, **dvert_array = NULL; + MDeformVert *dv, **dvert_array = nullptr; int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); @@ -1562,7 +1584,7 @@ static void vgroup_levels_subset(Object *ob, (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { @@ -1600,7 +1622,7 @@ static bool vgroup_normalize_all(Object *ob, const bool lock_active, ReportList *reports) { - MDeformVert *dv, **dvert_array = NULL; + MDeformVert *dv, **dvert_array = nullptr; int i, dvert_tot = 0; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; @@ -1611,7 +1633,7 @@ static bool vgroup_normalize_all(Object *ob, return false; } - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -1619,7 +1641,7 @@ static bool vgroup_normalize_all(Object *ob, bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot); bool changed = false; - if ((lock_active == true) && (lock_flags != NULL) && (def_nr < defbase_tot)) { + if ((lock_active == true) && (lock_flags != nullptr) && (def_nr < defbase_tot)) { lock_flags[def_nr] = true; } @@ -1682,7 +1704,7 @@ static const EnumPropertyItem vgroup_lock_actions[] = { {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"}, {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"}, {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; enum { @@ -1701,7 +1723,7 @@ static const EnumPropertyItem vgroup_lock_mask[] = { 0, "Invert Unselected", "Apply the opposite of Lock/Unlock to unselected vertex groups"}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; static bool *vgroup_selected_get(Object *ob) @@ -1720,7 +1742,7 @@ static bool *vgroup_selected_get(Object *ob) } } else { - mask = MEM_callocN(defbase_tot * sizeof(bool), __func__); + mask = static_cast<bool *>(MEM_callocN(defbase_tot * sizeof(bool), __func__)); } const int actdef = BKE_object_defgroup_active_index_get(ob); @@ -1734,7 +1756,7 @@ static bool *vgroup_selected_get(Object *ob) static void vgroup_lock_all(Object *ob, int action, int mask) { bDeformGroup *dg; - bool *selected = NULL; + bool *selected = nullptr; int i; if (mask != VGROUP_MASK_ALL) { @@ -1745,7 +1767,7 @@ static void vgroup_lock_all(Object *ob, int action, int mask) if (action == VGROUP_TOGGLE) { action = VGROUP_LOCK; - for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { + for (dg = static_cast<bDeformGroup *>(defbase->first), i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_INVERT_UNSELECTED: case VGROUP_MASK_SELECTED: @@ -1758,7 +1780,8 @@ static void vgroup_lock_all(Object *ob, int action, int mask) continue; } break; - default:; + default: + break; } if (dg->flag & DG_LOCK_WEIGHT) { @@ -1768,7 +1791,7 @@ static void vgroup_lock_all(Object *ob, int action, int mask) } } - for (dg = defbase->first, i = 0; dg; dg = dg->next, i++) { + for (dg = static_cast<bDeformGroup *>(defbase->first), i = 0; dg; dg = dg->next, i++) { switch (mask) { case VGROUP_MASK_SELECTED: if (!selected[i]) { @@ -1780,7 +1803,8 @@ static void vgroup_lock_all(Object *ob, int action, int mask) continue; } break; - default:; + default: + break; } switch (action) { @@ -1813,14 +1837,14 @@ static void vgroup_invert_subset(Object *ob, const bool auto_remove) { MDeformWeight *dw; - MDeformVert *dv, **dvert_array = NULL; + MDeformVert *dv, **dvert_array = nullptr; int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { for (int i = 0; i < dvert_tot; i++) { @@ -1870,10 +1894,10 @@ static void vgroup_smooth_subset(Object *ob, const float fac_expand) { const float ifac = 1.0f - fac; - MDeformVert **dvert_array = NULL; + MDeformVert **dvert_array = nullptr; int dvert_tot = 0; - int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count); - float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count); + blender::Array<int, 32> vgroup_subset_map(subset_count); + blender::Array<float, 32> vgroup_subset_weights(subset_count); const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; @@ -1885,8 +1909,8 @@ static void vgroup_smooth_subset(Object *ob, const float iexpand = 1.0f - expand; BMEditMesh *em = BKE_editmesh_from_object(ob); - BMesh *bm = em ? em->bm : NULL; - Mesh *me = em ? NULL : ob->data; + BMesh *bm = em ? em->bm : nullptr; + Mesh *me = em ? nullptr : static_cast<Mesh *>(ob->data); MeshElemMap *emap; int *emap_mem; @@ -1900,31 +1924,37 @@ static void vgroup_smooth_subset(Object *ob, uint *verts_used; STACK_DECLARE(verts_used); - BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map); - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count); + BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map.data()); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, false); + vgroup_subset_weights.fill(0.0f); if (bm) { BM_mesh_elem_table_ensure(bm, BM_VERT); BM_mesh_elem_index_ensure(bm, BM_VERT); - emap = NULL; - emap_mem = NULL; + emap = nullptr; + emap_mem = nullptr; } else { - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge); + BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->edges().data(), me->totvert, me->totedge); } - weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__); - weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__); + weight_accum_prev = static_cast<float *>( + MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__)); + weight_accum_curr = static_cast<float *>( + MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__)); - verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__); + verts_used = static_cast<uint *>(MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__)); STACK_INIT(verts_used, dvert_tot); #define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true) #define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true) -#define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true) + const bool *hide_vert = me ? (const bool *)CustomData_get_layer_named( + &me->vdata, CD_PROP_BOOL, ".hide_vert") : + nullptr; + +#define IS_ME_VERT_READ(v) (use_hide ? !(hide_vert && hide_vert[v]) : true) #define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true) /* initialize used verts */ @@ -1945,13 +1975,15 @@ static void vgroup_smooth_subset(Object *ob, } } else { + const Span<MVert> verts = me->verts(); + const blender::Span<MEdge> edges = me->edges(); for (int i = 0; i < dvert_tot; i++) { - const MVert *v = &me->mvert[i]; + const MVert *v = &verts[i]; if (IS_ME_VERT_WRITE(v)) { for (int j = 0; j < emap[i].count; j++) { - const MEdge *e = &me->medge[emap[i].indices[j]]; - const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1]; - if (IS_ME_VERT_READ(v_other)) { + const MEdge *e = &edges[emap[i].indices[j]]; + const int i_other = (e->v1 == i) ? e->v2 : e->v1; + if (IS_ME_VERT_READ(i_other)) { STACK_PUSH(verts_used, i); break; } @@ -2018,16 +2050,15 @@ static void vgroup_smooth_subset(Object *ob, } else { int j; + const blender::Span<MEdge> edges = me->edges(); /* checked already */ - BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i])); + BLI_assert(IS_ME_VERT_WRITE(&me->verts()[i])); for (j = 0; j < emap[i].count; j++) { - MEdge *e = &me->medge[emap[i].indices[j]]; + const MEdge *e = &edges[emap[i].indices[j]]; const int i_other = (e->v1 == i ? e->v2 : e->v1); - MVert *v_other = &me->mvert[i_other]; - - if (IS_ME_VERT_READ(v_other)) { + if (IS_ME_VERT_READ(i_other)) { WEIGHT_ACCUMULATE; } } @@ -2072,9 +2103,9 @@ static void vgroup_smooth_subset(Object *ob, MEM_freeN(dvert_array); } - /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */ + /* not so efficient to get 'dvert_array' again just so unselected verts are nullptr'd */ if (use_mirror) { - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, true); ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot); if (dvert_array) { MEM_freeN(dvert_array); @@ -2090,7 +2121,8 @@ static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2) * less than, equal to, or greater than zero corresponding to whether its first argument is * considered less than, equal to, or greater than its second argument. * This does the opposite. */ - const struct MDeformWeight *dw1 = a1, *dw2 = a2; + const MDeformWeight *dw1 = static_cast<const MDeformWeight *>(a1); + const MDeformWeight *dw2 = static_cast<const MDeformWeight *>(a2); if (dw1->weight < dw2->weight) { return 1; @@ -2114,12 +2146,12 @@ static int vgroup_limit_total_subset(Object *ob, const int subset_count, const int max_weights) { - MDeformVert *dv, **dvert_array = NULL; + MDeformVert *dv, **dvert_array = nullptr; int i, dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); int remove_tot = 0; - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { int num_to_drop = 0; @@ -2141,7 +2173,8 @@ static int vgroup_limit_total_subset(Object *ob, if (num_to_drop > 0) { /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end * sort the tail, then copy only the truncated array back to dv->dw */ - dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__); + dw_temp = static_cast<MDeformWeight *>( + MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__)); bone_count = 0; non_bone_count = 0; for (j = 0; j < dv->totweight; j++) { @@ -2164,7 +2197,8 @@ static int vgroup_limit_total_subset(Object *ob, dv->totweight -= num_to_drop; /* Do we want to clean/normalize here? */ MEM_freeN(dv->dw); - dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight); + dv->dw = static_cast<MDeformWeight *>( + MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight)); remove_tot += num_to_drop; } else { @@ -2185,14 +2219,14 @@ static void vgroup_clean_subset(Object *ob, const float epsilon, const bool keep_single) { - MDeformVert **dvert_array = NULL; + MDeformVert **dvert_array = nullptr; int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { if (use_mirror && use_vert_sel) { @@ -2215,13 +2249,13 @@ static void vgroup_quantize_subset(Object *ob, const int UNUSED(subset_count), const int steps) { - MDeformVert **dvert_array = NULL; + MDeformVert **dvert_array = nullptr; int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + ED_vgroup_parray_alloc(static_cast<ID *>(ob->data), &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { const float steps_fl = steps; @@ -2342,9 +2376,9 @@ void ED_vgroup_mirror(Object *ob, def_nr) BMVert *eve, *eve_mirr; - MDeformVert *dvert, *dvert_mirr; + MDeformVert *dvert_mirr; char sel, sel_mirr; - int *flip_map = NULL, flip_map_len; + int *flip_map = nullptr, flip_map_len; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; int totmirr = 0, totfail = 0; @@ -2353,7 +2387,7 @@ void ED_vgroup_mirror(Object *ob, const ListBase *defbase = BKE_object_defgroup_list(ob); if ((mirror_weights == false && flip_vgroups == false) || - (BLI_findlink(defbase, def_nr) == NULL)) { + (BLI_findlink(defbase, def_nr) == nullptr)) { return; } @@ -2361,21 +2395,21 @@ void ED_vgroup_mirror(Object *ob, flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) : BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr); - BLI_assert(flip_map != NULL); + BLI_assert(flip_map != nullptr); - if (flip_map == NULL) { + if (flip_map == nullptr) { /* something went wrong!, possibly no groups */ return; } } else { - flip_map = NULL; + flip_map = nullptr; flip_map_len = 0; } /* only the active group */ if (ob->type == OB_MESH) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; if (em) { @@ -2400,8 +2434,10 @@ void ED_vgroup_mirror(Object *ob, sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT); if ((sel || sel_mirr) && (eve != eve_mirr)) { - dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); - dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset); + MDeformVert *dvert = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); + dvert_mirr = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset)); VGROUP_MIRR_OP; totmirr++; @@ -2422,11 +2458,11 @@ void ED_vgroup_mirror(Object *ob, } else { /* object mode / weight paint */ - MVert *mv, *mv_mirr; + const MVert *mv, *mv_mirr; int vidx, vidx_mirr; const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - if (me->dvert == NULL) { + if (me->deform_verts().is_empty()) { goto cleanup; } @@ -2435,12 +2471,14 @@ void ED_vgroup_mirror(Object *ob, } BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); + const MVert *verts = me->verts().data(); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); - for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) { + for (vidx = 0, mv = verts; vidx < me->totvert; vidx++, mv++) { if (!BLI_BITMAP_TEST(vert_tag, vidx)) { - if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) { + if ((vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology)) != -1) { if (vidx != vidx_mirr) { - mv_mirr = &me->mvert[vidx_mirr]; + mv_mirr = &verts[vidx_mirr]; if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) { if (use_vert_sel) { @@ -2449,8 +2487,8 @@ void ED_vgroup_mirror(Object *ob, } if (sel || sel_mirr) { - dvert = &me->dvert[vidx]; - dvert_mirr = &me->dvert[vidx_mirr]; + MDeformVert *dvert = &dverts[vidx]; + dvert_mirr = &dvert[vidx_mirr]; VGROUP_MIRR_OP; totmirr++; @@ -2477,7 +2515,7 @@ void ED_vgroup_mirror(Object *ob, int pntsu_half; /* half but found up odd value */ - if (lt->pntsu == 1 || lt->dvert == NULL) { + if (lt->pntsu == 1 || lt->dvert == nullptr) { goto cleanup; } @@ -2503,7 +2541,7 @@ void ED_vgroup_mirror(Object *ob, sel_mirr = bp_mirr->f1 & SELECT; if (sel || sel_mirr) { - dvert = <->dvert[i1]; + MDeformVert *dvert = <->dvert[i1]; dvert_mirr = <->dvert[i2]; VGROUP_MIRR_OP; @@ -2537,7 +2575,8 @@ cleanup: static void vgroup_delete_active(Object *ob) { const ListBase *defbase = BKE_object_defgroup_list(ob); - bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); + bDeformGroup *dg = static_cast<bDeformGroup *>( + BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1)); if (!dg) { return; } @@ -2556,7 +2595,7 @@ static void vgroup_assign_verts(Object *ob, const float weight) } if (ob->type == OB_MESH) { - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); if (me->edit_mesh) { BMEditMesh *em = me->edit_mesh; @@ -2576,7 +2615,8 @@ static void vgroup_assign_verts(Object *ob, const float weight) if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { MDeformVert *dv; MDeformWeight *dw; - dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */ + dv = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); /* can be nullptr */ dw = BKE_defvert_ensure_index(dv, def_nr); if (dw) { dw->weight = weight; @@ -2585,14 +2625,12 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } else { - if (!me->dvert) { - BKE_object_defgroup_data_create(&me->id); - } - - MVert *mv = me->mvert; - MDeformVert *dv = me->dvert; + const Span<MVert> verts = me->verts(); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + MDeformVert *dv = dverts.data(); - for (int i = 0; i < me->totvert; i++, mv++, dv++) { + for (int i = 0; i < me->totvert; i++, dv++) { + const MVert *mv = &verts[i]; if (mv->flag & SELECT) { MDeformWeight *dw; dw = BKE_defvert_ensure_index(dv, def_nr); @@ -2609,7 +2647,7 @@ static void vgroup_assign_verts(Object *ob, const float weight) BPoint *bp; int a, tot; - if (lt->dvert == NULL) { + if (lt->dvert == nullptr) { BKE_object_defgroup_data_create(<->id); } @@ -2648,8 +2686,8 @@ static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob) } /* Data checks. */ - const ID *data = ob->data; - if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { + const ID *data = static_cast<const ID *>(ob->data); + if (data == nullptr || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { CTX_wm_operator_poll_msg_set(C, "Object type \"%s\" does not have editable data"); return false; } @@ -2705,8 +2743,8 @@ static bool vertex_group_mesh_with_dvert_poll(bContext *C) return false; } - Mesh *me = ob->data; - if (me->dvert == NULL) { + Mesh *me = static_cast<Mesh *>(ob->data); + if (me->deform_verts().is_empty()) { CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data"); return false; } @@ -2796,7 +2834,7 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) const int def_nr = BKE_object_defgroup_active_index_get(ob); if (def_nr != 0) { const ListBase *defbase = BKE_object_defgroup_list(ob); - const bDeformGroup *dg = BLI_findlink(defbase, def_nr - 1); + const bDeformGroup *dg = static_cast<const bDeformGroup *>(BLI_findlink(defbase, def_nr - 1)); if (dg) { return !(dg->flag & DG_LOCK_WEIGHT); } @@ -2900,10 +2938,10 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups"); + PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", false, "All", "Remove all vertex groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_boolean( - ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups"); + ot->srna, "all_unlocked", false, "All Unlocked", "Remove all unlocked vertex groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -2998,8 +3036,9 @@ static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) } else { const ListBase *defbase = BKE_object_defgroup_list(ob); - bDeformGroup *dg = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); - if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) { + bDeformGroup *dg = static_cast<bDeformGroup *>( + BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1)); + if ((dg == nullptr) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) { return OPERATOR_CANCELLED; } } @@ -3029,9 +3068,11 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ - prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups"); + prop = RNA_def_boolean( + ot->srna, "use_all_groups", false, "All Groups", "Remove from all groups"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Vertices", "Clear the active group"); + prop = RNA_def_boolean( + ot->srna, "use_all_verts", false, "All Vertices", "Clear the active group"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -3050,7 +3091,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) } vgroup_select_verts(ob, 1); - DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; @@ -3082,7 +3123,7 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = ED_object_context(C); vgroup_select_verts(ob, 0); - DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); return OPERATOR_FINISHED; @@ -3149,7 +3190,8 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op) float offset = RNA_float_get(op->ptr, "offset"); float gain = RNA_float_get(op->ptr, "gain"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); int subset_count, vgroup_tot; @@ -3236,7 +3278,8 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); bool lock_active = RNA_boolean_get(op->ptr, "lock_active"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); bool changed; int subset_count, vgroup_tot; const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type( @@ -3296,7 +3339,7 @@ static int vertex_group_fix_exec(bContext *C, wmOperator *op) float distToBe = RNA_float_get(op->ptr, "dist"); float strength = RNA_float_get(op->ptr, "strength"); float cp = RNA_float_get(op->ptr, "accuracy"); - ModifierData *md = ob->modifiers.first; + ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first); while (md) { if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { @@ -3385,9 +3428,9 @@ static int vertex_group_lock_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static char *vertex_group_lock_description(struct bContext *UNUSED(C), - struct wmOperatorType *UNUSED(op), - struct PointerRNA *params) +static char *vertex_group_lock_description(bContext *UNUSED(C), + wmOperatorType *UNUSED(op), + PointerRNA *params) { int action = RNA_enum_get(params, "action"); int mask = RNA_enum_get(params, "mask"); @@ -3408,7 +3451,7 @@ static char *vertex_group_lock_description(struct bContext *UNUSED(C), action_str = TIP_("Invert locks of"); break; default: - return NULL; + return nullptr; } switch (mask) { @@ -3437,7 +3480,7 @@ static char *vertex_group_lock_description(struct bContext *UNUSED(C), } break; default: - return NULL; + return nullptr; } return BLI_sprintfN(TIP_("%s %s vertex groups of the active object"), action_str, target_str); @@ -3485,7 +3528,8 @@ static int vertex_group_invert_exec(bContext *C, wmOperator *op) bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign"); bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); int subset_count, vgroup_tot; @@ -3538,7 +3582,8 @@ 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"); - const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + const eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); const float fac_expand = RNA_float_get(op->ptr, "expand"); uint objects_len; @@ -3603,7 +3648,8 @@ static int vertex_group_clean_exec(bContext *C, wmOperator *op) { 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"); + const eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); uint objects_len; Object **objects = object_array_for_wpaint(C, &objects_len); @@ -3670,7 +3716,8 @@ static int vertex_group_quantize_exec(bContext *C, wmOperator *op) Object *ob = ED_object_context(C); const int steps = RNA_int_get(op->ptr, "steps"); - eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); int subset_count, vgroup_tot; @@ -3713,7 +3760,8 @@ void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot) static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) { const int limit = RNA_int_get(op->ptr, "limit"); - const eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); + const eVGroupSelect subset_type = static_cast<eVGroupSelect>( + RNA_enum_get(op->ptr, "group_select_mode")); int remove_multi_count = 0; uint objects_len; @@ -3824,7 +3872,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) RNA_def_boolean( ot->srna, "use_topology", - 0, + false, "Topology Mirror", "Use topology based mirroring (for when both sides of mesh have matching, unique topology)"); } @@ -3908,13 +3956,13 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C, PropertyRNA *UNUSED(prop), bool *r_free) { - if (C == NULL) { + if (C == nullptr) { return DummyRNA_NULL_items; } Object *ob = ED_object_context(C); EnumPropertyItem tmp = {0, "", 0, "", ""}; - EnumPropertyItem *item = NULL; + EnumPropertyItem *item = nullptr; bDeformGroup *def; int a, totitem = 0; @@ -3923,7 +3971,7 @@ static const EnumPropertyItem *vgroup_itemf(bContext *C, } const ListBase *defbase = BKE_object_defgroup_list(ob); - for (a = 0, def = defbase->first; def; def = def->next, a++) { + for (a = 0, def = static_cast<bDeformGroup *>(defbase->first); def; def = def->next, a++) { tmp.value = a; tmp.icon = ICON_GROUP_VERTEX; tmp.identifier = def->name; @@ -3974,11 +4022,13 @@ static char *vgroup_init_remap(Object *ob) { const ListBase *defbase = BKE_object_defgroup_list(ob); int defbase_tot = BLI_listbase_count(defbase); - char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups"); + char *name_array = static_cast<char *>( + MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups")); char *name; name = name_array; - for (const bDeformGroup *def = defbase->first; def; def = def->next) { + for (const bDeformGroup *def = static_cast<const bDeformGroup *>(defbase->first); def; + def = def->next) { BLI_strncpy(name, def->name, MAX_VGROUP_NAME); name += MAX_VGROUP_NAME; } @@ -3988,20 +4038,21 @@ static char *vgroup_init_remap(Object *ob) static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) { - MDeformVert *dvert = NULL; + MDeformVert *dvert = nullptr; const bDeformGroup *def; const ListBase *defbase = BKE_object_defgroup_list(ob); int defbase_tot = BLI_listbase_count(defbase); /* Needs a dummy index at the start. */ - int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups"); + int *sort_map_update = static_cast<int *>( + MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__)); int *sort_map = sort_map_update + 1; const char *name; int i; name = name_array; - for (def = defbase->first, i = 0; def; def = def->next, i++) { + for (def = static_cast<const bDeformGroup *>(defbase->first), i = 0; def; def = def->next, i++) { sort_map[i] = BLI_findstringindex(defbase, name, offsetof(bDeformGroup, name)); name += MAX_VGROUP_NAME; @@ -4018,7 +4069,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) BMVert *eve; BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + dvert = static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); if (dvert->totweight) { BKE_defvert_remap(dvert, sort_map, defbase_tot); } @@ -4036,7 +4087,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) /* Grease pencil stores vertex groups separately for each stroke, * so remap each stroke's weights separately. */ if (ob->type == OB_GPENCIL) { - bGPdata *gpd = ob->data; + bGPdata *gpd = static_cast<bGPdata *>(ob->data); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { @@ -4055,7 +4106,7 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) } } else { - BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot); + BKE_object_defgroup_array_get(static_cast<ID *>(ob->data), &dvert, &dvert_tot); /* Create as necessary. */ if (dvert) { @@ -4088,8 +4139,8 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) { - const bDeformGroup *def_a = def_a_ptr; - const bDeformGroup *def_b = def_b_ptr; + const bDeformGroup *def_a = static_cast<const bDeformGroup *>(def_a_ptr); + const bDeformGroup *def_b = static_cast<const bDeformGroup *>(def_b_ptr); return BLI_strcasecmp_natural(def_a->name, def_b->name); } @@ -4100,22 +4151,22 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) */ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) { - if (bonebase == NULL) { + if (bonebase == nullptr) { Object *armobj = BKE_modifiers_is_deformed_by_armature(ob); - if (armobj != NULL) { - bArmature *armature = armobj->data; + if (armobj != nullptr) { + bArmature *armature = static_cast<bArmature *>(armobj->data); bonebase = &armature->bonebase; } } ListBase *defbase = BKE_object_defgroup_list_mutable(ob); - if (bonebase != NULL) { + if (bonebase != nullptr) { Bone *bone; - for (bone = bonebase->last; bone; bone = bone->prev) { + for (bone = static_cast<Bone *>(bonebase->last); bone; bone = bone->prev) { bDeformGroup *dg = BKE_object_defgroup_find_name(ob, bone->name); vgroup_sort_bone_hierarchy(ob, &bone->childbase); - if (dg != NULL) { + if (dg != nullptr) { BLI_remlink(defbase, dg); BLI_addhead(defbase, dg); } @@ -4146,7 +4197,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) BLI_listbase_sort(defbase, vgroup_sort_name); break; case SORT_TYPE_BONEHIERARCHY: - vgroup_sort_bone_hierarchy(ob, NULL); + vgroup_sort_bone_hierarchy(ob, nullptr); break; } @@ -4170,7 +4221,7 @@ void OBJECT_OT_vertex_group_sort(wmOperatorType *ot) static const EnumPropertyItem vgroup_sort_type[] = { {SORT_TYPE_NAME, "NAME", 0, "Name", ""}, {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; ot->name = "Sort Vertex Groups"; @@ -4203,7 +4254,8 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) ListBase *defbase = BKE_object_defgroup_list_mutable(ob); - def = BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1); + def = static_cast<bDeformGroup *>( + BLI_findlink(defbase, BKE_object_defgroup_active_index_get(ob) - 1)); if (!def) { return OPERATOR_CANCELLED; } @@ -4231,7 +4283,7 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) static const EnumPropertyItem vgroup_slot_move[] = { {-1, "UP", 0, "Up", ""}, {1, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, + {0, nullptr, 0, nullptr, nullptr}, }; /* identifiers */ @@ -4264,7 +4316,7 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { MDeformVert *dvert_act; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; int i; @@ -4274,13 +4326,14 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) BMVert *eve, *eve_act; dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act); - if (dvert_act == NULL) { + if (dvert_act == nullptr) { return; } BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) { - MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + MDeformVert *dvert_dst = static_cast<MDeformVert *>( + BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)); BKE_defvert_copy_index(dvert_dst, def_nr, dvert_act, def_nr); @@ -4299,13 +4352,16 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) int v_act; dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act); - if (dvert_act == NULL) { + if (dvert_act == nullptr) { return; } - dv = me->dvert; + const Span<MVert> verts = me->verts(); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + + dv = dverts.data(); for (i = 0; i < me->totvert; i++, dv++) { - if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) { + if ((verts[i].flag & SELECT) && (dv != dvert_act)) { BKE_defvert_copy_index(dv, def_nr, dvert_act, def_nr); @@ -4324,7 +4380,7 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr) { const ListBase *defbase = BKE_object_defgroup_list(ob); - bDeformGroup *dg = BLI_findlink(defbase, def_nr); + bDeformGroup *dg = static_cast<bDeformGroup *>(BLI_findlink(defbase, def_nr)); if (!dg) { BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index"); @@ -4381,7 +4437,7 @@ void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot) "Index of source weight in active vertex group", -1, INT_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); } /** \} */ @@ -4431,7 +4487,7 @@ void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot) "Index of source weight in active vertex group", -1, INT_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); } /** \} */ @@ -4478,7 +4534,7 @@ void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot) "Index of source weight in active vertex group", -1, INT_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + RNA_def_property_flag(prop, (PropertyFlag)(PROP_SKIP_SAVE | PROP_HIDDEN)); } /** \} */ @@ -4491,7 +4547,7 @@ static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *U { Object *ob = ED_object_context(C); ToolSettings *ts = CTX_data_tool_settings(C); - eVGroupSelect subset_type = ts->vgroupsubset; + eVGroupSelect subset_type = static_cast<eVGroupSelect>(ts->vgroupsubset); bool changed; changed = vgroup_normalize_active_vertex(ob, subset_type); @@ -4530,7 +4586,7 @@ static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); ToolSettings *ts = CTX_data_tool_settings(C); - eVGroupSelect subset_type = ts->vgroupsubset; + eVGroupSelect subset_type = static_cast<eVGroupSelect>(ts->vgroupsubset); vgroup_copy_active_to_sel(ob, subset_type); |