diff options
Diffstat (limited to 'source/blender/editors/object/object_add.cc')
-rw-r--r-- | source/blender/editors/object/object_add.cc | 183 |
1 files changed, 100 insertions, 83 deletions
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 041a1383b28..e9abf8c1441 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 * \{ */ @@ -1328,21 +1335,21 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op) const char *ob_name = nullptr; switch (type) { case GP_EMPTY: { - ob_name = "GPencil"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "GPencil"); break; } case GP_MONKEY: { - ob_name = "Suzanne"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Suzanne"); break; } case GP_STROKE: { - ob_name = "Stroke"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Stroke"); break; } case GP_LRT_OBJECT: case GP_LRT_SCENE: case GP_LRT_COLLECTION: { - ob_name = "Line Art"; + ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "LineArt"); break; } default: { @@ -1984,7 +1991,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 +2030,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 +2042,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 +2058,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 +2068,48 @@ void OBJECT_OT_curves_random_add(wmOperatorType *ot) static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); + ushort local_view_bits; - float loc[3], rot[3]; if (!ED_object_add_generic_get_opts( - C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr)) { + C, op, 'Z', nullptr, nullptr, nullptr, nullptr, &local_view_bits, nullptr)) { return OPERATOR_CANCELLED; } Object *surface_ob = CTX_data_active_object(C); + BLI_assert(surface_ob != nullptr); - Object *object = ED_object_add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits); - object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ + Object *curves_ob = ED_object_add_type( + C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits); + BKE_object_apply_mat4(curves_ob, surface_ob->obmat, false, false); - if (surface_ob != nullptr && surface_ob->type == OB_MESH) { - Curves *curves_id = static_cast<Curves *>(object->data); - curves_id->surface = surface_ob; - id_us_plus(&surface_ob->id); + /* Set surface object. */ + Curves *curves_id = static_cast<Curves *>(curves_ob->data); + curves_id->surface = surface_ob; - Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data); - const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_MLOOPUV); - if (uv_name != nullptr) { - curves_id->surface_uv_map = BLI_strdup(uv_name); - } + /* Parent to surface object. */ + ED_object_parent_set( + op->reports, C, scene, curves_ob, surface_ob, PAR_OBJECT, false, true, nullptr); + + /* Decide which UV map to use for attachment. */ + Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data); + const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_MLOOPUV); + if (uv_name != nullptr) { + curves_id->surface_uv_map = BLI_strdup(uv_name); } + /* Add deformation modifier. */ + blender::ed::curves::ensure_surface_deformation_node_exists(*C, *curves_ob); + + /* Make sure the surface object has a rest position attribute which is necessary for + * deformations. */ + surface_ob->modifier_flag |= OB_MODIFIER_FLAG_ADD_REST_POSITION; + return OPERATOR_FINISHED; } static bool object_curves_empty_hair_add_poll(bContext *C) { - if (!U.experimental.use_new_curves_type) { - return false; - } if (!ED_operator_objectmode(C)) { return false; } @@ -2763,28 +2771,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) { @@ -3192,9 +3178,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } /* Anonymous attributes shouldn't be available on the applied geometry. */ - MeshComponent component; - component.replace(new_mesh, GeometryOwnershipType::Editable); - component.attributes_remove_anonymous(); + blender::bke::mesh_attributes_for_write(*new_mesh).remove_anonymous(); BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ } @@ -3544,7 +3528,6 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum( ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to"); - RNA_def_enum_funcs(ot->prop, convert_target_items_fn); RNA_def_boolean(ot->srna, "keep_original", false, @@ -3600,7 +3583,8 @@ static Base *object_add_duplicate_internal(Main *bmain, ViewLayer *view_layer, Object *ob, const eDupli_ID_Flags dupflag, - const eLibIDDuplicateFlags duplicate_options) + const eLibIDDuplicateFlags duplicate_options, + Object **r_ob_new) { Base *base, *basen = nullptr; Object *obn; @@ -3611,6 +3595,9 @@ static Base *object_add_duplicate_internal(Main *bmain, else { obn = static_cast<Object *>( ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); + if (r_ob_new) { + *r_ob_new = obn; + } DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); base = BKE_view_layer_base_find(view_layer, ob); @@ -3623,7 +3610,7 @@ static Base *object_add_duplicate_internal(Main *bmain, } basen = BKE_view_layer_base_find(view_layer, obn); - if (base != nullptr) { + if (base != nullptr && basen != nullptr) { basen->local_view_bits = base->local_view_bits; } @@ -3654,7 +3641,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,45 +3675,73 @@ 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); + /* 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(); + + /* 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; + 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); + Object *ob_new = NULL; + 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}); /* 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; - if (basen == nullptr) { - continue; - } - - /* new object becomes active */ + /* new object will become active */ if (BASACT(view_layer) == base) { - ED_object_base_activate(C, basen); - } - - if (basen->object->data) { - DEG_id_tag_update(static_cast<ID *>(basen->object->data), 0); + ob_new_active = ob_new; } } CTX_DATA_END; - if (!changed) { + if (source_bases_new_objects.is_empty()) { return OPERATOR_CANCELLED; } + /* Sync the collection now, after everything is duplicated. */ + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync(bmain); + + /* After sync we can get to the new Base data, process it here. */ + for (const auto &item : source_bases_new_objects) { + Object *ob_new = item.second; + Base *base_source = item.first; + Base *base_new = BKE_view_layer_base_find(view_layer, ob_new); + if (base_new == nullptr) { + continue; + } + ED_object_base_select(base_new, BA_SELECT); + if (ob_new == ob_new_active) { + ED_object_base_activate(C, base_new); + } + if (base_new->object->data) { + DEG_id_tag_update(static_cast<ID *>(base_new->object->data), 0); + } + /* #object_add_duplicate_internal will not have done this, since + * before the collection sync it would not have found the new base yet. */ + base_new->local_view_bits = base_source->local_view_bits; + } /* Note that this will also clear newid pointers and tags. */ copy_object_set_idnew(C); @@ -3808,7 +3824,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"); @@ -3976,7 +3993,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; |