diff options
Diffstat (limited to 'source/blender/editors/object/object_add.cc')
-rw-r--r-- | source/blender/editors/object/object_add.cc | 264 |
1 files changed, 154 insertions, 110 deletions
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index c651affd96a..6075e4250eb 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -287,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': { @@ -322,7 +322,7 @@ void ED_object_base_init_transform_on_add(Object *object, const float loc[3], co copy_v3_v3(object->rot, rot); } - BKE_object_to_mat4(object, object->obmat); + BKE_object_to_mat4(object, object->object_to_world); } float ED_object_new_primitive_matrix(bContext *C, @@ -342,14 +342,14 @@ float ED_object_new_primitive_matrix(bContext *C, invert_m3(rmat); /* inverse transform for initial rotation and object */ - copy_m3_m4(mat, obedit->obmat); + copy_m3_m4(mat, obedit->object_to_world); mul_m3_m3m3(cmat, rmat, mat); invert_m3_m3(imat, cmat); copy_m4_m3(r_primmat, imat); /* center */ copy_v3_v3(r_primmat[3], loc); - sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->obmat[3]); + sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world[3]); invert_m3_m3(imat, mat); mul_m3_v3(imat, r_primmat[3]); @@ -372,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"); @@ -609,6 +609,7 @@ Object *ED_object_add_type_with_obdata(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); { + 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); @@ -619,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 = view_layer->basact; + 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); @@ -990,6 +992,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) } bool newob = false; + 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); @@ -1099,6 +1102,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); + 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); @@ -1471,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; @@ -2080,7 +2084,7 @@ static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op) 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); + BKE_object_apply_mat4(curves_ob, surface_ob->object_to_world, false, false); /* Set surface object. */ Curves *curves_id = static_cast<Curves *>(curves_ob->data); @@ -2534,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); @@ -2556,8 +2561,8 @@ static void make_object_duplilist_real(bContext *C, id_us_min((ID *)ob_dst->instance_collection); ob_dst->instance_collection = nullptr; - copy_m4_m4(ob_dst->obmat, dob->mat); - BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false); + copy_m4_m4(ob_dst->object_to_world, dob->mat); + BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world, false, false); BLI_ghash_insert(dupli_gh, dob, ob_dst); if (parent_gh) { @@ -2831,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); @@ -3011,7 +3017,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; float loc[3], size[3], rot[3][3], eul[3]; float matrix[4][4]; - mat4_to_loc_rot_size(loc, rot, size, ob->obmat); + mat4_to_loc_rot_size(loc, rot, size, ob->object_to_world); mat3_to_eul(eul, rot); Object *ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); @@ -3301,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; } @@ -3443,9 +3449,13 @@ static int object_convert_exec(bContext *C, wmOperator *op) ED_object_base_activate(C, basact); view_layer->basact = basact; } - else if (view_layer->basact->object->flag & OB_DONE) { - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, view_layer->basact->object); - WM_event_add_notifier(C, NC_OBJECT | ND_DATA, view_layer->basact->object); + 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); @@ -3457,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; @@ -3500,11 +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_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, @@ -3545,11 +3556,62 @@ void OBJECT_OT_convert(wmOperatorType *ot) /** \name Duplicate Object Operator * \{ */ +static void object_add_sync_base_collection( + Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new) +{ + if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { + BKE_collection_object_add_from(bmain, scene, base_src->object, object_new); + } + else { + LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); + BKE_collection_object_add(bmain, layer_collection->collection, object_new); + } +} + +static void object_add_sync_local_view(Base *base_src, Base *base_new) +{ + base_new->local_view_bits = base_src->local_view_bits; +} + +static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new) +{ + /* 1) duplis should end up in same collection as the original + * 2) Rigid Body sim participants MUST always be part of a collection... + */ + /* XXX: is 2) really a good measure here? */ + if (object_src->rigidbody_object || object_src->rigidbody_constraint) { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, object_src)) { + BKE_collection_object_add(bmain, collection, object_new); + } + } + } +} + /** * - Assumes `id.new` is correct. * - Leaves selection of base/object unaltered. * - Sets #ID.newid pointers. */ +static void object_add_duplicate_internal(Main *bmain, + Object *ob, + const eDupli_ID_Flags dupflag, + const eLibIDDuplicateFlags duplicate_options, + Object **r_ob_new) +{ + if (ob->mode & OB_MODE_POSE) { + return; + } + + Object *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); + return; +} + static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -3558,47 +3620,25 @@ static Base *object_add_duplicate_internal(Main *bmain, const eLibIDDuplicateFlags duplicate_options, Object **r_ob_new) { - Base *base, *basen = nullptr; - Object *obn; - - if (ob->mode & OB_MODE_POSE) { - /* nothing? */ + Object *object_new = nullptr; + object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new); + if (r_ob_new) { + *r_ob_new = object_new; + } + if (object_new == nullptr) { + return nullptr; } - 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); - if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { - BKE_collection_object_add_from(bmain, scene, ob, obn); - } - else { - LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); - BKE_collection_object_add(bmain, layer_collection->collection, obn); - } - - basen = BKE_view_layer_base_find(view_layer, obn); - if (base != nullptr && basen != nullptr) { - basen->local_view_bits = base->local_view_bits; - } - /* 1) duplis should end up in same collection as the original - * 2) Rigid Body sim participants MUST always be part of a collection... - */ - /* XXX: is 2) really a good measure here? */ - if (ob->rigidbody_object || ob->rigidbody_constraint) { - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_has_object(collection, ob)) { - BKE_collection_object_add(bmain, collection, obn); - } - } - } + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_src = BKE_view_layer_base_find(view_layer, ob); + object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_new = BKE_view_layer_base_find(view_layer, object_new); + if (base_src && base_new) { + object_add_sync_local_view(base_src, base_new); } - return basen; + object_add_sync_rigid_body(bmain, ob, object_new); + return base_new; } Base *ED_object_add_duplicate( @@ -3652,68 +3692,70 @@ static int duplicate_exec(bContext *C, wmOperator *op) * 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; + * after the sync. */ + struct DuplicateObjectLink { + Base *base_src = nullptr; + Object *object_new = nullptr; + + DuplicateObjectLink(Base *base_src) : base_src(base_src) + { + } + }; + blender::Vector<DuplicateObjectLink> object_base_links; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Object *ob_new = nullptr; + object_base_links.append(DuplicateObjectLink(base)); + } + CTX_DATA_END; + + bool new_objects_created = false; + for (DuplicateObjectLink &link : object_base_links) { object_add_duplicate_internal(bmain, - scene, - view_layer, - base->object, + link.base_src->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); - - /* new object will become active */ - if (view_layer->basact == base) { - ob_new_active = ob_new; + &link.object_new); + if (link.object_new) { + new_objects_created = true; } } - CTX_DATA_END; - BKE_layer_collection_resync_allow(); - if (source_bases_new_objects.is_empty()) { + if (!new_objects_created) { return OPERATOR_CANCELLED; } - /* Sync the collection now, after everything is duplicated. */ - BKE_main_collection_sync(bmain); + /* Sync that could tag the view_layer out of sync. */ + for (DuplicateObjectLink &link : object_base_links) { + /* note that this is safe to do with this context iterator, + * the list is made in advance */ + ED_object_base_select(link.base_src, BA_DESELECT); + if (link.object_new) { + object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new); + object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new); + } + } - /* 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) { + /* Sync the view layer. Everything else should not tag the view_layer out of sync. */ + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *active_base = BKE_view_layer_active_base_get(view_layer); + for (DuplicateObjectLink &link : object_base_links) { + if (!link.object_new) { continue; } + + Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new); + BLI_assert(base_new); ED_object_base_select(base_new, BA_SELECT); - if (ob_new == ob_new_active) { + if (active_base == link.base_src) { ED_object_base_activate(C, base_new); } - if (base_new->object->data) { - DEG_id_tag_update(static_cast<ID *>(base_new->object->data), 0); + + if (link.object_new->data) { + DEG_id_tag_update(static_cast<ID *>(link.object_new->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; + + object_add_sync_local_view(link.base_src, base_new); } /* Note that this will also clear newid pointers and tags. */ @@ -3811,7 +3853,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); @@ -3829,8 +3871,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op) PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix"); if (RNA_property_is_set(op->ptr, prop_matrix)) { Object *ob_add = basen->object; - RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->obmat[0][0]); - BKE_object_apply_mat4(ob_add, ob_add->obmat, true, true); + RNA_property_float_get_array(op->ptr, prop_matrix, &ob_add->object_to_world[0][0]); + BKE_object_apply_mat4(ob_add, ob_add->object_to_world, true, true); DEG_id_tag_update(&ob_add->id, ID_RECALC_TRANSFORM); } @@ -3888,12 +3930,14 @@ 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) { + BKE_view_layer_synced_ensure(scene, view_layer); ob = BKE_view_layer_active_object_get(view_layer); } @@ -3925,7 +3969,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) float mat_dst_unit[4][4]; float final_delta[4][4]; - normalize_m4_m4(mat_src_unit, ob->obmat); + normalize_m4_m4(mat_src_unit, ob->object_to_world); normalize_m4_m4(mat_dst_unit, matrix); invert_m4(mat_src_unit); mul_m4_m4m4(final_delta, mat_dst_unit, mat_src_unit); @@ -4080,7 +4124,7 @@ static int object_join_exec(bContext *C, wmOperator *op) * If the zero scale is removed, the data on this axis remains un-scaled * (something that wouldn't work for #invert_m4_m4_safe). */ float imat_test[4][4]; - if (!invert_m4_m4(imat_test, ob->obmat)) { + if (!invert_m4_m4(imat_test, ob->object_to_world)) { BKE_report(op->reports, RPT_WARNING, "Active object final transform has one or more zero scaled axes"); |