diff options
author | Sergey Sharybin <sergey@blender.org> | 2022-10-07 15:52:28 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey@blender.org> | 2022-10-07 15:55:23 +0300 |
commit | 7383c6c309ca7c474253b7e50cc5042e23e2eb40 (patch) | |
tree | e5583c8951015df2d4765ba695fcc2e759d47aa1 /source/blender/editors/object | |
parent | a56a90a8e2f3f029b9828ffaea21edc3e6679014 (diff) | |
parent | 87ef423e6ebdb90e0e8937b7e749d470a000b3e4 (diff) |
Merge branch 'master' into tracking_toolstracking_tools
Diffstat (limited to 'source/blender/editors/object')
25 files changed, 1567 insertions, 827 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..3ce39b695e0 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 * \{ */ @@ -280,7 +287,7 @@ void ED_object_rotation_from_quat(float rot[3], const float viewquat[4], const c } case 'Y': { quat_to_eul(rot, viewquat); - rot[0] -= (float)M_PI_2; + rot[0] -= float(M_PI_2); break; } case 'Z': { @@ -365,8 +372,8 @@ float ED_object_new_primitive_matrix(bContext *C, /** \name Add Object Operator * \{ */ -static void view_align_update(struct Main *UNUSED(main), - struct Scene *UNUSED(scene), +static void view_align_update(struct Main * /*main*/, + struct Scene * /*scene*/, struct PointerRNA *ptr) { RNA_struct_idprops_unset(ptr, "rotation"); @@ -602,7 +609,8 @@ 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); + BKE_view_layer_synced_ensure(scene, 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); } @@ -612,17 +620,18 @@ Object *ED_object_add_type_with_obdata(bContext *C, Object *ob; if (obdata != nullptr) { BLI_assert(type == BKE_object_obdata_to_type(obdata)); - ob = BKE_object_add_for_data(bmain, view_layer, type, name, obdata, true); + ob = BKE_object_add_for_data(bmain, scene, view_layer, type, name, obdata, true); const short *materials_len_p = BKE_id_material_len_p(obdata); if (materials_len_p && *materials_len_p > 0) { BKE_object_materials_test(bmain, ob, static_cast<ID *>(ob->data)); } } else { - ob = BKE_object_add(bmain, view_layer, type, name); + ob = BKE_object_add(bmain, scene, view_layer, type, name); } - Base *ob_base_act = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *ob_base_act = BKE_view_layer_active_base_get(view_layer); /* 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 +659,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 +992,8 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } bool newob = false; - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, 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 +1102,8 @@ 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); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; @@ -1328,21 +1338,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: { @@ -1465,7 +1475,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void object_add_ui(bContext *UNUSED(C), wmOperator *op) +static void object_add_ui(bContext * /*C*/, wmOperator *op) { uiLayout *layout = op->layout; @@ -1984,7 +1994,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 +2033,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 +2045,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 +2061,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 +2071,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; } @@ -2527,6 +2538,7 @@ static void make_object_duplilist_real(bContext *C, } BKE_collection_object_add_from(bmain, scene, base->object, ob_dst); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst); BLI_assert(base_dst != nullptr); @@ -2763,47 +2775,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); @@ -2865,6 +2836,7 @@ static Base *duplibase_for_convert( DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); BKE_collection_object_add_from(bmain, scene, ob, obn); + BKE_view_layer_synced_ensure(scene, view_layer); Base *basen = BKE_view_layer_base_find(view_layer, obn); ED_object_base_select(basen, BA_SELECT); ED_object_base_select(base, BA_DESELECT); @@ -2922,7 +2894,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; @@ -3185,16 +3157,14 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_mesh_edges_set_draw_render(me_eval); BKE_object_material_from_eval_data(bmain, newob, &me_eval->id); Mesh *new_mesh = (Mesh *)newob->data; - BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob); if (do_merge_customdata) { BKE_mesh_merge_customdata_for_apply_modifier(new_mesh); } /* 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 +3242,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 +3277,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) { @@ -3337,7 +3307,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) baseob = BKE_mball_basis_find(scene, ob); if (ob != baseob) { - /* if motherball is converting it would be marked as done later */ + /* If mother-ball is converting it would be marked as done later. */ ob->flag |= OB_DONE; } @@ -3348,21 +3318,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 +3373,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 +3447,15 @@ 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 { + BKE_view_layer_synced_ensure(scene, view_layer); + Object *object = BKE_view_layer_active_object_get(view_layer); + if (object->flag & OB_DONE) { + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, object); + } } DEG_relations_tag_update(bmain); @@ -3501,7 +3467,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void object_convert_ui(bContext *UNUSED(C), wmOperator *op) +static void object_convert_ui(bContext * /*C*/, wmOperator *op) { uiLayout *layout = op->layout; @@ -3544,12 +3510,12 @@ 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, - "Keep Original", - "Keep original objects instead of replacing them"); + prop = RNA_def_boolean(ot->srna, + "keep_original", + false, + "Keep Original", + "Keep original objects instead of replacing them"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_OBJECT); RNA_def_boolean( ot->srna, @@ -3600,7 +3566,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,10 +3578,14 @@ 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); + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, ob); - if ((base != nullptr) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) { + if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { BKE_collection_object_add_from(bmain, scene, ob, obn); } else { @@ -3622,8 +3593,9 @@ static Base *object_add_duplicate_internal(Main *bmain, BKE_collection_object_add(bmain, layer_collection->collection, obn); } + BKE_view_layer_synced_ensure(scene, view_layer); 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 +3626,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 +3660,77 @@ 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 */ + BKE_view_layer_synced_ensure(scene, view_layer); + if (BKE_view_layer_active_base_get(view_layer) == 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; + BKE_view_layer_synced_ensure(scene, view_layer); + 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 +3812,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"); @@ -3821,7 +3826,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) /* object_add_duplicate_internal() doesn't deselect other objects, unlike object_add_common() or * BKE_view_layer_base_deselect_all(). */ - ED_object_base_deselect_all(view_layer, nullptr, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, nullptr, SEL_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); @@ -3898,13 +3903,15 @@ void OBJECT_OT_add_named(wmOperatorType *ot) static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = reinterpret_cast<Object *>( WM_operator_properties_id_lookup_from_name_or_session_uuid(bmain, op->ptr, ID_OB)); if (!ob) { - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + ob = BKE_view_layer_active_object_get(view_layer); } if (ob == nullptr) { @@ -3976,7 +3983,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..781866db6a0 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, @@ -417,11 +419,13 @@ static bool is_noncolor_pass(eScenePassType pass_type) } /* if all is good tag image and return true */ -static bool bake_object_check(ViewLayer *view_layer, +static bool bake_object_check(const Scene *scene, + ViewLayer *view_layer, Object *ob, const eBakeTarget target, ReportList *reports) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base == NULL) { @@ -447,14 +451,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; } } @@ -592,6 +593,7 @@ static bool bake_pass_filter_check(eScenePassType pass_type, /* before even getting in the bake function we check for some basic errors */ static bool bake_objects_check(Main *bmain, + const Scene *scene, ViewLayer *view_layer, Object *ob, ListBase *selected_objects, @@ -607,7 +609,7 @@ static bool bake_objects_check(Main *bmain, if (is_selected_to_active) { int tot_objects = 0; - if (!bake_object_check(view_layer, ob, target, reports)) { + if (!bake_object_check(scene, view_layer, ob, target, reports)) { return false; } @@ -641,7 +643,7 @@ static bool bake_objects_check(Main *bmain, } for (link = selected_objects->first; link; link = link->next) { - if (!bake_object_check(view_layer, link->ptr.data, target, reports)) { + if (!bake_object_check(scene, view_layer, link->ptr.data, target, reports)) { return false; } } @@ -935,23 +937,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 +974,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 +991,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 +1002,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 +1029,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; + uint l = lt->tri[j]; + uint 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 +1108,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 +1161,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 +1267,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 +1291,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); @@ -1319,7 +1412,8 @@ static int bake(const BakeAPIRender *bkr, else { ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage); ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; - ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_cage_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); } } } @@ -1419,7 +1513,8 @@ static int bake(const BakeAPIRender *bkr, highpoly[i].ob = ob_iter; highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); highpoly[i].ob_eval->visibility_flag &= ~OB_HIDE_RENDER; - highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + highpoly[i].ob_eval->base_flag |= (BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false); /* Low-poly to high-poly transformation matrix. */ @@ -1435,10 +1530,11 @@ static int bake(const BakeAPIRender *bkr, if (ob_cage != NULL) { ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; - ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_cage_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | + BASE_ENABLED_RENDER); } ob_low_eval->visibility_flag |= OB_HIDE_RENDER; - ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); + ob_low_eval->base_flag &= ~(BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT | BASE_ENABLED_RENDER); /* populate the pixel arrays with the corresponding face data for each high poly object */ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.pixels_num, @@ -1719,6 +1815,7 @@ static int bake_exec(bContext *C, wmOperator *op) } if (!bake_objects_check(bkr.main, + bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, @@ -1772,6 +1869,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa } if (!bake_objects_check(bkr->main, + bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 39951c2ab6e..53e1a75cba0 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,8 @@ 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); + BKE_view_layer_synced_ensure(scene, 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..fa9ded0f989 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -31,6 +31,7 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" @@ -50,6 +51,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" @@ -112,7 +114,7 @@ ListBase *ED_object_constraint_list_from_constraint(Object *ob, } /* try object constraints first */ - if ((BLI_findindex(&ob->constraints, con) != -1)) { + if (BLI_findindex(&ob->constraints, con) != -1) { return &ob->constraints; } @@ -124,7 +126,7 @@ ListBase *ED_object_constraint_list_from_constraint(Object *ob, * NOTE: it's not possible to directly look up the active bone yet, so this will have to do */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if ((BLI_findindex(&pchan->constraints, con) != -1)) { + if (BLI_findindex(&pchan->constraints, con) != -1) { if (r_pchan) { *r_pchan = pchan; @@ -295,10 +297,9 @@ static void test_constraint( if (con->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = con->data; - /* bad: we need a separate set of checks here as poletarget is - * optional... otherwise poletarget must exist too or else - * the constraint is deemed invalid - */ + /* Bad: we need a separate set of checks here as pole-target is optional... + * otherwise pole-target must exist too or else the constraint is deemed invalid. */ + /* default IK check ... */ if (BKE_object_exists_check(bmain, data->tar) == 0) { data->tar = NULL; @@ -2312,12 +2313,14 @@ static bool get_new_constraint_target( /* if still not found, add a new empty to act as a target (if allowed) */ if ((found == false) && (add)) { Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base = BKE_view_layer_active_base_get(view_layer); Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL); + obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL); /* transform cent to global coords for loc */ if (pchanact) { @@ -2335,7 +2338,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_data_transform.c b/source/blender/editors/object/object_data_transform.c index 63513eac965..cb66010c497 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -7,7 +7,7 @@ * Use to transform object origins only. * * This is a small API to store & apply transformations to object data, - * where a transformation matrix can be continually applied ontop of the original values + * where a transformation matrix can be continually applied on top of the original values * so we don't lose precision over time. */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index e5dd9fb2c8b..2e22e3bb00d 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -140,8 +140,10 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, uint *r_objects_len) { ScrArea *area = CTX_wm_area(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob_active = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, 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 +196,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( + scene, view_layer, v3d, r_objects_len, ¶ms); } else { objects = BKE_view_layer_array_selected_objects( @@ -234,7 +236,8 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op) const bool select = RNA_boolean_get(op->ptr, "select"); bool changed = false; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->flag & BASE_HIDDEN) { base->flag &= ~BASE_HIDDEN; changed = true; @@ -252,7 +255,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); @@ -286,8 +289,9 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) bool changed = false; /* Hide selected or unselected objects. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - if (!(base->flag & BASE_VISIBLE_VIEWLAYER)) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + if (!(base->flag & BASE_ENABLED_AND_VISIBLE_IN_DEFAULT_VIEWPORT)) { continue; } @@ -310,7 +314,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_layer_collection_sync(scene, view_layer); + BKE_view_layer_need_resync_tag(view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); @@ -362,10 +366,10 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) } if (toggle) { lc->local_collections_bits ^= v3d->local_collections_uuid; - BKE_layer_collection_local_sync(view_layer, v3d); + BKE_layer_collection_local_sync(scene, view_layer, v3d); } else { - BKE_layer_collection_isolate_local(view_layer, v3d, lc, extend); + BKE_layer_collection_isolate_local(scene, view_layer, v3d, lc, extend); } } else { @@ -381,6 +385,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); LayerCollection *lc_scene = view_layer->layer_collections.first; @@ -399,7 +404,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) } int icon = ICON_NONE; - if (BKE_layer_collection_has_selected_objects(view_layer, lc)) { + if (BKE_layer_collection_has_selected_objects(scene, view_layer, lc)) { icon = ICON_LAYER_ACTIVE; } else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) { @@ -701,14 +706,16 @@ 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); + BKE_view_layer_synced_ensure(scene, view_layer); + Object *obedit = BKE_view_layer_edit_object_get(view_layer); if (obedit == NULL) { return false; } bool changed = false; const short obedit_type = obedit->type; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; if ((ob->type == obedit_type) && (ob->mode & OB_MODE_EDIT)) { changed |= ED_object_editmode_exit_ex(bmain, scene, base->object, flag); @@ -841,7 +848,8 @@ 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); + BKE_view_layer_synced_ensure(scene, 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); @@ -867,7 +875,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA); if ((obact->mode & mode_flag) == 0) { - FOREACH_OBJECT_BEGIN (view_layer, ob) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob) { if ((ob != obact) && (ob->type == obact->type)) { ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); } @@ -889,13 +897,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 +961,8 @@ static int posemode_exec(bContext *C, wmOperator *op) } { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + BKE_view_layer_synced_ensure(scene, 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; @@ -963,7 +972,7 @@ static int posemode_exec(bContext *C, wmOperator *op) if (is_mode_set) { bool ok = ED_object_posemode_exit(C, obact); if (ok) { - FOREACH_OBJECT_BEGIN (view_layer, ob) { + FOREACH_OBJECT_BEGIN (scene, view_layer, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) { ED_object_posemode_exit_ex(bmain, ob); } @@ -1244,7 +1253,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 +1325,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 +1478,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; @@ -1479,9 +1486,11 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) /* For modes that only use an active object, don't handle the whole selection. */ { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); - if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { + BKE_view_layer_synced_ensure(scene, 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 +1527,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; } @@ -1548,8 +1561,10 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) static bool shade_poll(bContext *C) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, 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..e85947534cd 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; } @@ -935,6 +934,242 @@ void OBJECT_OT_gpencil_modifier_copy_to_selected(wmOperatorType *ot) gpencil_edit_modifier_properties(ot); } +/************************* Time Offset Advanced Modifier *******************************/ + +static bool time_segment_poll(bContext *C) +{ + return gpencil_edit_modifier_poll_generic(C, &RNA_TimeGpencilModifier, 0, false); +} + +static bool time_segment_name_exists_fn(void *arg, const char *name) +{ + const TimeGpencilModifierData *gpmd = (const TimeGpencilModifierData *)arg; + for (int i = 0; i < gpmd->segments_len; i++) { + if (STREQ(gpmd->segments[i].name, name) && gpmd->segments[i].name != name) { + return true; + } + } + return false; +} + +static int time_segment_add_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)gpencil_edit_modifier_property_get( + op, ob, eGpencilModifierType_Time); + if (gpmd == NULL) { + return OPERATOR_CANCELLED; + } + const int new_active_index = gpmd->segment_active_index + 1; + TimeGpencilModifierSegment *new_segments = MEM_malloc_arrayN( + gpmd->segments_len + 1, sizeof(TimeGpencilModifierSegment), __func__); + + if (gpmd->segments_len != 0) { + /* Copy the segments before the new segment. */ + memcpy(new_segments, gpmd->segments, sizeof(TimeGpencilModifierSegment) * new_active_index); + /* Copy the segments after the new segment. */ + memcpy(new_segments + new_active_index + 1, + gpmd->segments + new_active_index, + sizeof(TimeGpencilModifierSegment) * (gpmd->segments_len - new_active_index)); + } + + /* Create the new segment. */ + TimeGpencilModifierSegment *ds = &new_segments[new_active_index]; + memcpy( + ds, DNA_struct_default_get(TimeGpencilModifierSegment), sizeof(TimeGpencilModifierSegment)); + BLI_uniquename_cb( + time_segment_name_exists_fn, gpmd, DATA_("Segment"), '.', ds->name, sizeof(ds->name)); + ds->gpmd = gpmd; + + MEM_SAFE_FREE(gpmd->segments); + gpmd->segments = new_segments; + gpmd->segments_len++; + gpmd->segment_active_index++; + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int time_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) { + return time_segment_add_exec(C, op); + } + return OPERATOR_CANCELLED; +} + +void GPENCIL_OT_time_segment_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Segment"; + ot->description = "Add a segment to the time modifier"; + ot->idname = "GPENCIL_OT_time_segment_add"; + + /* api callbacks */ + ot->poll = time_segment_poll; + ot->invoke = time_segment_add_invoke; + ot->exec = time_segment_add_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} + +static int time_segment_remove_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + + TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)gpencil_edit_modifier_property_get( + op, ob, eGpencilModifierType_Time); + + if (gpmd->segment_active_index < 0 || gpmd->segment_active_index >= gpmd->segments_len) { + return OPERATOR_CANCELLED; + } + + if (gpmd->segments_len == 1) { + MEM_SAFE_FREE(gpmd->segments); + gpmd->segment_active_index = -1; + } + else { + TimeGpencilModifierSegment *new_segments = MEM_malloc_arrayN( + gpmd->segments_len, sizeof(TimeGpencilModifierSegment), __func__); + + /* Copy the segments before the deleted segment. */ + memcpy(new_segments, + gpmd->segments, + sizeof(TimeGpencilModifierSegment) * gpmd->segment_active_index); + + /* Copy the segments after the deleted segment. */ + memcpy(new_segments + gpmd->segment_active_index, + gpmd->segments + gpmd->segment_active_index + 1, + sizeof(TimeGpencilModifierSegment) * + (gpmd->segments_len - gpmd->segment_active_index - 1)); + + MEM_freeN(gpmd->segments); + gpmd->segments = new_segments; + gpmd->segment_active_index = MAX2(gpmd->segment_active_index - 1, 0); + } + + gpmd->segments_len--; + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int time_segment_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) { + return time_segment_remove_exec(C, op); + } + return OPERATOR_CANCELLED; +} + +void GPENCIL_OT_time_segment_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Time Segment"; + ot->description = "Remove the active segment from the time modifier"; + ot->idname = "GPENCIL_OT_time_segment_remove"; + + /* api callbacks */ + ot->poll = time_segment_poll; + ot->invoke = time_segment_remove_invoke; + ot->exec = time_segment_remove_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); + + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of the segment to remove", 0, INT_MAX); +} + +enum { + GP_TIME_SEGEMENT_MOVE_UP = -1, + GP_TIME_SEGEMENT_MOVE_DOWN = 1, +}; + +static int time_segment_move_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + + TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)gpencil_edit_modifier_property_get( + op, ob, eGpencilModifierType_Time); + + if (gpmd->segments_len < 2) { + return OPERATOR_CANCELLED; + } + + const int direction = RNA_enum_get(op->ptr, "type"); + if (direction == GP_TIME_SEGEMENT_MOVE_UP) { + if (gpmd->segment_active_index == 0) { + return OPERATOR_CANCELLED; + } + + SWAP(TimeGpencilModifierSegment, + gpmd->segments[gpmd->segment_active_index], + gpmd->segments[gpmd->segment_active_index - 1]); + + gpmd->segment_active_index--; + } + else if (direction == GP_TIME_SEGEMENT_MOVE_DOWN) { + if (gpmd->segment_active_index == gpmd->segments_len - 1) { + return OPERATOR_CANCELLED; + } + + SWAP(TimeGpencilModifierSegment, + gpmd->segments[gpmd->segment_active_index], + gpmd->segments[gpmd->segment_active_index + 1]); + + gpmd->segment_active_index++; + } + else { + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int time_segment_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) { + return time_segment_move_exec(C, op); + } + return OPERATOR_CANCELLED; +} + +void GPENCIL_OT_time_segment_move(wmOperatorType *ot) +{ + static const EnumPropertyItem segment_move[] = { + {GP_TIME_SEGEMENT_MOVE_UP, "UP", 0, "Up", ""}, + {GP_TIME_SEGEMENT_MOVE_DOWN, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Move Time Segment"; + ot->description = "Move the active time segment up or down"; + ot->idname = "GPENCIL_OT_time_segment_move"; + + /* api callbacks */ + ot->poll = time_segment_poll; + ot->invoke = time_segment_move_invoke; + ot->exec = time_segment_move_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); + + ot->prop = RNA_def_enum(ot->srna, "type", segment_move, 0, "Type", ""); +} + /************************* Dash Modifier *******************************/ static bool dash_segment_poll(bContext *C) diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index b3f62f3fc0f..27659042f50 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -484,22 +484,22 @@ static bool hook_op_edit_poll(bContext *C) return false; } -static Object *add_hook_object_new(Main *bmain, ViewLayer *view_layer, View3D *v3d, Object *obedit) +static Object *add_hook_object_new( + Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit) { Base *basedit; Object *ob; - - ob = BKE_object_add(bmain, view_layer, OB_EMPTY, NULL); - - basedit = BKE_view_layer_base_find(view_layer, obedit); - BLI_assert(view_layer->basact->object == ob); - + ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *basact = BKE_view_layer_active_base_get(view_layer); + BLI_assert(basact->object == ob); if (v3d && v3d->localvd) { - view_layer->basact->local_view_bits |= v3d->local_view_uuid; + basact->local_view_bits |= v3d->local_view_uuid; } /* icky, BKE_object_add sets new base as active. * so set it back to the original edit object */ + basedit = BKE_view_layer_base_find(view_layer, obedit); view_layer->basact = basedit; return ob; @@ -532,7 +532,7 @@ static int add_hook_object(const bContext *C, if (mode == OBJECT_ADDHOOK_NEWOB && !ob) { - ob = add_hook_object_new(bmain, view_layer, v3d, obedit); + ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit); /* transform cent to global coords for loc */ mul_v3_m4v3(ob->loc, obedit->obmat, cent); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b5862d4d957..b136f311557 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. @@ -217,6 +221,10 @@ void GPENCIL_OT_segment_add(struct wmOperatorType *ot); void GPENCIL_OT_segment_remove(struct wmOperatorType *ot); void GPENCIL_OT_segment_move(struct wmOperatorType *ot); +void GPENCIL_OT_time_segment_add(struct wmOperatorType *ot); +void GPENCIL_OT_time_segment_remove(struct wmOperatorType *ot); +void GPENCIL_OT_time_segment_move(struct wmOperatorType *ot); + /* object_shader_fx.c */ void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot); @@ -259,7 +267,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..6525f2d6027 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -190,8 +190,11 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports) { wmWindowManager *wm = CTX_wm_manager(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); + + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); if (ob == NULL) { return (mode == OB_MODE_OBJECT); } @@ -327,9 +330,11 @@ static void ed_object_posemode_set_for_weight_paint_ex(bContext *C, const bool is_mode_set) { View3D *v3d = CTX_wm_view3d(C); + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); if (ob_arm != NULL) { + BKE_view_layer_synced_ensure(scene, view_layer); const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm); if (base_arm && BASE_VISIBLE(v3d, base_arm)) { if (is_mode_set) { @@ -464,8 +469,9 @@ static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { Object *ob_dst_orig = DEG_get_original_object(ob_dst); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig); - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); BKE_view_layer_base_select_and_set_active(view_layer, base); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index 202c6d96a47..4581c6a6502 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" @@ -83,8 +85,6 @@ #include "ED_screen.h" #include "ED_sculpt.h" -#include "MOD_nodes.h" - #include "UI_interface.h" #include "WM_api.h" @@ -92,6 +92,8 @@ #include "object_intern.h" +using blender::Span; + static void modifier_skin_customdata_delete(struct Object *ob); /* ------------------------------------------------------------------- */ @@ -111,7 +113,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 +488,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); @@ -515,13 +520,15 @@ void ED_object_modifier_copy_to_object(bContext *C, DEG_relations_tag_update(bmain); } -bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), +bool ED_object_modifier_convert_psys_to_mesh(ReportList * /*reports*/, Main *bmain, Depsgraph *depsgraph, + Scene *scene, ViewLayer *view_layer, Object *ob, ModifierData *md) { + using namespace blender; int cvert = 0; if (md->type != eModifierType_ParticleSystem) { @@ -576,26 +583,33 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } /* add new mesh */ - Object *obn = BKE_object_add(bmain, view_layer, OB_MESH, nullptr); + Object *obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, nullptr); Mesh *me = static_cast<Mesh *>(obn->data); 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); + + blender::MutableSpan<MVert> verts = me->verts_for_write(); + blender::MutableSpan<MEdge> edges = me->edges_for_write(); + MVert *mvert = verts.data(); + MEdge *medge = edges.data(); - MVert *mvert = me->mvert; - MEdge *medge = me->medge; + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>( + ".select_vert", ATTR_DOMAIN_POINT); /* copy coordinates */ + int vert_index = 0; cache = psys_eval->pathcache; for (int a = 0; a < part_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -604,7 +618,7 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } @@ -613,8 +627,8 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), for (int a = 0; a < child_num; a++) { ParticleCacheKey *key = cache[a]; int kmax = key->segments; - for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { - copy_v3_v3(mvert->co, key->co); + for (int k = 0; k <= kmax; k++, key++, cvert++, vert_index++) { + copy_v3_v3(mvert[vert_index].co, key->co); if (k) { medge->v1 = cvert - 1; medge->v2 = cvert; @@ -623,11 +637,13 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList *UNUSED(reports), } else { /* cheap trick to select the roots */ - mvert->flag |= SELECT; + select_vert.span[vert_index] = true; } } } + select_vert.finish(); + DEG_relations_tag_update(bmain); return true; @@ -754,12 +770,10 @@ static bool modifier_apply_obdata( Main *bmain = DEG_get_bmain(depsgraph); BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id); - BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(mesh_applied, me, ob); /* 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 +834,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 +842,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. */ @@ -927,7 +939,7 @@ bool ED_object_modifier_apply(Main *bmain, } bool ED_object_modifier_copy( - ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md) + ReportList * /*reports*/, Main *bmain, Scene *scene, Object *ob, ModifierData *md) { if (md->type == eModifierType_ParticleSystem) { ModifierData *nmd = object_copy_particle_system( @@ -972,8 +984,8 @@ static int modifier_add_exec(bContext *C, wmOperator *op) } static const EnumPropertyItem *modifier_add_itemf(bContext *C, - PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), + PointerRNA * /*ptr*/, + PropertyRNA * /*prop*/, bool *r_free) { Object *ob = ED_object_active_context(C); @@ -1227,7 +1239,8 @@ 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)) { + BKE_view_layer_synced_ensure(scene, 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 +1380,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 +1453,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 +1461,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); @@ -1548,7 +1562,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ -/** \name Apply Modifier As Shapekey Operator +/** \name Apply Modifier As Shape-Key Operator * \{ */ static bool modifier_apply_as_shapekey_poll(bContext *C) @@ -1572,8 +1586,8 @@ static int modifier_apply_as_shapekey_invoke(bContext *C, wmOperator *op, const return retval; } -static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED(C), - struct wmOperatorType *UNUSED(op), +static char *modifier_apply_as_shapekey_get_description(struct bContext * /*C*/, + struct wmOperatorType * /*op*/, struct PointerRNA *values) { bool keep = RNA_boolean_get(values, "keep_modifier"); @@ -1615,12 +1629,13 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); if (!md || !ED_object_modifier_convert_psys_to_mesh( - op->reports, bmain, depsgraph, view_layer, ob, md)) { + op->reports, bmain, depsgraph, scene, view_layer, ob, md)) { return OPERATOR_CANCELLED; } @@ -1630,7 +1645,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return modifier_convert_exec(C, op); @@ -1671,6 +1686,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; @@ -1922,7 +1938,7 @@ static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, - const wmEvent *UNUSED(event)) + const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_higher_levels_delete_exec(C, op); @@ -1998,7 +2014,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_subdivide_exec(C, op); @@ -2073,7 +2089,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_reshape_exec(C, op); @@ -2130,7 +2146,7 @@ static int multires_external_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { Object *ob = ED_object_active_context(C); Mesh *me = static_cast<Mesh *>(ob->data); @@ -2195,7 +2211,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot) /** \name Multires Pack Operator * \{ */ -static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op)) +static int multires_external_pack_exec(bContext *C, wmOperator * /*op*/) { Object *ob = ED_object_active_context(C); Mesh *me = static_cast<Mesh *>(ob->data); @@ -2252,7 +2268,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_base_apply_exec(C, op); @@ -2304,7 +2320,7 @@ static int multires_unsubdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_unsubdivide_exec(C, op); @@ -2358,9 +2374,7 @@ static int multires_rebuild_subdiv_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_rebuild_subdiv_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int multires_rebuild_subdiv_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return multires_rebuild_subdiv_exec(C, op); @@ -2435,7 +2449,7 @@ static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_sk } } -static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) +static int skin_root_mark_exec(bContext *C, wmOperator * /*op*/) { Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -2544,7 +2558,7 @@ void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot) RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", nullptr); } -static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) +static int skin_radii_equalize_exec(bContext *C, wmOperator * /*op*/) { Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -2586,8 +2600,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,18 +2646,22 @@ 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); + Scene *scene = DEG_get_input_scene(depsgraph); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); - Object *arm_ob = BKE_object_add(bmain, view_layer, OB_ARMATURE, nullptr); + Object *arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, nullptr); BKE_object_transform_copy(arm_ob, skin_ob); bArmature *arm = static_cast<bArmature *>(arm_ob->data); arm->layer = 1; @@ -2655,7 +2673,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 +2689,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); } } } @@ -2727,7 +2746,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return skin_armature_create_exec(C, op); @@ -2791,7 +2810,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) /* Signal to modifier to recalculate. */ CorrectiveSmoothModifierData *csmd_eval = (CorrectiveSmoothModifierData *) BKE_modifier_get_evaluated(depsgraph, ob, &csmd->modifier); - csmd_eval->bind_coords_num = (uint)-1; + csmd_eval->bind_coords_num = uint(-1); /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ @@ -2804,7 +2823,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return correctivesmooth_bind_exec(C, op); @@ -2879,7 +2898,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return meshdeform_bind_exec(C, op); @@ -2933,7 +2952,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return explode_refresh_exec(C, op); @@ -2985,7 +3004,7 @@ static void oceanbake_free(void *customdata) } /* called by oceanbake, only to check job 'stop' value */ -static int oceanbake_breakjob(void *UNUSED(customdata)) +static int oceanbake_breakjob(void * /*customdata*/) { // OceanBakeJob *ob = (OceanBakeJob *)customdata; // return *(ob->stop); @@ -3134,7 +3153,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return ocean_bake_exec(C, op); @@ -3211,7 +3230,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return laplaciandeform_bind_exec(C, op); @@ -3278,7 +3297,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { if (edit_modifier_invoke_properties(C, op)) { return surfacedeform_bind_exec(C, op); @@ -3347,6 +3366,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; @@ -3360,13 +3380,12 @@ void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot) /** \name Copy and Assign Geometry Node Group operator * \{ */ -static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *UNUSED(op)) +static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator * /*op*/) { 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; } @@ -3386,6 +3405,7 @@ static int geometry_node_tree_copy_assign_exec(bContext *C, wmOperator *UNUSED(o nmd->node_group = new_tree; id_us_min(&tree->id); + 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; @@ -3398,6 +3418,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..a73cc98c78e 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); @@ -148,6 +151,10 @@ void ED_operatortypes_object(void) WM_operatortype_append(GPENCIL_OT_segment_remove); WM_operatortype_append(GPENCIL_OT_segment_move); + WM_operatortype_append(GPENCIL_OT_time_segment_add); + WM_operatortype_append(GPENCIL_OT_time_segment_remove); + WM_operatortype_append(GPENCIL_OT_time_segment_move); + /* grease pencil line art */ WM_operatortypes_lineart(); diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c index 7d670d3f452..3117cbb0166 100644 --- a/source/blender/editors/object/object_random.c +++ b/source/blender/editors/object/object_random.c @@ -9,6 +9,7 @@ #include "DNA_layer_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "BLI_math.h" #include "BLI_rand.h" @@ -77,6 +78,7 @@ static bool object_rand_transverts(TransVertStore *tvs, static int object_rand_verts_exec(bContext *C, wmOperator *op) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = CTX_data_edit_object(C); const int ob_mode = ob_active->mode; @@ -89,7 +91,7 @@ static int object_rand_verts_exec(bContext *C, wmOperator *op) bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len, ob_mode); + scene, view_layer, CTX_wm_view3d(C), &objects_len, ob_mode); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 6cfd322b2e2..2f18922f4ee 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -262,8 +262,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } else { Object workob; - - ob->parent = BASACT(view_layer)->object; + BKE_view_layer_synced_ensure(scene, view_layer); + ob->parent = BKE_view_layer_active_object_get(view_layer); if (par3 != INDEX_UNSET) { ob->partype = PARVERT3; ob->par1 = par1; @@ -570,7 +570,9 @@ bool ED_object_parent_set(ReportList *reports, pchan = BKE_pose_channel_active_if_layer_visible(par); pchan_eval = BKE_pose_channel_active_if_layer_visible(parent_eval); - if (pchan == NULL) { + if (pchan == NULL || pchan_eval == NULL) { + /* If pchan_eval is NULL, pchan should also be NULL. */ + BLI_assert_msg(pchan == NULL, "Missing evaluated bone data"); BKE_report(reports, RPT_ERROR, "No active bone"); return false; } @@ -951,7 +953,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 +966,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 +992,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 +1832,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, @@ -2060,6 +2075,7 @@ static void tag_localizable_objects(bContext *C, const int mode) * otherwise they're lost on reload, see T40595. */ static bool make_local_all__instance_indirect_unused(Main *bmain, + const Scene *scene, ViewLayer *view_layer, Collection *collection) { @@ -2073,6 +2089,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, id_us_plus(&ob->id); BKE_collection_object_add(bmain, collection, ob); + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, ob); ED_object_base_select(base, BA_SELECT); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -2140,15 +2157,16 @@ static int make_local_exec(bContext *C, wmOperator *op) /* NOTE: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ if (mode == MAKE_LOCAL_ALL) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); Collection *collection = CTX_data_collection(C); BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* De-select so the user can differentiate newly instanced from existing objects. */ - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); - if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) { + if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, collection)) { BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss"); @@ -2198,7 +2216,7 @@ static int make_local_exec(bContext *C, wmOperator *op) CTX_DATA_END; } - BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */ + BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libraries. */ WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; @@ -2267,12 +2285,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 && @@ -2290,27 +2302,19 @@ static int make_override_library_exec(bContext *C, wmOperator *op) user_overrides_from_selected_objects = false; } else if (!make_override_library_object_overridable_check(bmain, obact)) { - const int i = RNA_property_enum_get(op->ptr, op->type->prop); - const uint collection_session_uuid = *((uint *)&i); + const int i = RNA_property_int_get(op->ptr, op->type->prop); + const uint collection_session_uuid = *((const uint *)&i); if (collection_session_uuid == MAIN_ID_SESSION_UUID_UNSET) { BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, - "Active object '%s' is not overridable", + "Could not find an overridable root hierarchy for object '%s'", obact->id.name + 2); return OPERATOR_CANCELLED; } - Collection *collection = BLI_listbase_bytes_find(&bmain->collections, &collection_session_uuid, sizeof(collection_session_uuid), offsetof(ID, session_uuid)); - if (!ID_IS_OVERRIDABLE_LIBRARY(collection)) { - BKE_reportf(op->reports, - RPT_ERROR_INVALID_INPUT, - "Could not find an overridable collection containing object '%s'", - obact->id.name + 2); - return OPERATOR_CANCELLED; - } id_root = &collection->id; user_overrides_from_selected_objects = true; } @@ -2320,6 +2324,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. */ } @@ -2342,6 +2361,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, @@ -2372,23 +2410,52 @@ static int make_override_library_exec(bContext *C, wmOperator *op) BLI_gset_free(user_overrides_objects_uids, NULL); } - /* Remove the instance empty from this scene, the items now have an overridden collection - * instead. */ - if (success && is_override_instancing_object) { - ED_object_base_free_and_unlink(bmain, scene, obact); + if (success) { + if (is_override_instancing_object) { + /* Remove the instance empty from this scene, the items now have an overridden collection + * instead. */ + ED_object_base_free_and_unlink(bmain, scene, obact); + } + else { + /* Remove the found root ID from the view layer. */ + switch (GS(id_root->name)) { + case ID_GR: { + Collection *collection_root = (Collection *)id_root; + LISTBASE_FOREACH_MUTABLE ( + CollectionParent *, collection_parent, &collection_root->parents) { + if (ID_IS_LINKED(collection_parent->collection) || + !BKE_view_layer_has_collection(view_layer, collection_parent->collection)) { + continue; + } + BKE_collection_child_remove(bmain, collection_parent->collection, collection_root); + } + break; + } + case ID_OB: { + /* TODO: Not sure how well we can handle this case, when we don't have the collections as + * reference containers... */ + break; + } + default: + break; + } + } } 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; } /* Set the object to override. */ -static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Object *obact = ED_object_active_context(C); /* Sanity checks. */ @@ -2402,16 +2469,40 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve return make_override_library_exec(C, op); } - if (ID_IS_LINKED(obact)) { - /* Show menu with list of directly linked collections containing the active object. */ - WM_enum_search_invoke(C, op, event); + 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; } - /* Error.. cannot continue. */ - BKE_report(op->reports, - RPT_ERROR, - "Can only make library override for a referenced object or collection"); + int potential_root_collections_num = 0; + uint collection_session_uuid = MAIN_ID_SESSION_UUID_UNSET; + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + /* Only check for directly linked collections. */ + if (!ID_IS_LINKED(&collection->id) || (collection->id.tag & LIB_TAG_INDIRECT) != 0 || + !BKE_view_layer_has_collection(view_layer, collection)) { + continue; + } + if (BKE_collection_has_object_recursive(collection, obact)) { + if (potential_root_collections_num == 0) { + collection_session_uuid = collection->id.session_uuid; + } + potential_root_collections_num++; + } + } + + if (potential_root_collections_num <= 1) { + RNA_property_int_set(op->ptr, op->type->prop, *((int *)&collection_session_uuid)); + return make_override_library_exec(C, op); + } + + BKE_reportf(op->reports, + RPT_ERROR, + "Too many potential root collections (%d) for the override hierarchy, " + "please use the Outliner instead", + potential_root_collections_num); return OPERATOR_CANCELLED; } @@ -2420,77 +2511,168 @@ 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)))); } -static const EnumPropertyItem *make_override_collections_of_linked_object_itemf( - bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +void OBJECT_OT_make_override_library(wmOperatorType *ot) { - EnumPropertyItem item_tmp = {0}, *item = NULL; - int totitem = 0; + /* identifiers */ + ot->name = "Make Library Override"; + 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 */ + ot->invoke = make_override_library_invoke; + ot->exec = make_override_library_exec; + ot->poll = make_override_library_poll; - Object *object = ED_object_active_context(C); + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, + "collection", + MAIN_ID_SESSION_UUID_UNSET, + INT_MIN, + INT_MAX, + "Override Collection", + "Session UUID of the directly linked collection containing the selected " + "object, to make an override from", + INT_MIN, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->prop = prop; +} + +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \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); - if (!object || !ID_IS_LINKED(object)) { - return DummyRNA_DEFAULT_items; + /* 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; - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - /* Only check for directly linked collections. */ - if (!ID_IS_LINKED(&collection->id) || (collection->id.tag & LIB_TAG_INDIRECT) != 0) { + 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; } - if (BKE_collection_has_object_recursive(collection, object)) { - item_tmp.identifier = item_tmp.name = collection->id.name + 2; - item_tmp.value = *((int *)&collection->id.session_uuid); - RNA_enum_item_add(&item, &totitem, &item_tmp); + 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; + BKE_view_layer_synced_ensure(scene, view_layer); + 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); } } - RNA_enum_item_end(&item, &totitem); - *r_free = 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 item; + return OPERATOR_FINISHED; } -void OBJECT_OT_make_override_library(wmOperatorType *ot) +void OBJECT_OT_clear_override_library(wmOperatorType *ot) { /* identifiers */ - ot->name = "Make Library Override"; - ot->description = "Make a local override of this library linked data-block"; - ot->idname = "OBJECT_OT_make_override_library"; + 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->invoke = make_override_library_invoke; - ot->exec = make_override_library_exec; - ot->poll = make_override_library_poll; + ot->exec = clear_override_library_exec; + ot->poll = reset_clear_override_library_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - PropertyRNA *prop; - prop = RNA_def_enum(ot->srna, - "collection", - DummyRNA_DEFAULT_items, - MAIN_ID_SESSION_UUID_UNSET, - "Override Collection", - "Name of directly linked collection containing the selected object, to make " - "an override from"); - RNA_def_enum_funcs(prop, make_override_collections_of_linked_object_itemf); - RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); - 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); } /** \} */ @@ -2516,7 +2698,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "object")) { if (flag == SELECT) { - BKE_view_layer_selected_objects_tag(view_layer, OB_DONE); + BKE_view_layer_selected_objects_tag(scene, view_layer, OB_DONE); single_object_users(bmain, scene, v3d, OB_DONE, copy_collections); } else { diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 71b757b66ff..8358bf632d3 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) { @@ -175,14 +179,13 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_remesh_reproject_vertex_paint(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (smooth_normals) { BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true); } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(CTX_data_scene(C), ob); ED_sculpt_undo_geometry_end(ob); } @@ -243,7 +246,7 @@ static void voxel_size_parallel_lines_draw(uint pos3d, const float spacing) { const float total_len = len_v3v3(initial_co, end_co); - const int tot_lines = (int)(total_len / spacing); + const int tot_lines = int(total_len / spacing); const int tot_lines_half = (tot_lines / 2) + 1; float spacing_dir[3], lines_start[3]; float line_dir[3]; @@ -258,7 +261,7 @@ static void voxel_size_parallel_lines_draw(uint pos3d, mid_v3_v3v3(lines_start, initial_co, end_co); - immBegin(GPU_PRIM_LINES, (uint)tot_lines_half * 2); + immBegin(GPU_PRIM_LINES, uint(tot_lines_half) * 2); for (int i = 0; i < tot_lines_half; i++) { float line_start[3]; float line_end[3]; @@ -271,7 +274,7 @@ static void voxel_size_parallel_lines_draw(uint pos3d, mul_v3_fl(spacing_dir, -1.0f); - immBegin(GPU_PRIM_LINES, (uint)(tot_lines_half - 1) * 2); + immBegin(GPU_PRIM_LINES, uint(tot_lines_half - 1) * 2); for (int i = 1; i < tot_lines_half; i++) { float line_start[3]; float line_end[3]; @@ -283,7 +286,7 @@ static void voxel_size_parallel_lines_draw(uint pos3d, immEnd(); } -static void voxel_size_edit_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) +static void voxel_size_edit_draw(const bContext *C, ARegion * /*ar*/, void *arg) { VoxelSizeEditCustomData *cd = static_cast<VoxelSizeEditCustomData *>(arg); @@ -317,7 +320,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion *UNUSED(ar), void *a GPU_line_width(1.0f); const float total_len = len_v3v3(cd->preview_plane[0], cd->preview_plane[1]); - const int tot_lines = (int)(total_len / cd->voxel_size); + const int tot_lines = int(total_len / cd->voxel_size); /* Smooth-step to reduce the alpha of the grid as the line number increases. */ const float a = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES * 0.1f; @@ -343,7 +346,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion *UNUSED(ar), void *a UnitSettings *unit = &scene->unit; BKE_unit_value_as_string(str, VOXEL_SIZE_EDIT_MAX_STR_LEN, - (double)(cd->voxel_size * unit->scale_length), + double(cd->voxel_size * unit->scale_length), -3, B_UNIT_LENGTH, unit, @@ -354,7 +357,7 @@ static void voxel_size_edit_draw(const bContext *C, ARegion *UNUSED(ar), void *a GPU_matrix_push(); GPU_matrix_mul(cd->text_mat); - BLF_size(fontid, 10.0f * fstyle_points, U.dpi); + BLF_size(fontid, 10.0f * fstyle_points * U.dpi_fac); BLF_color3f(fontid, 1.0f, 1.0f, 1.0f); BLF_width_and_height(fontid, str, strdrawlen, &strwidth, &strheight); BLF_position(fontid, -0.5f * strwidth, -0.5f * strheight, 0.0f); @@ -415,15 +418,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 +580,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 +603,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 +657,7 @@ struct QuadriFlowJob { short *stop, *do_update; float *progress; + const struct wmOperator *op; Scene *scene; int target_faces; int seed; @@ -668,9 +681,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 +694,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 +712,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 +896,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) { @@ -890,14 +904,13 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update BKE_mesh_remesh_reproject_paint_mask(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (qj->smooth_normals) { BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true); } if (ob->mode == OB_MODE_SCULPT) { - BKE_sculpt_ensure_orig_mesh_data(qj->scene, ob); ED_sculpt_undo_geometry_end(ob); } @@ -940,6 +953,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..43867877fdb 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -117,29 +117,28 @@ void ED_object_base_activate(bContext *C, Base *base) void ED_object_base_activate_with_mode_exit_if_needed(bContext *C, Base *base) { + Scene *scene = CTX_data_scene(C); 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); + BKE_view_layer_synced_ensure(scene, 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)) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); ED_object_editmode_exit_multi_ex(bmain, scene, view_layer, EM_FREEDATA); } } ED_object_base_activate(C, base); } -bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, - View3D *v3d, - int action, - bool *r_any_visible) +bool ED_object_base_deselect_all_ex( + const Scene *scene, ViewLayer *view_layer, View3D *v3d, int action, bool *r_any_visible) { if (action == SEL_TOGGLE) { action = SEL_SELECT; - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) { + FOREACH_VISIBLE_BASE_BEGIN (scene, view_layer, v3d, base) { if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) { continue; } @@ -153,7 +152,7 @@ bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, bool any_visible = false; bool changed = false; - FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) { + FOREACH_VISIBLE_BASE_BEGIN (scene, view_layer, v3d, base) { if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) { continue; } @@ -190,9 +189,12 @@ bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, return changed; } -bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action) +bool ED_object_base_deselect_all(const Scene *scene, + ViewLayer *view_layer, + View3D *v3d, + int action) { - return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL); + return ED_object_base_deselect_all_ex(scene, view_layer, v3d, action, NULL); } /** \} */ @@ -203,7 +205,7 @@ bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action) static int get_base_select_priority(Base *base) { - if (base->flag & BASE_VISIBLE_DEPSGRAPH) { + if (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) { if (base->flag & BASE_SELECTABLE) { return 3; } @@ -212,12 +214,13 @@ static int get_base_select_priority(Base *base) return 1; } -Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) +Base *ED_object_find_first_by_data_id(const Scene *scene, ViewLayer *view_layer, ID *id) { BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name))); /* Try active object. */ - Base *basact = view_layer->basact; + BKE_view_layer_synced_ensure(scene, view_layer); + Base *basact = BKE_view_layer_active_base_get(view_layer); if (basact && basact->object && basact->object->data == id) { return basact; @@ -227,7 +230,7 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) Base *base_best = NULL; int priority_best = 0; - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (base->object && base->object->data == id) { if (base->flag & BASE_SELECTED) { return base; @@ -247,8 +250,10 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id) bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_hidden)) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); if (base == NULL) { @@ -257,10 +262,10 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ /* TODO: use 'reveal_hidden', as is done with bones. */ - if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) { + if (BKE_view_layer_active_base_get(view_layer) != base || !(base->flag & BASE_SELECTED)) { /* Select if not selected. */ if (!(base->flag & BASE_SELECTED)) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); if (BASE_VISIBLE(v3d, base)) { ED_object_base_select(base, BA_SELECT); @@ -382,6 +387,7 @@ static bool objects_selectable_poll(bContext *C) static int object_select_by_type_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); short obtype, extend; @@ -390,7 +396,7 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } CTX_DATA_BEGIN (C, Base *, base, visible_bases) { @@ -400,7 +406,6 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -623,10 +628,11 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, 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,17 +783,21 @@ 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) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); Base *baspar, *basact = CTX_data_active_base(C); 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; } + BKE_view_layer_synced_ensure(scene, view_layer); baspar = BKE_view_layer_base_find(view_layer, basact->object->parent); /* can be NULL if parent in other scene */ @@ -856,6 +866,7 @@ static bool select_grouped_collection(bContext *C, Object *ob) static bool select_grouped_object_hooks(bContext *C, Object *ob) { + const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); @@ -868,6 +879,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob) if (md->type == eModifierType_Hook) { hmd = (HookModifierData *)md; if (hmd->object) { + BKE_view_layer_synced_ensure(scene, view_layer); base = BKE_view_layer_base_find(view_layer, hmd->object); if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) { ED_object_base_select(base, BA_SELECT); @@ -1018,10 +1030,11 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (extend == 0) { - changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT); + changed = ED_object_base_deselect_all(scene, view_layer, v3d, SEL_DESELECT); } - ob = OBACT(view_layer); + BKE_view_layer_synced_ensure(scene, 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; @@ -1111,15 +1124,15 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot) static int object_select_all_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); int action = RNA_enum_get(op->ptr, "action"); bool any_visible = false; - bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible); + bool changed = ED_object_base_deselect_all_ex(scene, view_layer, v3d, action, &any_visible); if (changed) { - Scene *scene = CTX_data_scene(C); DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -1128,7 +1141,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; } @@ -1238,6 +1251,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op) if (!STREQ(name_flip, primbase->object->id.name + 2)) { Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip); if (ob) { + BKE_view_layer_synced_ensure(scene, view_layer); Base *secbase = BKE_view_layer_base_find(view_layer, ob); if (secbase) { @@ -1289,9 +1303,11 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot) static bool object_select_more_less(bContext *C, const bool select) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *ob = base->object; ob->flag &= ~OB_DONE; ob->id.tag &= ~LIB_TAG_DOIT; 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..6604e3da4d2 100644 --- a/source/blender/editors/object/object_transform.cc +++ b/source/blender/editors/object/object_transform.cc @@ -321,7 +321,7 @@ static int object_clear_transform_generic_exec(bContext *C, BKE_scene_graph_evaluated_ensure(depsgraph, bmain); xcs = ED_object_xform_skip_child_container_create(); ED_object_xform_skip_child_container_item_ensure_from_array( - xcs, view_layer, objects.data(), objects.size()); + xcs, scene, view_layer, objects.data(), objects.size()); } if (use_transform_data_origin) { BKE_scene_graph_evaluated_ensure(depsgraph, bmain); @@ -469,7 +469,7 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot) /** \name Clear Origin Operator * \{ */ -static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) +static int object_origin_clear_exec(bContext *C, wmOperator * /*op*/) { float *v1, *v3; float mat[3][3]; @@ -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); } } @@ -1061,7 +1066,7 @@ static int apply_objects_internal(bContext *C, return OPERATOR_FINISHED; } -static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) +static int visual_transform_apply_exec(bContext *C, wmOperator * /*op*/) { Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -1118,7 +1123,7 @@ static int object_transform_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int object_transform_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int object_transform_apply_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/) { Object *ob = ED_object_active_context(C); @@ -1176,7 +1181,7 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) /** \name Apply Parent Inverse Operator * \{ */ -static int object_parent_inverse_apply_exec(bContext *C, wmOperator *UNUSED(op)) +static int object_parent_inverse_apply_exec(bContext *C, wmOperator * /*op*/) { CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob->parent == nullptr) { @@ -1283,7 +1288,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } else { /* #V3D_AROUND_CENTER_MEDIAN. */ if (em->bm->totvert) { - const float total_div = 1.0f / (float)em->bm->totvert; + const float total_div = 1.0f / float(em->bm->totvert); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { madd_v3_v3fl(cent, eve->co, total_div); } @@ -1598,6 +1603,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } } } + BKE_gpencil_stroke_geometry_update(gpd, gps); } } } @@ -1860,7 +1866,7 @@ struct XFormAxisData { static void object_transform_axis_target_calc_depth_init(XFormAxisData *xfd, const int mval[2]) { float view_co_a[3], view_co_b[3]; - const float2 mval_fl = {static_cast<float>(mval[0]), static_cast<float>(mval[1])}; + const float2 mval_fl = {float(mval[0]), float(mval[1])}; ED_view3d_win_to_ray(xfd->vc.region, mval_fl, view_co_a, view_co_b); add_v3_v3(view_co_b, view_co_a); float center[3] = {0.0f}; @@ -2073,7 +2079,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const if (event->type == MOUSEMOVE || is_translate_init) { const ViewDepths *depths = xfd->depths; - if (depths && ((uint)event->mval[0] < depths->w) && ((uint)event->mval[1] < depths->h)) { + if (depths && (uint(event->mval[0]) < depths->w) && (uint(event->mval[1]) < depths->h)) { float depth_fl = 1.0f; ED_view3d_depth_read_cached(depths, event->mval, 0, &depth_fl); float location_world[3]; @@ -2095,7 +2101,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const } #endif - double depth = (double)depth_fl; + double depth = double(depth_fl); if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { xfd->prev.depth = depth_fl; xfd->prev.is_depth_valid = true; @@ -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_utils.c b/source/blender/editors/object/object_utils.c index cb9c8a92abe..50ba5b8af5f 100644 --- a/source/blender/editors/object/object_utils.c +++ b/source/blender/editors/object/object_utils.c @@ -22,6 +22,7 @@ #include "BKE_armature.h" #include "BKE_editmesh.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -169,6 +170,7 @@ struct XFormObjectSkipChild_Container *ED_object_xform_skip_child_container_crea void ED_object_xform_skip_child_container_item_ensure_from_array( struct XFormObjectSkipChild_Container *xcs, + const Scene *scene, ViewLayer *view_layer, Object **objects, uint objects_len) @@ -178,8 +180,9 @@ void ED_object_xform_skip_child_container_item_ensure_from_array( Object *ob = objects[ob_index]; BLI_gset_add(objects_in_transdata, ob); } - - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if (ob->parent != NULL) { if (!BLI_gset_haskey(objects_in_transdata, ob)) { @@ -209,7 +212,7 @@ void ED_object_xform_skip_child_container_item_ensure_from_array( } } - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, object_bases) { Object *ob = base->object; if (BLI_gset_haskey(objects_in_transdata, ob)) { diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.cc index 9ad36cacc7d..02a247dd15e 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,15 +21,17 @@ #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_attribute.hh" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_deform.h" @@ -66,6 +68,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 +79,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 +105,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 +120,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) { @@ -150,8 +155,9 @@ bool ED_vgroup_parray_alloc(ID *id, int *dvert_tot, const bool use_vert_sel) { + using namespace blender; *dvert_tot = 0; - *dvert_arr = NULL; + *dvert_arr = nullptr; if (id) { switch (GS(id->name)) { @@ -172,42 +178,48 @@ 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()) { + 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) { + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + for (int i = 0; i < me->totvert; i++) { - (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : NULL; + (*dvert_arr)[i] = select_vert[i] ? &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 +234,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 +268,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; } @@ -268,13 +282,13 @@ void ED_vgroup_parray_mirror_sync(Object *ob, } int flip_map_len; - const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + const int *flip_map = BKE_object_defgroup_flip_map(ob, true, &flip_map_len); 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 +308,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 +323,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 +372,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 +393,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 +429,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 +437,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 +449,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)); } } @@ -496,14 +511,14 @@ static void mesh_defvert_mirror_update_internal(Object *ob, if (def_nr == -1) { /* All vgroups, add groups where needed. */ int flip_map_len; - int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + int *flip_map = BKE_object_defgroup_flip_map_unlocked(ob, true, &flip_map_len); BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true); MEM_freeN(flip_map); } 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 +528,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 +536,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 +547,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 +602,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 +617,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 +641,8 @@ 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; + using namespace blender; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; int i, vgroup_tot, subset_count; @@ -639,7 +658,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 +669,18 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) } } else { - MDeformVert *dv; + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); + 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 (select_vert[i] && &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 +711,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), + PointerRNA * /*ptr*/, + 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 +754,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 +820,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 +888,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 +898,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 +914,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 +955,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]; } } } @@ -990,6 +1020,7 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -998,7 +1029,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 +1041,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,27 +1059,23 @@ static void vgroup_select_verts(Object *ob, int select) } } else { - if (me->dvert) { - MVert *mv; - MDeformVert *dv; - int i; - - mv = me->mvert; - dv = me->dvert; - - for (i = 0; i < me->totvert; i++, mv++, dv++) { - if (!(mv->flag & ME_HIDE)) { - if (BKE_defvert_find_index(dv, def_nr)) { - if (select) { - mv->flag |= SELECT; - } - else { - mv->flag &= ~SELECT; - } + const Span<MDeformVert> dverts = me->deform_verts(); + if (!dverts.is_empty()) { + bke::MutableAttributeAccessor attributes = me->attributes_for_write(); + const VArray<bool> hide_vert = attributes.lookup_or_default<bool>( + ".hide_vert", ATTR_DOMAIN_POINT, false); + bke::SpanAttributeWriter<bool> select_vert = + attributes.lookup_or_add_for_write_only_span<bool>(".select_vert", ATTR_DOMAIN_POINT); + + for (const int i : select_vert.span.index_range()) { + if (!hide_vert[i]) { + if (BKE_defvert_find_index(&dverts[i], def_nr)) { + select_vert.span[i] = select; } } } + select_vert.finish(); paintvert_flush_flags(ob); } } @@ -1085,12 +1113,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 +1141,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 +1163,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 +1174,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 +1221,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 +1246,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 +1254,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 +1265,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 +1279,6 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count) mp++; } - /* Do not free the array! */ - *count = BLI_array_len(verts); return verts; } @@ -1305,17 +1329,18 @@ 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), + Scene * /*scene*/, Object *ob, Mesh *me, int index, @@ -1333,20 +1358,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 +1382,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 +1425,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; @@ -1495,32 +1522,37 @@ static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph, /* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex * but it could be used to raise or lower an existing 'bump.' */ static void vgroup_fix( - const bContext *C, Scene *UNUSED(scene), Object *ob, float distToBe, float strength, float cp) + const bContext *C, Scene * /*scene*/, Object *ob, float distToBe, float strength, float cp) { + using namespace blender; Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); 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; } + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); for (i = 0; i < me->totvert && mvert; i++, mvert++) { - if (mvert->flag & SELECT) { - int count = 0; - if ((verts = getSurroundingVerts(me, i, &count))) { + if (select_vert[i]) { + 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 +1560,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 +1571,6 @@ static void vgroup_fix( } } - MEM_freeN(verts); MEM_freeN(p); } } @@ -1549,12 +1580,12 @@ static void vgroup_fix( static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, - const int UNUSED(subset_count), + const int /*subset_count*/, const float offset, 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 +1593,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 +1631,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 +1642,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 +1650,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 +1713,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 +1732,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 +1751,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 +1765,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 +1776,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 +1789,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 +1800,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 +1812,8 @@ static void vgroup_lock_all(Object *ob, int action, int mask) continue; } break; - default:; + default: + break; } switch (action) { @@ -1808,19 +1841,19 @@ static void vgroup_lock_all(Object *ob, int action, int mask) static void vgroup_invert_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, - const int UNUSED(subset_count), + const int /*subset_count*/, const bool auto_assign, 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++) { @@ -1869,11 +1902,12 @@ static void vgroup_smooth_subset(Object *ob, const int repeat, const float fac_expand) { + using namespace blender; 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 +1919,12 @@ 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); + + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); MeshElemMap *emap; int *emap_mem; @@ -1900,32 +1938,38 @@ 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) -#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 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 ? select_vert[v] : true) /* initialize used verts */ if (bm) { @@ -1945,13 +1989,13 @@ static void vgroup_smooth_subset(Object *ob, } } else { + const blender::Span<MEdge> edges = me->edges(); for (int i = 0; i < dvert_tot; i++) { - const MVert *v = &me->mvert[i]; - if (IS_ME_VERT_WRITE(v)) { + if (IS_ME_VERT_WRITE(i)) { 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 +2062,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(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 +2115,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 +2133,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 +2158,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 +2185,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 +2209,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 { @@ -2181,18 +2227,18 @@ static int vgroup_limit_total_subset(Object *ob, static void vgroup_clean_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, - const int UNUSED(subset_count), + const int /*subset_count*/, 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) { @@ -2212,16 +2258,16 @@ static void vgroup_clean_subset(Object *ob, static void vgroup_quantize_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, - const int UNUSED(subset_count), + const int /*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; @@ -2326,6 +2372,7 @@ void ED_vgroup_mirror(Object *ob, int *r_totmirr, int *r_totfail) { + using namespace blender; /* TODO: vgroup locking. * TODO: face masking. */ @@ -2342,9 +2389,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,29 +2400,29 @@ 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; } if (flip_vgroups) { - 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); + flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, false, &flip_map_len) : + BKE_object_defgroup_flip_map_single(ob, false, def_nr, &flip_map_len); - 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 +2447,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 +2471,10 @@ void ED_vgroup_mirror(Object *ob, } else { /* object mode / weight paint */ - 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,22 +2483,25 @@ void ED_vgroup_mirror(Object *ob, } BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__); + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) { + for (vidx = 0; vidx < me->totvert; vidx++) { 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]; if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) { if (use_vert_sel) { - sel = mv->flag & SELECT; - sel_mirr = mv_mirr->flag & SELECT; + sel = select_vert[vidx]; + sel_mirr = select_vert[vidx_mirr]; } 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 +2528,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 +2554,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 +2588,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; } @@ -2548,6 +2600,7 @@ static void vgroup_delete_active(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { + using namespace blender; const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1; const ListBase *defbase = BKE_object_defgroup_list(ob); @@ -2556,7 +2609,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 +2629,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,17 +2639,16 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } else { - if (!me->dvert) { - BKE_object_defgroup_data_create(&me->id); - } + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - MVert *mv = me->mvert; - MDeformVert *dv = me->dvert; + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); - for (int i = 0; i < me->totvert; i++, mv++, dv++) { - if (mv->flag & SELECT) { + for (int i = 0; i < me->totvert; i++) { + if (select_vert[i]) { MDeformWeight *dw; - dw = BKE_defvert_ensure_index(dv, def_nr); + dw = BKE_defvert_ensure_index(&dverts[i], def_nr); if (dw) { dw->weight = weight; } @@ -2609,7 +2662,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 +2701,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 +2758,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; } @@ -2736,7 +2789,7 @@ static bool vertex_group_vert_poll_ex(bContext *C, return false; } - if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) { + if (ob_type_flag && ((1 << ob->type) & ob_type_flag) == 0) { return false; } @@ -2796,7 +2849,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); } @@ -2826,7 +2879,7 @@ static bool vertex_group_vert_select_mesh_poll(bContext *C) /** \name Vertex Group Add Operator * \{ */ -static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_add_exec(bContext *C, wmOperator * /*op*/) { Object *ob = ED_object_context(C); @@ -2900,10 +2953,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); } @@ -2913,7 +2966,7 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) /** \name Vertex Group Assign Operator * \{ */ -static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_assign_exec(bContext *C, wmOperator * /*op*/) { ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = ED_object_context(C); @@ -2998,8 +3051,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 +3083,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); } @@ -3041,7 +3097,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) /** \name Vertex Group Select Operator * \{ */ -static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_select_exec(bContext *C, wmOperator * /*op*/) { Object *ob = ED_object_context(C); @@ -3050,7 +3106,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; @@ -3077,12 +3133,12 @@ void OBJECT_OT_vertex_group_select(wmOperatorType *ot) /** \name Vertex Group Deselect Operator * \{ */ -static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_deselect_exec(bContext *C, wmOperator * /*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; @@ -3109,7 +3165,7 @@ void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot) /** \name Vertex Group Copy Operator * \{ */ -static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_copy_exec(bContext *C, wmOperator * /*op*/) { Object *ob = ED_object_context(C); @@ -3149,7 +3205,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; @@ -3193,7 +3250,7 @@ void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) /** \name Vertex Group Normalize Operator * \{ */ -static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_normalize_exec(bContext *C, wmOperator * /*op*/) { Object *ob = ED_object_context(C); bool changed; @@ -3236,7 +3293,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 +3354,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 +3443,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 * /*C*/, + wmOperatorType * /*op*/, + PointerRNA *params) { int action = RNA_enum_get(params, "action"); int mask = RNA_enum_get(params, "mask"); @@ -3408,7 +3466,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 +3495,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 +3543,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 +3597,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 +3663,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 +3731,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 +3775,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 +3887,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)"); } @@ -3904,17 +3967,17 @@ static int set_active_group_exec(bContext *C, wmOperator *op) } static const EnumPropertyItem *vgroup_itemf(bContext *C, - PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), + PointerRNA * /*ptr*/, + PropertyRNA * /*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 +3986,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 +4037,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 +4053,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 +4084,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 +4102,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 +4121,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 +4154,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 +4166,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 +4212,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 +4236,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 +4269,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 +4298,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 */ @@ -4262,9 +4329,10 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { + using namespace blender; MDeformVert *dvert_act; - Mesh *me = ob->data; + Mesh *me = static_cast<Mesh *>(ob->data); BMEditMesh *em = me->edit_mesh; int i; @@ -4274,13 +4342,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); @@ -4295,19 +4364,21 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) } } else { - MDeformVert *dv; 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; - for (i = 0; i < me->totvert; i++, dv++) { - if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) { + MutableSpan<MDeformVert> dverts = me->deform_verts_for_write(); + const bke::AttributeAccessor attributes = me->attributes(); + const VArray<bool> select_vert = attributes.lookup_or_default<bool>( + ".select_vert", ATTR_DOMAIN_POINT, false); - BKE_defvert_copy_index(dv, def_nr, dvert_act, def_nr); + for (i = 0; i < me->totvert; i++) { + if (select_vert[i] && (&dverts[i] != dvert_act)) { + BKE_defvert_copy_index(&dverts[i], def_nr, dvert_act, def_nr); if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); @@ -4324,7 +4395,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 +4452,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 +4502,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 +4549,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)); } /** \} */ @@ -4487,11 +4558,11 @@ void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot) /** \name Vertex Group Normalize Active Vertex Operator * \{ */ -static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator * /*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); bool changed; changed = vgroup_normalize_active_vertex(ob, subset_type); @@ -4526,11 +4597,11 @@ void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot) /** \name Vertex Group Copy Weights from Active Operator * \{ */ -static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_weight_copy_exec(bContext *C, wmOperator * /*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); |