Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_add.cc')
-rw-r--r--source/blender/editors/object/object_add.cc183
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;