Blender V4.3
object_add.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cctype>
10#include <cstdlib>
11#include <cstring>
12#include <optional>
13
14#include "BKE_curves.hh"
15#include "MEM_guardedalloc.h"
16
17#include "DNA_anim_types.h"
18#include "DNA_camera_types.h"
20#include "DNA_curve_types.h"
23#include "DNA_key_types.h"
24#include "DNA_light_types.h"
26#include "DNA_material_types.h"
27#include "DNA_mesh_types.h"
28#include "DNA_meta_types.h"
29#include "DNA_modifier_types.h"
32#include "DNA_object_types.h"
34#include "DNA_scene_types.h"
35#include "DNA_vfont_types.h"
36
37#include "BLI_ghash.h"
38#include "BLI_listbase.h"
39#include "BLI_math_matrix.h"
41#include "BLI_math_rotation.h"
43#include "BLI_string.h"
44#include "BLI_string_utf8.h"
45#include "BLI_utildefines.h"
46#include "BLI_vector.hh"
47
48#include "BLT_translation.hh"
49
50#include "BKE_action.hh"
51#include "BKE_anim_data.hh"
52#include "BKE_armature.hh"
53#include "BKE_camera.h"
54#include "BKE_collection.hh"
55#include "BKE_constraint.h"
56#include "BKE_context.hh"
57#include "BKE_curve.hh"
58#include "BKE_curve_to_mesh.hh"
59#include "BKE_curves.h"
60#include "BKE_curves.hh"
61#include "BKE_customdata.hh"
62#include "BKE_displist.h"
63#include "BKE_duplilist.hh"
64#include "BKE_effect.h"
65#include "BKE_geometry_set.hh"
69#include "BKE_gpencil_legacy.h"
71#include "BKE_grease_pencil.hh"
73#include "BKE_key.hh"
74#include "BKE_lattice.hh"
75#include "BKE_layer.hh"
76#include "BKE_lib_id.hh"
77#include "BKE_lib_override.hh"
78#include "BKE_lib_query.hh"
79#include "BKE_lib_remap.hh"
80#include "BKE_light.h"
81#include "BKE_lightprobe.h"
82#include "BKE_main.hh"
83#include "BKE_material.h"
84#include "BKE_mball.hh"
85#include "BKE_mesh.hh"
86#include "BKE_mesh_runtime.hh"
87#include "BKE_modifier.hh"
88#include "BKE_nla.hh"
89#include "BKE_node.hh"
90#include "BKE_object.hh"
91#include "BKE_object_types.hh"
92#include "BKE_particle.h"
93#include "BKE_pointcloud.hh"
94#include "BKE_report.hh"
95#include "BKE_scene.hh"
96#include "BKE_speaker.h"
97#include "BKE_vfont.hh"
98#include "BKE_volume.hh"
99
100#include "DEG_depsgraph.hh"
101#include "DEG_depsgraph_build.hh"
102#include "DEG_depsgraph_query.hh"
103
104#include "GEO_join_geometries.hh"
105
106#include "RNA_access.hh"
107#include "RNA_define.hh"
108#include "RNA_enum_types.hh"
109
110#include "UI_interface.hh"
111
112#include "WM_api.hh"
113#include "WM_types.hh"
114
115#include "ED_armature.hh"
116#include "ED_curve.hh"
117#include "ED_curves.hh"
118#include "ED_gpencil_legacy.hh"
119#include "ED_grease_pencil.hh"
120#include "ED_mball.hh"
121#include "ED_mesh.hh"
122#include "ED_node.hh"
123#include "ED_object.hh"
124#include "ED_outliner.hh"
125#include "ED_physics.hh"
126#include "ED_render.hh"
127#include "ED_screen.hh"
128#include "ED_select_utils.hh"
129#include "ED_transform.hh"
130#include "ED_view3d.hh"
131
133
134#include "UI_resources.hh"
135
136#include "object_intern.hh"
137
139 {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
140 {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
141 {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
142 {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
143 {0, nullptr, 0, nullptr, nullptr},
144};
145
146namespace blender::ed::object {
147
148/* -------------------------------------------------------------------- */
152/* This is an exact copy of the define in `rna_light.cc`
153 * kept here because of linking order.
154 * Icons are only defined here. */
155
156/* copy from rna_object_force.cc */
158 {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
159 {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
160 {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
161 {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
162 {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
163 {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
164 {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
165 {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
166 {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
167 {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
168 {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
169 {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
170 {PFIELD_FLUIDFLOW, "FLUID", ICON_FORCE_FLUIDFLOW, "Fluid Flow", ""},
171 {0, nullptr, 0, nullptr, nullptr},
172};
173
176 "SPHERE",
177 ICON_LIGHTPROBE_SPHERE,
178 "Sphere",
179 "Light probe that captures precise lighting from all directions at a single point in space"},
181 "PLANE",
182 ICON_LIGHTPROBE_PLANE,
183 "Plane",
184 "Light probe that captures incoming light from a single direction on a plane"},
186 "VOLUME",
187 ICON_LIGHTPROBE_VOLUME,
188 "Volume",
189 "Light probe that captures low frequency lighting inside a volume"},
190 {0, nullptr, 0, nullptr, nullptr},
191};
192
193enum {
197};
198
200 {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"},
201 {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"},
202 {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"},
203 {0, nullptr, 0, nullptr, nullptr},
204};
205
208/* -------------------------------------------------------------------- */
217{
218 PropertyRNA *prop;
219
220 prop = RNA_def_int(ot->srna,
221 "drop_x",
222 0,
223 INT_MIN,
224 INT_MAX,
225 "Drop X",
226 "X-coordinate (screen space) to place the new object under",
227 INT_MIN,
228 INT_MAX);
230 prop = RNA_def_int(ot->srna,
231 "drop_y",
232 0,
233 INT_MIN,
234 INT_MAX,
235 "Drop Y",
236 "Y-coordinate (screen space) to place the new object under",
237 INT_MIN,
238 INT_MAX);
240}
241
243{
244 return RNA_struct_property_is_set(op->ptr, "drop_x") &&
245 RNA_struct_property_is_set(op->ptr, "drop_y");
246}
247
252static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int (*r_mval)[2])
253{
254 if (!object_add_drop_xy_is_set(op)) {
255 (*r_mval)[0] = 0.0f;
256 (*r_mval)[1] = 0.0f;
257 return false;
258 }
259
260 const ARegion *region = CTX_wm_region(C);
261 (*r_mval)[0] = RNA_int_get(op->ptr, "drop_x") - region->winrct.xmin;
262 (*r_mval)[1] = RNA_int_get(op->ptr, "drop_y") - region->winrct.ymin;
263
264 return true;
265}
266
272{
273 if (!object_add_drop_xy_is_set(op)) {
274 RNA_int_set(op->ptr, "drop_x", event->xy[0]);
275 RNA_int_set(op->ptr, "drop_y", event->xy[1]);
276 }
277 return op->type->exec(C, op);
278}
279
282/* -------------------------------------------------------------------- */
286void location_from_view(bContext *C, float loc[3])
287{
288 const Scene *scene = CTX_data_scene(C);
289 copy_v3_v3(loc, scene->cursor.location);
290}
291
292void rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
293{
294 BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
295
296 switch (align_axis) {
297 case 'X': {
298 /* Same as 'rv3d->viewinv[1]' */
299 const float axis_y[4] = {0.0f, 1.0f, 0.0f};
300 float quat_y[4], quat[4];
301 axis_angle_to_quat(quat_y, axis_y, M_PI_2);
302 mul_qt_qtqt(quat, viewquat, quat_y);
303 quat_to_eul(rot, quat);
304 break;
305 }
306 case 'Y': {
307 quat_to_eul(rot, viewquat);
308 rot[0] -= float(M_PI_2);
309 break;
310 }
311 case 'Z': {
312 quat_to_eul(rot, viewquat);
313 break;
314 }
315 }
316}
317
318void rotation_from_view(bContext *C, float rot[3], const char align_axis)
319{
321 BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
322 if (rv3d) {
323 float viewquat[4];
324 copy_qt_qt(viewquat, rv3d->viewquat);
325 viewquat[0] *= -1.0f;
326 rotation_from_quat(rot, viewquat, align_axis);
327 }
328 else {
329 zero_v3(rot);
330 }
331}
332
333void init_transform_on_add(Object *object, const float loc[3], const float rot[3])
334{
335 if (loc) {
336 copy_v3_v3(object->loc, loc);
337 }
338
339 if (rot) {
340 copy_v3_v3(object->rot, rot);
341 }
342
343 BKE_object_to_mat4(object, object->runtime->object_to_world.ptr());
344}
345
347 Object *obedit,
348 const float loc[3],
349 const float rot[3],
350 const float scale[3],
351 float r_primmat[4][4])
352{
353 Scene *scene = CTX_data_scene(C);
354 View3D *v3d = CTX_wm_view3d(C);
355 float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
356
357 unit_m4(r_primmat);
358
359 eul_to_mat3(rmat, rot);
360 invert_m3(rmat);
361
362 /* inverse transform for initial rotation and object */
363 copy_m3_m4(mat, obedit->object_to_world().ptr());
364 mul_m3_m3m3(cmat, rmat, mat);
365 invert_m3_m3(imat, cmat);
366 copy_m4_m3(r_primmat, imat);
367
368 /* center */
369 copy_v3_v3(r_primmat[3], loc);
370 sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world().location());
371 invert_m3_m3(imat, mat);
372 mul_m3_v3(imat, r_primmat[3]);
373
374 if (scale != nullptr) {
375 rescale_m4(r_primmat, scale);
376 }
377
378 {
379 const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
380 ED_scene_grid_scale(scene, nullptr);
381 return dia;
382 }
383
384 // return 1.0f;
385}
386
389/* -------------------------------------------------------------------- */
393static void view_align_update(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
394{
395 RNA_struct_idprops_unset(ptr, "rotation");
396}
397
399{
401 ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
402}
403
404void add_unit_props_radius_ex(wmOperatorType *ot, float default_value)
405{
407 ot->srna, "radius", default_value, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
408}
409
414
415void add_generic_props(wmOperatorType *ot, bool do_editmode)
416{
417 PropertyRNA *prop;
418
419 if (do_editmode) {
420 prop = RNA_def_boolean(ot->srna,
421 "enter_editmode",
422 false,
423 "Enter Edit Mode",
424 "Enter edit mode when adding this object");
426 }
427 /* NOTE: this property gets hidden for add-camera operator. */
428 prop = RNA_def_enum(
429 ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
431
433 "location",
434 3,
435 nullptr,
438 "Location",
439 "Location for the newly added object",
440 -1000.0f,
441 1000.0f);
444 "rotation",
445 3,
446 nullptr,
449 "Rotation",
450 "Rotation for the newly added object",
451 DEG2RADF(-360.0f),
452 DEG2RADF(360.0f));
454
456 "scale",
457 3,
458 nullptr,
461 "Scale",
462 "Scale for the newly added object",
463 -1000.0f,
464 1000.0f);
466}
467
469{
470 RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
471}
472
474 wmOperator *op,
475 const char view_align_axis,
476 float r_loc[3],
477 float r_rot[3],
478 float r_scale[3],
479 bool *r_enter_editmode,
480 ushort *r_local_view_bits,
481 bool *r_is_view_aligned)
482{
483 /* Edit Mode! (optional) */
484 {
485 bool _enter_editmode;
486 if (!r_enter_editmode) {
487 r_enter_editmode = &_enter_editmode;
488 }
489 /* Only to ensure the value is _always_ set.
490 * Typically the property will exist when the argument is non-null. */
491 *r_enter_editmode = false;
492
493 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "enter_editmode");
494 if (prop != nullptr) {
495 if (RNA_property_is_set(op->ptr, prop) && r_enter_editmode) {
496 *r_enter_editmode = RNA_property_boolean_get(op->ptr, prop);
497 }
498 else {
499 *r_enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
500 RNA_property_boolean_set(op->ptr, prop, *r_enter_editmode);
501 }
502 }
503 }
504
505 if (r_local_view_bits) {
506 View3D *v3d = CTX_wm_view3d(C);
507 *r_local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uid : 0;
508 }
509
510 /* Location! */
511 {
512 float _loc[3];
513 if (!r_loc) {
514 r_loc = _loc;
515 }
516
517 if (RNA_struct_property_is_set(op->ptr, "location")) {
518 RNA_float_get_array(op->ptr, "location", r_loc);
519 }
520 else {
521 location_from_view(C, r_loc);
522 RNA_float_set_array(op->ptr, "location", r_loc);
523 }
524 }
525
526 /* Rotation! */
527 {
528 bool _is_view_aligned;
529 float _rot[3];
530 if (!r_is_view_aligned) {
531 r_is_view_aligned = &_is_view_aligned;
532 }
533 if (!r_rot) {
534 r_rot = _rot;
535 }
536
537 if (RNA_struct_property_is_set(op->ptr, "rotation")) {
538 /* If rotation is set, always use it. Alignment (and corresponding user preference)
539 * can be ignored since this is in world space anyways.
540 * To not confuse (e.g. on redo), don't set it to #ALIGN_WORLD in the op UI though. */
541 *r_is_view_aligned = false;
542 RNA_float_get_array(op->ptr, "rotation", r_rot);
543 }
544 else {
545 int alignment = ALIGN_WORLD;
546 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "align");
547
548 if (RNA_property_is_set(op->ptr, prop)) {
549 /* If alignment is set, always use it. */
550 *r_is_view_aligned = alignment == ALIGN_VIEW;
551 alignment = RNA_property_enum_get(op->ptr, prop);
552 }
553 else {
554 /* If alignment is not set, use User Preferences. */
555 *r_is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
556 if (*r_is_view_aligned) {
558 alignment = ALIGN_VIEW;
559 }
560 else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) {
562 alignment = ALIGN_CURSOR;
563 }
564 else {
566 alignment = ALIGN_WORLD;
567 }
568 }
569 switch (alignment) {
570 case ALIGN_WORLD:
571 RNA_float_get_array(op->ptr, "rotation", r_rot);
572 break;
573 case ALIGN_VIEW:
574 rotation_from_view(C, r_rot, view_align_axis);
575 RNA_float_set_array(op->ptr, "rotation", r_rot);
576 break;
577 case ALIGN_CURSOR: {
578 const Scene *scene = CTX_data_scene(C);
579 const float3x3 tmat = scene->cursor.matrix<float3x3>();
580 mat3_normalized_to_eul(r_rot, tmat.ptr());
581 RNA_float_set_array(op->ptr, "rotation", r_rot);
582 break;
583 }
584 }
585 }
586 }
587
588 /* Scale! */
589 {
590 float _scale[3];
591 if (!r_scale) {
592 r_scale = _scale;
593 }
594
595 /* For now this is optional, we can make it always use. */
596 copy_v3_fl(r_scale, 1.0f);
597
598 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "scale");
599 if (prop != nullptr) {
600 if (RNA_property_is_set(op->ptr, prop)) {
601 RNA_property_float_get_array(op->ptr, prop, r_scale);
602 }
603 else {
604 copy_v3_fl(r_scale, 1.0f);
605 RNA_property_float_set_array(op->ptr, prop, r_scale);
606 }
607 }
608 }
609}
610
612 const int type,
613 const char *name,
614 const float loc[3],
615 const float rot[3],
616 const bool enter_editmode,
617 const ushort local_view_bits,
618 ID *obdata)
619{
620 Main *bmain = CTX_data_main(C);
621 Scene *scene = CTX_data_scene(C);
622 ViewLayer *view_layer = CTX_data_view_layer(C);
623
624 {
625 BKE_view_layer_synced_ensure(scene, view_layer);
626 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
627 if (obedit != nullptr) {
628 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
629 }
630 }
631
632 /* deselects all, sets active object */
633 Object *ob;
634 if (obdata != nullptr) {
635 BLI_assert(type == BKE_object_obdata_to_type(obdata));
636 ob = BKE_object_add_for_data(bmain, scene, view_layer, type, name, obdata, true);
637 const short *materials_len_p = BKE_id_material_len_p(obdata);
638 if (materials_len_p && *materials_len_p > 0) {
639 BKE_object_materials_test(bmain, ob, static_cast<ID *>(ob->data));
640 }
641 }
642 else {
643 ob = BKE_object_add(bmain, scene, view_layer, type, name);
644 }
645
646 BKE_view_layer_synced_ensure(scene, view_layer);
647 Base *ob_base_act = BKE_view_layer_active_base_get(view_layer);
648 /* While not getting a valid base is not a good thing, it can happen in convoluted corner cases,
649 * better not crash on it in releases. */
650 BLI_assert(ob_base_act != nullptr);
651 if (ob_base_act != nullptr) {
652 ob_base_act->local_view_bits = local_view_bits;
653 /* editor level activate, notifiers */
654 base_activate(C, ob_base_act);
655 }
656
657 /* more editor stuff */
658 init_transform_on_add(ob, loc, rot);
659
660 /* TODO(sergey): This is weird to manually tag objects for update, better to
661 * use DEG_id_tag_update here perhaps.
662 */
663 DEG_id_type_tag(bmain, ID_OB);
665 if (ob->data != nullptr) {
667 }
668
669 if (enter_editmode) {
670 editmode_enter_ex(bmain, scene, ob, 0);
671 }
672
674
676
678
679 return ob;
680}
681
683 const int type,
684 const char *name,
685 const float loc[3],
686 const float rot[3],
687 const bool enter_editmode,
688 const ushort local_view_bits)
689{
690 return add_type_with_obdata(C, type, name, loc, rot, enter_editmode, local_view_bits, nullptr);
691}
692
693/* for object add operator */
695{
696 ushort local_view_bits;
697 bool enter_editmode;
698 float loc[3], rot[3], radius;
700 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
701
702 radius = RNA_float_get(op->ptr, "radius");
703 Object *ob = add_type(
704 C, RNA_enum_get(op->ptr, "type"), nullptr, loc, rot, enter_editmode, local_view_bits);
705
706 if (ob->type == OB_LATTICE) {
707 /* lattice is a special case!
708 * we never want to scale the obdata since that is the rest-state */
709 copy_v3_fl(ob->scale, radius);
710 }
711 else {
712 BKE_object_obdata_size_init(ob, radius);
713 }
714
715 return OPERATOR_FINISHED;
716}
717
719{
720 /* identifiers */
721 ot->name = "Add Object";
722 ot->description = "Add an object to the scene";
723 ot->idname = "OBJECT_OT_add";
724
725 /* api callbacks */
728
729 /* flags */
731
732 /* properties */
734 PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
736
737 add_generic_props(ot, true);
738}
739
742/* -------------------------------------------------------------------- */
746/* for object add operator */
747static const char *get_lightprobe_defname(int type)
748{
749 switch (type) {
751 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Volume");
753 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Plane");
755 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sphere");
756 default:
757 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
758 }
759}
760
762{
763 bool enter_editmode;
764 ushort local_view_bits;
765 float loc[3], rot[3];
767 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
768
769 int type = RNA_enum_get(op->ptr, "type");
770 float radius = RNA_float_get(op->ptr, "radius");
771
772 Object *ob = add_type(
773 C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
774 copy_v3_fl(ob->scale, radius);
775
776 LightProbe *probe = (LightProbe *)ob->data;
777
778 BKE_lightprobe_type_set(probe, type);
779
780 return OPERATOR_FINISHED;
781}
782
784{
785 /* identifiers */
786 ot->name = "Add Light Probe";
787 ot->description = "Add a light probe object";
788 ot->idname = "OBJECT_OT_lightprobe_add";
789
790 /* api callbacks */
793
794 /* flags */
796
797 /* properties */
798 ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
799
801 add_generic_props(ot, true);
802}
803
806/* -------------------------------------------------------------------- */
810/* for object add operator */
811
812static const char *get_effector_defname(ePFieldType type)
813{
814 switch (type) {
815 case PFIELD_FORCE:
816 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Force");
817 case PFIELD_VORTEX:
818 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Vortex");
819 case PFIELD_MAGNET:
820 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Magnet");
821 case PFIELD_WIND:
822 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Wind");
823 case PFIELD_GUIDE:
824 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
825 case PFIELD_TEXTURE:
826 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "TextureField");
827 case PFIELD_HARMONIC:
828 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Harmonic");
829 case PFIELD_CHARGE:
830 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Charge");
831 case PFIELD_LENNARDJ:
832 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Lennard-Jones");
833 case PFIELD_BOID:
834 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Boid");
836 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Turbulence");
837 case PFIELD_DRAG:
838 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Drag");
839 case PFIELD_FLUIDFLOW:
840 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "FluidField");
841 case PFIELD_NULL:
842 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
843 case NUM_PFIELD_TYPES:
844 break;
845 }
846
847 BLI_assert(false);
848 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
849}
850
852{
853 bool enter_editmode;
854 ushort local_view_bits;
855 float loc[3], rot[3];
857 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
858
859 const ePFieldType type = static_cast<ePFieldType>(RNA_enum_get(op->ptr, "type"));
860 float dia = RNA_float_get(op->ptr, "radius");
861
862 Object *ob;
863 if (type == PFIELD_GUIDE) {
864 Main *bmain = CTX_data_main(C);
865 Scene *scene = CTX_data_scene(C);
866 ob = add_type(
867 C, OB_CURVES_LEGACY, get_effector_defname(type), loc, rot, false, local_view_bits);
868
869 Curve *cu = static_cast<Curve *>(ob->data);
870 cu->flag |= CU_PATH | CU_3D;
871 editmode_enter_ex(bmain, scene, ob, 0);
872
873 float mat[4][4];
874 new_primitive_matrix(C, ob, loc, rot, nullptr, mat);
875 mul_mat3_m4_fl(mat, dia);
878 if (!enter_editmode) {
879 editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
880 }
881 }
882 else {
883 ob = add_type(C, OB_EMPTY, get_effector_defname(type), loc, rot, false, local_view_bits);
885 if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) {
887 }
888 }
889
890 ob->pd = BKE_partdeflect_new(type);
891
892 return OPERATOR_FINISHED;
893}
894
896{
897 /* identifiers */
898 ot->name = "Add Effector";
899 ot->description = "Add an empty object with a physics effector to the scene";
900 ot->idname = "OBJECT_OT_effector_add";
901
902 /* api callbacks */
905
906 /* flags */
908
909 /* properties */
910 ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
911
913 add_generic_props(ot, true);
914}
915
918/* -------------------------------------------------------------------- */
923{
924 View3D *v3d = CTX_wm_view3d(C);
925 Scene *scene = CTX_data_scene(C);
926
927 /* force view align for cameras */
928 RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
929
930 ushort local_view_bits;
931 bool enter_editmode;
932 float loc[3], rot[3];
933 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
934
935 Object *ob = add_type(C, OB_CAMERA, nullptr, loc, rot, false, local_view_bits);
936
937 if (v3d) {
938 if (v3d->camera == nullptr) {
939 v3d->camera = ob;
940 }
941 if (v3d->scenelock && scene->camera == nullptr) {
942 scene->camera = ob;
943 }
944 }
945
946 Camera *cam = static_cast<Camera *>(ob->data);
947 cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
948 ED_scene_grid_scale(scene, nullptr);
949
950 return OPERATOR_FINISHED;
951}
952
954{
955 PropertyRNA *prop;
956
957 /* identifiers */
958 ot->name = "Add Camera";
959 ot->description = "Add a camera object to the scene";
960 ot->idname = "OBJECT_OT_camera_add";
961
962 /* api callbacks */
965
966 /* flags */
968
969 add_generic_props(ot, true);
970
971 /* hide this for cameras, default */
972 prop = RNA_struct_type_find_property(ot->srna, "align");
974}
975
978/* -------------------------------------------------------------------- */
983{
984 Main *bmain = CTX_data_main(C);
985 Scene *scene = CTX_data_scene(C);
986 ViewLayer *view_layer = CTX_data_view_layer(C);
987
988 ushort local_view_bits;
989 bool enter_editmode;
990 float loc[3], rot[3];
992 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
993
994 bool newob = false;
995 BKE_view_layer_synced_ensure(scene, view_layer);
996 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
997 if (obedit == nullptr || obedit->type != OB_MBALL) {
998 obedit = add_type(C, OB_MBALL, nullptr, loc, rot, true, local_view_bits);
999 newob = true;
1000 }
1001 else {
1003 }
1004
1005 float mat[4][4];
1006 new_primitive_matrix(C, obedit, loc, rot, nullptr, mat);
1007 /* Halving here is done to account for constant values from #BKE_mball_element_add.
1008 * While the default radius of the resulting meta element is 2,
1009 * we want to pass in 1 so other values such as resolution are scaled by 1.0. */
1010 float dia = RNA_float_get(op->ptr, "radius") / 2;
1011
1012 ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type"));
1013
1014 /* userdef */
1015 if (newob && !enter_editmode) {
1016 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1017 }
1018 else {
1019 /* Only needed in edit-mode (#add_type normally handles this). */
1021 }
1022
1023 return OPERATOR_FINISHED;
1024}
1025
1027{
1028 /* identifiers */
1029 ot->name = "Add Metaball";
1030 ot->description = "Add an metaball object to the scene";
1031 ot->idname = "OBJECT_OT_metaball_add";
1032
1033 /* api callbacks */
1037
1038 /* flags */
1040
1041 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
1042
1044 add_generic_props(ot, true);
1045}
1046
1049/* -------------------------------------------------------------------- */
1054{
1055 Object *obedit = CTX_data_edit_object(C);
1056 bool enter_editmode;
1057 ushort local_view_bits;
1058 float loc[3], rot[3];
1059
1061 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1062
1063 if (obedit && obedit->type == OB_FONT) {
1064 return OPERATOR_CANCELLED;
1065 }
1066
1067 obedit = add_type(C, OB_FONT, nullptr, loc, rot, enter_editmode, local_view_bits);
1068 BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
1069
1070 return OPERATOR_FINISHED;
1071}
1072
1074{
1075 /* identifiers */
1076 ot->name = "Add Text";
1077 ot->description = "Add a text object to the scene";
1078 ot->idname = "OBJECT_OT_text_add";
1079
1080 /* api callbacks */
1083
1084 /* flags */
1086
1087 /* properties */
1089 add_generic_props(ot, true);
1090}
1091
1094/* -------------------------------------------------------------------- */
1099{
1100 Main *bmain = CTX_data_main(C);
1101 Scene *scene = CTX_data_scene(C);
1102 ViewLayer *view_layer = CTX_data_view_layer(C);
1103 BKE_view_layer_synced_ensure(scene, view_layer);
1104 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
1105
1107 bool newob = false;
1108 bool enter_editmode;
1109 ushort local_view_bits;
1110 float loc[3], rot[3], dia;
1111 bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
1112
1114 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1115
1116 if ((obedit == nullptr) || (obedit->type != OB_ARMATURE)) {
1117 obedit = add_type(C, OB_ARMATURE, nullptr, loc, rot, true, local_view_bits);
1118 editmode_enter_ex(bmain, scene, obedit, 0);
1119 newob = true;
1120 }
1121 else {
1123 }
1124
1125 if (obedit == nullptr) {
1126 BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
1127 return OPERATOR_CANCELLED;
1128 }
1129
1130 /* Give the Armature its default bone collection. */
1131 bArmature *armature = static_cast<bArmature *>(obedit->data);
1132 BoneCollection *default_bonecoll = ANIM_armature_bonecoll_new(armature, "");
1133 ANIM_armature_bonecoll_active_set(armature, default_bonecoll);
1134
1135 dia = RNA_float_get(op->ptr, "radius");
1136 ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
1137
1138 /* userdef */
1139 if (newob && !enter_editmode) {
1140 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1141 }
1142
1143 return OPERATOR_FINISHED;
1144}
1145
1147{
1148 /* identifiers */
1149 ot->name = "Add Armature";
1150 ot->description = "Add an armature object to the scene";
1151 ot->idname = "OBJECT_OT_armature_add";
1152
1153 /* api callbacks */
1156
1157 /* flags */
1159
1160 /* properties */
1162 add_generic_props(ot, true);
1163}
1164
1167/* -------------------------------------------------------------------- */
1172{
1173 Object *ob;
1174 int type = RNA_enum_get(op->ptr, "type");
1175 ushort local_view_bits;
1176 float loc[3], rot[3];
1177
1179 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1180
1181 ob = add_type(C, OB_EMPTY, nullptr, loc, rot, false, local_view_bits);
1182
1184 BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
1185
1186 return OPERATOR_FINISHED;
1187}
1188
1190{
1191 /* identifiers */
1192 ot->name = "Add Empty";
1193 ot->description = "Add an empty object to the scene";
1194 ot->idname = "OBJECT_OT_empty_add";
1195
1196 /* api callbacks */
1200
1201 /* flags */
1203
1204 /* properties */
1205 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
1206
1208 add_generic_props(ot, false);
1209}
1210
1212{
1213 Image *ima = nullptr;
1214
1215 ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
1216 if (!ima) {
1217 return OPERATOR_CANCELLED;
1218 }
1219
1220 /* Add new empty. */
1221 ushort local_view_bits;
1222 float loc[3], rot[3];
1223
1224 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1225
1226 Object *ob = add_type(C, OB_EMPTY, nullptr, loc, rot, false, local_view_bits);
1227 ob->empty_drawsize = 5.0f;
1228
1229 if (RNA_boolean_get(op->ptr, "background")) {
1230 /* When "background" has been set to "true", set image to render in the background. */
1233
1235 if (rv3d->persp != RV3D_PERSP) {
1237 }
1238 }
1239
1241
1242 ob->data = ima;
1243
1244 return OPERATOR_FINISHED;
1245}
1246
1247static int object_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1248{
1249 if (!RNA_struct_property_is_set(op->ptr, "align")) {
1250 /* Default to Aligned unless something else was explicitly passed. */
1251 RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
1252 }
1253
1254 /* Check if the user has not specified the image to load.
1255 * If they have not, assume this is a drag an drop operation. */
1256 if (!RNA_struct_property_is_set(op->ptr, "filepath") &&
1258 {
1261 }
1262
1263 if (!RNA_struct_property_is_set(op->ptr, "background")) {
1264 /* Check if we should switch to "background" mode. */
1266 if (rv3d->persp != RV3D_PERSP) {
1267 RNA_boolean_set(op->ptr, "background", true);
1268 }
1269 }
1270
1271 float loc[3];
1272 location_from_view(C, loc);
1273 ED_view3d_cursor3d_position(C, event->mval, false, loc);
1274 RNA_float_set_array(op->ptr, "location", loc);
1275
1276 Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
1277
1278 /* Either change empty under cursor or create a new empty. */
1279 if (!ob_cursor || ob_cursor->type != OB_EMPTY) {
1280 return object_image_add_exec(C, op);
1281 }
1282 /* User dropped an image on an existing image. */
1283 Image *ima = nullptr;
1284
1285 ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
1286 if (!ima) {
1287 return OPERATOR_CANCELLED;
1288 }
1289 /* Handled below. */
1290 id_us_min(&ima->id);
1291
1292 Scene *scene = CTX_data_scene(C);
1295
1297
1298 id_us_min(static_cast<ID *>(ob_cursor->data));
1299 ob_cursor->data = ima;
1300 id_us_plus(static_cast<ID *>(ob_cursor->data));
1301 return OPERATOR_FINISHED;
1302}
1303
1305{
1307}
1308
1310{
1311 /* identifiers */
1312 ot->name = "Add Empty Image/Drop Image to Empty";
1313 ot->description = "Add an empty image type to scene with data";
1314 ot->idname = "OBJECT_OT_empty_image_add";
1315
1316 /* api callbacks */
1320
1321 /* flags */
1323
1324 /* properties */
1332
1334 add_generic_props(ot, false);
1335 PropertyRNA *prop;
1336 prop = RNA_def_boolean(ot->srna,
1337 "background",
1338 false,
1339 "Put in Background",
1340 "Make the image render behind all objects");
1342 /* Hide the filepath and relative path prop */
1343 prop = RNA_struct_type_find_property(ot->srna, "filepath");
1345 prop = RNA_struct_type_find_property(ot->srna, "relative_path");
1347}
1348
1351/* -------------------------------------------------------------------- */
1357 "2D",
1358 0,
1359 "2D Layers",
1360 "Display strokes using grease pencil layers to define order"},
1361 {GP_DRAWMODE_3D, "3D", 0, "3D Location", "Display strokes using real 3D position in 3D space"},
1362 {0, nullptr, 0, nullptr, nullptr},
1363};
1364
1366{
1367 Main *bmain = CTX_data_main(C);
1368 Scene *scene = CTX_data_scene(C);
1369 Object *original_active_object = CTX_data_active_object(C);
1370 /* TODO: For now, only support adding the 'Stroke' type. */
1371 const int type = RNA_enum_get(op->ptr, "type");
1372
1373 ushort local_view_bits;
1374 float loc[3], rot[3];
1375
1376 /* NOTE: We use 'Y' here (not 'Z'), as. */
1378 add_generic_get_opts(C, op, 'Y', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1379
1380 const char *ob_name = nullptr;
1381 switch (type) {
1382 case GP_EMPTY: {
1383 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "GPencil");
1384 break;
1385 }
1386 case GP_STROKE: {
1387 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Stroke");
1388 break;
1389 }
1390 case GP_MONKEY: {
1391 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Suzanne");
1392 break;
1393 }
1397 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "LineArt");
1398 break;
1399 }
1400 default: {
1401 break;
1402 }
1403 }
1404
1405 Object *object = add_type(C, OB_GREASE_PENCIL, ob_name, loc, rot, false, local_view_bits);
1406 GreasePencil &grease_pencil_id = *static_cast<GreasePencil *>(object->data);
1407 switch (type) {
1408 case GP_EMPTY: {
1409 greasepencil::create_blank(*bmain, *object, scene->r.cfra);
1410 break;
1411 }
1412 case GP_STROKE: {
1413 const float radius = RNA_float_get(op->ptr, "radius");
1414 const float3 scale(radius);
1415
1416 float4x4 mat;
1417 new_primitive_matrix(C, object, loc, rot, scale, mat.ptr());
1418
1419 greasepencil::create_stroke(*bmain, *object, mat, scene->r.cfra);
1420 break;
1421 }
1422 case GP_MONKEY: {
1423 const float radius = RNA_float_get(op->ptr, "radius");
1424 const float3 scale(radius);
1425
1426 float4x4 mat;
1427 new_primitive_matrix(C, object, loc, rot, scale, mat.ptr());
1428
1429 greasepencil::create_suzanne(*bmain, *object, mat, scene->r.cfra);
1430 break;
1431 }
1435 const int type = RNA_enum_get(op->ptr, "type");
1436 const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front");
1437 const bool use_lights = RNA_boolean_get(op->ptr, "use_lights");
1438 const int stroke_depth_order = RNA_enum_get(op->ptr, "stroke_depth_order");
1439 const float stroke_depth_offset = RNA_float_get(op->ptr, "stroke_depth_offset");
1440
1441 greasepencil::create_blank(*bmain, *object, scene->r.cfra);
1442
1443 auto *grease_pencil = reinterpret_cast<GreasePencil *>(object->data);
1444 auto *new_md = reinterpret_cast<ModifierData *>(
1446 auto *md = reinterpret_cast<GreasePencilLineartModifierData *>(new_md);
1447
1448 BLI_addtail(&object->modifiers, md);
1449 BKE_modifier_unique_name(&object->modifiers, new_md);
1450 BKE_modifiers_persistent_uid_init(*object, *new_md);
1451
1453 md->source_type = LINEART_SOURCE_COLLECTION;
1454 md->source_collection = CTX_data_collection(C);
1455 }
1456 else if (type == GREASE_PENCIL_LINEART_OBJECT) {
1457 md->source_type = LINEART_SOURCE_OBJECT;
1458 md->source_object = original_active_object;
1459 }
1460 else {
1461 /* Whole scene. */
1462 md->source_type = LINEART_SOURCE_SCENE;
1463 }
1464 /* Only created one layer and one material. */
1465 STRNCPY(md->target_layer, grease_pencil->get_active_layer()->name().c_str());
1466 md->target_material = BKE_object_material_get(object, 0);
1467 if (md->target_material) {
1468 id_us_plus(&md->target_material->id);
1469 }
1470
1471 if (use_lights) {
1472 object->dtx |= OB_USE_GPENCIL_LIGHTS;
1473 }
1474 else {
1475 object->dtx &= ~OB_USE_GPENCIL_LIGHTS;
1476 }
1477
1478 /* Stroke object is drawn in front of meshes by default. */
1479 if (use_in_front) {
1480 object->dtx |= OB_DRAW_IN_FRONT;
1481 }
1482 else {
1483 if (stroke_depth_order == GP_DRAWMODE_3D) {
1484 grease_pencil->flag |= GREASE_PENCIL_STROKE_ORDER_3D;
1485 }
1486 md->stroke_depth_offset = stroke_depth_offset;
1487 }
1488
1489 break;
1490 }
1491 }
1492
1493 DEG_id_tag_update(&grease_pencil_id.id, ID_RECALC_GEOMETRY);
1494 WM_main_add_notifier(NC_GEOM | ND_DATA, &grease_pencil_id.id);
1495
1496 return OPERATOR_FINISHED;
1497}
1498
1500{
1501 /* identifiers */
1502 ot->name = "Add Grease Pencil";
1503 ot->description = "Add a Grease Pencil object to the scene";
1504 ot->idname = "OBJECT_OT_grease_pencil_add";
1505
1506 /* api callbacks */
1509
1510 /* flags */
1512
1513 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
1516 "use_in_front",
1517 true,
1518 "Show In Front",
1519 "Show Line Art grease pencil in front of everything");
1521 "stroke_depth_offset",
1522 0.05f,
1523 0.0f,
1524 FLT_MAX,
1525 "Stroke Offset",
1526 "Stroke offset for the Line Art modifier",
1527 0.0f,
1528 0.5f);
1530 ot->srna, "use_lights", false, "Use Lights", "Use lights for this grease pencil object");
1532 ot->srna,
1533 "stroke_depth_order",
1536 "Stroke Depth Order",
1537 "Defines how the strokes are ordered in 3D space (for objects not displayed 'In Front')");
1538
1540 add_generic_props(ot, false);
1541}
1542
1545/* -------------------------------------------------------------------- */
1549static const char *get_light_defname(int type)
1550{
1551 switch (type) {
1552 case LA_LOCAL:
1553 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
1554 case LA_SUN:
1555 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
1556 case LA_SPOT:
1557 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
1558 case LA_AREA:
1559 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
1560 default:
1561 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
1562 }
1563}
1564
1566{
1567 Object *ob;
1568 Light *la;
1569 int type = RNA_enum_get(op->ptr, "type");
1570 ushort local_view_bits;
1571 float loc[3], rot[3];
1572
1574 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1575
1576 ob = add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
1577
1578 float size = RNA_float_get(op->ptr, "radius");
1579 /* Better defaults for light size. */
1580 switch (type) {
1581 case LA_LOCAL:
1582 case LA_SPOT:
1583 break;
1584 case LA_AREA:
1585 size *= 4.0f;
1586 break;
1587 default:
1588 size *= 0.5f;
1589 break;
1590 }
1592
1593 la = (Light *)ob->data;
1594 la->type = type;
1595
1596 if (type == LA_SUN) {
1597 la->energy = 1.0f;
1598 }
1599
1600 return OPERATOR_FINISHED;
1601}
1602
1604{
1605 /* identifiers */
1606 ot->name = "Add Light";
1607 ot->description = "Add a light object to the scene";
1608 ot->idname = "OBJECT_OT_light_add";
1609
1610 /* api callbacks */
1614
1615 /* flags */
1617
1618 /* properties */
1619 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
1621
1623 add_generic_props(ot, false);
1624}
1625
1628/* -------------------------------------------------------------------- */
1633 /* The collection that is supposed to be added, determined through operator properties. */
1635 /* The local-view bits (if any) the object should have set to become visible in current context.
1636 */
1638 /* The transform that should be applied to the collection, determined through operator properties
1639 * if set (e.g. to place the collection under the cursor), otherwise through context (e.g. 3D
1640 * cursor location). */
1641 float loc[3], rot[3];
1642};
1643
1644static std::optional<CollectionAddInfo> collection_add_info_get_from_op(bContext *C,
1645 wmOperator *op)
1646{
1647 CollectionAddInfo add_info{};
1648
1649 Main *bmain = CTX_data_main(C);
1650
1651 PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location");
1652
1653 add_info.collection = reinterpret_cast<Collection *>(
1655
1656 bool update_location_if_necessary = false;
1657 if (add_info.collection) {
1658 update_location_if_necessary = true;
1659 }
1660 else {
1661 add_info.collection = static_cast<Collection *>(
1662 BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection")));
1663 }
1664
1665 if (update_location_if_necessary && CTX_wm_region_view3d(C)) {
1666 int mval[2];
1667 if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
1668 location_from_view(C, add_info.loc);
1669 ED_view3d_cursor3d_position(C, mval, false, add_info.loc);
1670 RNA_property_float_set_array(op->ptr, prop_location, add_info.loc);
1671 }
1672 }
1673
1674 if (add_info.collection == nullptr) {
1675 return std::nullopt;
1676 }
1677
1679 op,
1680 'Z',
1681 add_info.loc,
1682 add_info.rot,
1683 nullptr,
1684 nullptr,
1685 &add_info.local_view_bits,
1686 nullptr);
1687
1688 ViewLayer *view_layer = CTX_data_view_layer(C);
1689
1690 /* Avoid dependency cycles. */
1691 LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
1692 while (BKE_collection_cycle_find(active_lc->collection, add_info.collection)) {
1693 active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
1694 }
1695
1696 return add_info;
1697}
1698
1700{
1701 std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
1702 if (!add_info) {
1703 return OPERATOR_CANCELLED;
1704 }
1705
1706 Object *ob = add_type(C,
1707 OB_EMPTY,
1708 add_info->collection->id.name + 2,
1709 add_info->loc,
1710 add_info->rot,
1711 false,
1712 add_info->local_view_bits);
1713 ob->instance_collection = add_info->collection;
1714 ob->empty_drawsize = U.collection_instance_empty_size;
1716 id_us_plus(&add_info->collection->id);
1717
1718 return OPERATOR_FINISHED;
1719}
1720
1722{
1723 if (!object_add_drop_xy_is_set(op)) {
1724 RNA_int_set(op->ptr, "drop_x", event->xy[0]);
1725 RNA_int_set(op->ptr, "drop_y", event->xy[1]);
1726 }
1727
1729 return WM_enum_search_invoke(C, op, event);
1730 }
1731 return op->type->exec(C, op);
1732}
1733
1735{
1736 PropertyRNA *prop;
1737
1738 /* identifiers */
1739 ot->name = "Add Collection Instance";
1740 ot->description = "Add a collection instance";
1741 ot->idname = "OBJECT_OT_collection_instance_add";
1742
1743 /* api callbacks */
1747
1748 /* flags */
1750
1751 /* properties */
1753 ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
1754 prop = RNA_def_enum(ot->srna, "collection", rna_enum_dummy_NULL_items, 0, "Collection", "");
1757 ot->prop = prop;
1758 add_generic_props(ot, false);
1759
1761
1763}
1764
1767/* -------------------------------------------------------------------- */
1787{
1788 Main *bmain = CTX_data_main(C);
1789 LayerCollection *active_collection = CTX_data_layer_collection(C);
1790 std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
1791 if (!add_info) {
1792 return OPERATOR_CANCELLED;
1793 }
1794
1795 if (RNA_boolean_get(op->ptr, "use_instance")) {
1796 BKE_collection_child_remove(bmain, active_collection->collection, add_info->collection);
1799
1800 Object *ob = add_type(C,
1801 OB_EMPTY,
1802 add_info->collection->id.name + 2,
1803 add_info->loc,
1804 add_info->rot,
1805 false,
1806 add_info->local_view_bits);
1807 ob->instance_collection = add_info->collection;
1808 ob->empty_drawsize = U.collection_instance_empty_size;
1810 id_us_plus(&add_info->collection->id);
1811 }
1812 else if (ID_IS_EDITABLE(&add_info->collection->id)) {
1813 ViewLayer *view_layer = CTX_data_view_layer(C);
1814 float delta_mat[4][4];
1815 unit_m4(delta_mat);
1816
1817 const float scale[3] = {1.0f, 1.0f, 1.0f};
1818 loc_eul_size_to_mat4(delta_mat, add_info->loc, add_info->rot, scale);
1819
1820 float offset[3];
1821 /* Reverse apply the instance offset, so toggling the Instance option doesn't cause the
1822 * collection to jump. */
1823 negate_v3_v3(offset, add_info->collection->instance_offset);
1824 translate_m4(delta_mat, UNPACK3(offset));
1825
1828 view_layer, nullptr, &params);
1829 object_xform_array_m4(objects.data(), objects.size(), delta_mat);
1830 }
1831
1832 return OPERATOR_FINISHED;
1833}
1834
1836{
1837 PropertyRNA *prop;
1838
1839 /* identifiers */
1840 /* Name should only be displayed in the drag tooltip. */
1841 ot->name = "Add Collection";
1842 ot->description = "Add the dragged collection to the scene";
1843 ot->idname = "OBJECT_OT_collection_external_asset_drop";
1844
1845 /* api callbacks */
1849
1850 /* flags */
1852
1853 /* properties */
1855
1856 add_generic_props(ot, false);
1857
1858 /* IMPORTANT: Instancing option. Intentionally remembered across executions (no #PROP_SKIP_SAVE).
1859 */
1861 "use_instance",
1862 true,
1863 "Instance",
1864 "Add the dropped collection as collection instance");
1865
1867
1868 prop = RNA_def_enum(ot->srna, "collection", rna_enum_dummy_NULL_items, 0, "Collection", "");
1871 ot->prop = prop;
1872}
1873
1876/* -------------------------------------------------------------------- */
1883{
1884 Main *bmain = CTX_data_main(C);
1885 ID *id = nullptr;
1886 ushort local_view_bits;
1887 float loc[3], rot[3];
1888
1889 PropertyRNA *prop_type = RNA_struct_find_property(op->ptr, "type");
1890 PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location");
1891
1892 const short id_type = RNA_property_enum_get(op->ptr, prop_type);
1894 if (id == nullptr) {
1895 return OPERATOR_CANCELLED;
1896 }
1897 const int object_type = BKE_object_obdata_to_type(id);
1898 if (object_type == -1) {
1899 return OPERATOR_CANCELLED;
1900 }
1901
1902 if (CTX_wm_region_view3d(C)) {
1903 int mval[2];
1904 if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
1905 location_from_view(C, loc);
1906 ED_view3d_cursor3d_position(C, mval, false, loc);
1907 RNA_property_float_set_array(op->ptr, prop_location, loc);
1908 }
1909 }
1910
1911 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1912
1913 add_type_with_obdata(C, object_type, id->name + 2, loc, rot, false, local_view_bits, id);
1914
1915 return OPERATOR_FINISHED;
1916}
1917
1919{
1920 /* identifiers */
1921 ot->name = "Add Object Data Instance";
1922 ot->description = "Add an object data instance";
1923 ot->idname = "OBJECT_OT_data_instance_add";
1924
1925 /* api callbacks */
1929
1930 /* flags */
1932
1933 /* properties */
1935 PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_id_type_items, 0, "Type", "");
1937 add_generic_props(ot, false);
1938
1940}
1941
1944/* -------------------------------------------------------------------- */
1949{
1950 Main *bmain = CTX_data_main(C);
1951 Scene *scene = CTX_data_scene(C);
1952
1953 ushort local_view_bits;
1954 float loc[3], rot[3];
1955 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1956
1957 Object *ob = add_type(C, OB_SPEAKER, nullptr, loc, rot, false, local_view_bits);
1958 const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob);
1959
1960 /* To make it easier to start using this immediately in NLA, a default sound clip is created
1961 * ready to be moved around to re-time the sound and/or make new sound clips. */
1962 {
1963 /* create new data for NLA hierarchy */
1964 AnimData *adt = BKE_animdata_ensure_id(&ob->id);
1965 NlaTrack *nlt = BKE_nlatrack_new_tail(&adt->nla_tracks, is_liboverride);
1967 NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, static_cast<Speaker *>(ob->data));
1968 strip->start = scene->r.cfra;
1969 strip->end += strip->start;
1970
1971 /* hook them up */
1972 BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
1973
1974 /* Auto-name the strip, and give the track an interesting name. */
1975 STRNCPY_UTF8(nlt->name, DATA_("SoundTrack"));
1976 BKE_nlastrip_validate_name(adt, strip);
1977
1979 }
1980
1981 return OPERATOR_FINISHED;
1982}
1983
1985{
1986 /* identifiers */
1987 ot->name = "Add Speaker";
1988 ot->description = "Add a speaker object to the scene";
1989 ot->idname = "OBJECT_OT_speaker_add";
1990
1991 /* api callbacks */
1994
1995 /* flags */
1997
1998 add_generic_props(ot, true);
1999}
2000
2003/* -------------------------------------------------------------------- */
2008{
2009 ushort local_view_bits;
2010 float loc[3], rot[3];
2011 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2012
2013 Object *object = add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits);
2014
2015 Curves *curves_id = static_cast<Curves *>(object->data);
2016 curves_id->geometry.wrap() = ed::curves::primitive_random_sphere(500, 8);
2017
2018 return OPERATOR_FINISHED;
2019}
2020
2022{
2023 /* identifiers */
2024 ot->name = "Add Random Curves";
2025 ot->description = "Add a curves object with random curves to the scene";
2026 ot->idname = "OBJECT_OT_curves_random_add";
2027
2028 /* api callbacks */
2031
2032 /* flags */
2034
2035 add_generic_props(ot, false);
2036}
2037
2039{
2040 Scene *scene = CTX_data_scene(C);
2041
2042 ushort local_view_bits;
2043 add_generic_get_opts(C, op, 'Z', nullptr, nullptr, nullptr, nullptr, &local_view_bits, nullptr);
2044
2045 Object *surface_ob = CTX_data_active_object(C);
2046 BLI_assert(surface_ob != nullptr);
2047
2048 Object *curves_ob = add_type(C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits);
2049 BKE_object_apply_mat4(curves_ob, surface_ob->object_to_world().ptr(), false, false);
2050
2051 /* Set surface object. */
2052 Curves *curves_id = static_cast<Curves *>(curves_ob->data);
2053 curves_id->surface = surface_ob;
2054
2055 /* Parent to surface object. */
2056 parent_set(op->reports, C, scene, curves_ob, surface_ob, PAR_OBJECT, false, true, nullptr);
2057
2058 /* Decide which UV map to use for attachment. */
2059 Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data);
2060 const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->corner_data,
2062 if (uv_name != nullptr) {
2063 curves_id->surface_uv_map = BLI_strdup(uv_name);
2064 }
2065
2066 /* Add deformation modifier. */
2068
2069 /* Make sure the surface object has a rest position attribute which is necessary for
2070 * deformations. */
2072
2073 return OPERATOR_FINISHED;
2074}
2075
2077{
2078 if (!ED_operator_objectmode(C)) {
2079 return false;
2080 }
2082 if (ob == nullptr || ob->type != OB_MESH) {
2083 CTX_wm_operator_poll_msg_set(C, "No active mesh object");
2084 return false;
2085 }
2086 return true;
2087}
2088
2090{
2091 ot->name = "Add Empty Curves";
2092 ot->description = "Add an empty curve object to the scene with the selected mesh as surface";
2093 ot->idname = "OBJECT_OT_curves_empty_hair_add";
2094
2097
2099
2100 add_generic_props(ot, false);
2101}
2102
2105/* -------------------------------------------------------------------- */
2110{
2111 if (!U.experimental.use_new_point_cloud_type) {
2112 return false;
2113 }
2114 return ED_operator_objectmode(C);
2115}
2116
2118{
2119 ushort local_view_bits;
2120 float loc[3], rot[3];
2121 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2122
2123 Object *object = add_type(C, OB_POINTCLOUD, nullptr, loc, rot, false, local_view_bits);
2124 object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
2125
2126 return OPERATOR_FINISHED;
2127}
2128
2130{
2131 /* identifiers */
2132 ot->name = "Add Point Cloud";
2133 ot->description = "Add a point cloud object to the scene";
2134 ot->idname = "OBJECT_OT_pointcloud_add";
2135
2136 /* api callbacks */
2139
2140 /* flags */
2142
2143 add_generic_props(ot, false);
2144}
2145
2148/* -------------------------------------------------------------------- */
2152void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
2153{
2154 if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
2156 {
2157 /* We cannot delete indirectly used object... */
2158 printf(
2159 "WARNING, undeletable object '%s', should have been caught before reaching this "
2160 "function!",
2161 ob->id.name + 2);
2162 return;
2163 }
2165 /* Do not delete objects used by overrides of collections. */
2166 return;
2167 }
2168
2170
2171 BKE_scene_collections_object_remove(bmain, scene, ob, true);
2172}
2173
2180
2182{
2183 Main *bmain = CTX_data_main(C);
2184 Scene *scene = CTX_data_scene(C);
2186 const bool use_global = RNA_boolean_get(op->ptr, "use_global");
2187 const bool confirm = op->flag & OP_IS_INVOKE;
2188 uint changed_count = 0;
2189 uint tagged_count = 0;
2190
2191 if (CTX_data_edit_object(C)) {
2192 return OPERATOR_CANCELLED;
2193 }
2194
2195 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2196
2197 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2198 if (ob->id.tag & ID_TAG_INDIRECT) {
2199 /* Can this case ever happen? */
2200 BKE_reportf(op->reports,
2202 "Cannot delete indirectly linked object '%s'",
2203 ob->id.name + 2);
2204 continue;
2205 }
2206
2207 if (!BKE_lib_override_library_id_is_user_deletable(bmain, &ob->id)) {
2208 BKE_reportf(op->reports,
2210 "Cannot delete object '%s' as it is used by override collections",
2211 ob->id.name + 2);
2212 continue;
2213 }
2214
2215 if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
2217 {
2218 BKE_reportf(op->reports,
2220 "Cannot delete object '%s' from scene '%s', indirectly used objects need at "
2221 "least one user",
2222 ob->id.name + 2,
2223 scene->id.name + 2);
2224 continue;
2225 }
2226
2227 /* if grease pencil object, set cache as dirty */
2228 if (ob->type == OB_GPENCIL_LEGACY) {
2229 bGPdata *gpd = (bGPdata *)ob->data;
2231 }
2232
2233 /* Use multi tagged delete if `use_global=True`, or the object is used only in one scene. */
2234 if (use_global || ID_REAL_USERS(ob) <= 1) {
2235 ob->id.tag |= ID_TAG_DOIT;
2236 tagged_count += 1;
2237 }
2238 else {
2239 /* Object is used in multiple scenes. Delete the object from the current scene only. */
2241 changed_count += 1;
2242
2243 /* FIXME: this will also remove parent from grease pencil from other scenes. */
2244 /* Remove from Grease Pencil parent */
2245 LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) {
2246 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2247 if (gpl->parent != nullptr) {
2248 if (gpl->parent == ob) {
2249 gpl->parent = nullptr;
2250 }
2251 }
2252 }
2253 }
2254 }
2255 }
2257
2258 if ((changed_count + tagged_count) == 0) {
2259 return OPERATOR_CANCELLED;
2260 }
2261
2262 if (tagged_count > 0) {
2264 }
2265
2266 if (confirm) {
2267 BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", (changed_count + tagged_count));
2268 }
2269
2270 /* delete has to handle all open scenes */
2272 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
2273 scene = WM_window_get_active_scene(win);
2274
2275 if (scene->id.tag & ID_TAG_DOIT) {
2276 scene->id.tag &= ~ID_TAG_DOIT;
2277
2279
2283 }
2284 }
2285
2286 return OPERATOR_FINISHED;
2287}
2288
2289static int object_delete_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
2290{
2291 if (RNA_boolean_get(op->ptr, "confirm")) {
2292 return WM_operator_confirm_ex(C,
2293 op,
2294 IFACE_("Delete selected objects?"),
2295 nullptr,
2296 IFACE_("Delete"),
2298 false);
2299 }
2300 return object_delete_exec(C, op);
2301}
2302
2304{
2305 /* identifiers */
2306 ot->name = "Delete";
2307 ot->description = "Delete selected objects";
2308 ot->idname = "OBJECT_OT_delete";
2309
2310 /* api callbacks */
2314
2315 /* flags */
2317
2318 PropertyRNA *prop;
2319 prop = RNA_def_boolean(
2320 ot->srna, "use_global", false, "Delete Globally", "Remove object from all scenes");
2323}
2324
2327/* -------------------------------------------------------------------- */
2331/* after copying objects, copied data should get new pointers */
2333{
2334 Main *bmain = CTX_data_main(C);
2335
2336 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
2337 BKE_libblock_relink_to_newid(bmain, &ob->id, 0);
2338 }
2340
2341#ifndef NDEBUG
2342 /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
2343 ID *id_iter;
2344 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2345 if (GS(id_iter->name) == ID_OB) {
2346 /* Not all duplicated objects would be used by other newly duplicated data, so their flag
2347 * will not always be cleared. */
2348 continue;
2349 }
2350 BLI_assert((id_iter->tag & ID_TAG_NEW) == 0);
2351 }
2353#endif
2354
2356}
2357
2360/* -------------------------------------------------------------------- */
2364/* XXX TODO: That whole hierarchy handling based on persistent_id tricks is
2365 * very confusing and convoluted, and it will fail in many cases besides basic ones.
2366 * Think this should be replaced by a proper tree-like representation of the instantiations,
2367 * should help a lot in both readability, and precise consistent rebuilding of hierarchy.
2368 */
2369
2383static uint dupliobject_hash(const void *ptr)
2384{
2385 const DupliObject *dob = static_cast<const DupliObject *>(ptr);
2387
2388 if (dob->type == OB_DUPLICOLLECTION) {
2389 for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
2390 hash ^= (dob->persistent_id[i] ^ i);
2391 }
2392 }
2393 else {
2394 hash ^= (dob->persistent_id[0] ^ 0);
2395 }
2396 return hash;
2397}
2398
2406{
2407 const DupliObject *dob = static_cast<const DupliObject *>(ptr);
2409 for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
2410 hash ^= (dob->persistent_id[i] ^ i);
2411 }
2412 return hash;
2413}
2414
2418static bool dupliobject_cmp(const void *a_, const void *b_)
2419{
2420 const DupliObject *a = static_cast<const DupliObject *>(a_);
2421 const DupliObject *b = static_cast<const DupliObject *>(b_);
2422
2423 if (a->ob != b->ob) {
2424 return true;
2425 }
2426
2427 if (a->type != b->type) {
2428 return true;
2429 }
2430
2431 if (a->type == OB_DUPLICOLLECTION) {
2432 for (int i = 1; (i < MAX_DUPLI_RECUR); i++) {
2433 if (a->persistent_id[i] != b->persistent_id[i]) {
2434 return true;
2435 }
2436 if (a->persistent_id[i] == INT_MAX) {
2437 break;
2438 }
2439 }
2440 }
2441 else {
2442 if (a->persistent_id[0] != b->persistent_id[0]) {
2443 return true;
2444 }
2445 }
2446
2447 /* matching */
2448 return false;
2449}
2450
2451/* Compare function that matches dupliobject_instancer_hash. */
2452static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
2453{
2454 const DupliObject *a = static_cast<const DupliObject *>(a_);
2455 const DupliObject *b = static_cast<const DupliObject *>(b_);
2456
2457 for (int i = 0; (i < MAX_DUPLI_RECUR); i++) {
2458 if (a->persistent_id[i] != b->persistent_id[i]) {
2459 return true;
2460 }
2461 if (a->persistent_id[i] == INT_MAX) {
2462 break;
2463 }
2464 }
2465
2466 /* matching */
2467 return false;
2468}
2469
2471 Depsgraph *depsgraph,
2472 Scene *scene,
2473 Base *base,
2474 const bool use_base_parent,
2475 const bool use_hierarchy)
2476{
2477 Main *bmain = CTX_data_main(C);
2478 ViewLayer *view_layer = CTX_data_view_layer(C);
2479 GHash *parent_gh = nullptr, *instancer_gh = nullptr;
2480
2481 Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
2482
2483 if (!(base->object->transflag & OB_DUPLI) &&
2485 {
2486 return;
2487 }
2488
2489 ListBase *lb_duplis = object_duplilist(depsgraph, scene, object_eval);
2490
2491 if (BLI_listbase_is_empty(lb_duplis)) {
2492 free_object_duplilist(lb_duplis);
2493 return;
2494 }
2495
2496 GHash *dupli_gh = BLI_ghash_ptr_new(__func__);
2497 if (use_hierarchy) {
2498 parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
2499
2500 if (use_base_parent) {
2501 instancer_gh = BLI_ghash_new(
2503 }
2504 }
2505
2506 LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) {
2507 Object *ob_src = DEG_get_original_object(dob->ob);
2508 Object *ob_dst = static_cast<Object *>(ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id)));
2509 id_us_min(&ob_dst->id);
2510
2511 /* font duplis can have a totcol without material, we get them from parent
2512 * should be implemented better...
2513 */
2514 if (ob_dst->mat == nullptr) {
2515 ob_dst->totcol = 0;
2516 }
2517
2518 BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
2519 BKE_view_layer_synced_ensure(scene, view_layer);
2520 Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
2521 BLI_assert(base_dst != nullptr);
2522
2523 base_select(base_dst, BA_SELECT);
2525
2527
2528 /* make sure apply works */
2529 BKE_animdata_free(&ob_dst->id, true);
2530 ob_dst->adt = nullptr;
2531
2532 ob_dst->parent = nullptr;
2534 ob_dst->runtime->curve_cache = nullptr;
2535 const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0;
2536 ob_dst->transflag &= ~OB_DUPLI;
2537 /* Remove instantiated collection, it's annoying to keep it here
2538 * (and get potentially a lot of usages of it then...). */
2539 id_us_min((ID *)ob_dst->instance_collection);
2540 ob_dst->instance_collection = nullptr;
2541
2542 copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob->mat);
2543 BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world().ptr(), false, false);
2544
2545 BLI_ghash_insert(dupli_gh, dob, ob_dst);
2546 if (parent_gh) {
2547 void **val;
2548 /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
2549 * 'the same', this avoids trying to insert same key several time and
2550 * raise asserts in debug builds... */
2551 if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
2552 *val = ob_dst;
2553 }
2554
2555 if (is_dupli_instancer && instancer_gh) {
2556 /* Same as above, we may have several 'hits'. */
2557 if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) {
2558 *val = ob_dst;
2559 }
2560 }
2561 }
2562 }
2563
2564 LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) {
2565 Object *ob_src = dob->ob;
2566 Object *ob_dst = static_cast<Object *>(BLI_ghash_lookup(dupli_gh, dob));
2567
2568 /* Remap new object to itself, and clear again newid pointer of orig object. */
2569 BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0);
2570
2572
2573 if (use_hierarchy) {
2574 /* original parents */
2575 Object *ob_src_par = ob_src->parent;
2576 Object *ob_dst_par = nullptr;
2577
2578 /* find parent that was also made real */
2579 if (ob_src_par) {
2580 /* OK to keep most of the members uninitialized,
2581 * they won't be read, this is simply for a hash lookup. */
2582 DupliObject dob_key;
2583 dob_key.ob = ob_src_par;
2584 dob_key.type = dob->type;
2585 if (dob->type == OB_DUPLICOLLECTION) {
2586 memcpy(&dob_key.persistent_id[1],
2587 &dob->persistent_id[1],
2588 sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
2589 }
2590 else {
2591 dob_key.persistent_id[0] = dob->persistent_id[0];
2592 }
2593 ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(parent_gh, &dob_key));
2594 }
2595
2596 if (ob_dst_par) {
2597 /* allow for all possible parent types */
2598 ob_dst->partype = ob_src->partype;
2599 STRNCPY(ob_dst->parsubstr, ob_src->parsubstr);
2600 ob_dst->par1 = ob_src->par1;
2601 ob_dst->par2 = ob_src->par2;
2602 ob_dst->par3 = ob_src->par3;
2603
2604 copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
2605
2606 ob_dst->parent = ob_dst_par;
2607 }
2608 }
2609 if (use_base_parent && ob_dst->parent == nullptr) {
2610 Object *ob_dst_par = nullptr;
2611
2612 if (instancer_gh != nullptr) {
2613 /* OK to keep most of the members uninitialized,
2614 * they won't be read, this is simply for a hash lookup. */
2615 DupliObject dob_key;
2616 /* We are looking one step upper in hierarchy, so we need to 'shift' the `persistent_id`,
2617 * ignoring the first item.
2618 * We only check on persistent_id here, since we have no idea what object it might be. */
2619 memcpy(&dob_key.persistent_id[0],
2620 &dob->persistent_id[1],
2621 sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
2622 ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(instancer_gh, &dob_key));
2623 }
2624
2625 if (ob_dst_par == nullptr) {
2626 /* Default to parenting to root object...
2627 * Always the case when use_hierarchy is false. */
2628 ob_dst_par = base->object;
2629 }
2630
2631 ob_dst->parent = ob_dst_par;
2632 ob_dst->partype = PAROBJECT;
2633 }
2634
2635 if (ob_dst->parent) {
2636 /* NOTE: this may be the parent of other objects, but it should
2637 * still work out ok */
2638 BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
2639
2640 /* to set ob_dst->orig and in case there's any other discrepancies */
2642 }
2643 }
2644
2646 base->object->instance_collection = nullptr;
2647 }
2648
2649 base_select(base, BA_DESELECT);
2651
2652 BLI_ghash_free(dupli_gh, nullptr, nullptr);
2653 if (parent_gh) {
2654 BLI_ghash_free(parent_gh, nullptr, nullptr);
2655 }
2656 if (instancer_gh) {
2657 BLI_ghash_free(instancer_gh, nullptr, nullptr);
2658 }
2659
2660 free_object_duplilist(lb_duplis);
2661
2663
2664 base->object->transflag &= ~OB_DUPLI;
2666}
2667
2669{
2670 Main *bmain = CTX_data_main(C);
2672 Scene *scene = CTX_data_scene(C);
2673
2674 const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
2675 const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
2676
2678
2679 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
2680 make_object_duplilist_real(C, depsgraph, scene, base, use_base_parent, use_hierarchy);
2681
2682 /* dependencies were changed */
2683 WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
2684 }
2686
2691
2692 return OPERATOR_FINISHED;
2693}
2694
2696{
2697 /* identifiers */
2698 ot->name = "Make Instances Real";
2699 ot->description = "Make instanced objects attached to this object real";
2700 ot->idname = "OBJECT_OT_duplicates_make_real";
2701
2702 /* api callbacks */
2704
2706
2707 /* flags */
2709
2711 "use_base_parent",
2712 false,
2713 "Parent",
2714 "Parent newly created objects to the original instancer");
2717 ot->srna, "use_hierarchy", false, "Keep Hierarchy", "Maintain parent child relationships");
2718}
2719
2722/* -------------------------------------------------------------------- */
2728 "CURVE",
2729 ICON_OUTLINER_OB_CURVE,
2730 "Curve",
2731 "Curve from Mesh or Text objects"},
2732 {OB_MESH,
2733 "MESH",
2734 ICON_OUTLINER_OB_MESH,
2735 "Mesh",
2736#ifdef WITH_POINT_CLOUD
2737 "Mesh from Curve, Surface, Metaball, Text, or Point Cloud objects"},
2738#else
2739 "Mesh from Curve, Surface, Metaball, or Text objects"},
2740#endif
2741#if 0
2743 "GPENCIL",
2744 ICON_OUTLINER_OB_GREASEPENCIL,
2745 "Grease Pencil",
2746 "Grease Pencil from Curve or Mesh objects"},
2747#endif
2748#ifdef WITH_POINT_CLOUD
2750 "POINTCLOUD",
2751 ICON_OUTLINER_OB_POINTCLOUD,
2752 "Point Cloud",
2753 "Point Cloud from Mesh objects"},
2754#endif
2755 {OB_CURVES, "CURVES", ICON_OUTLINER_OB_CURVES, "Curves", "Curves from evaluated curve data"},
2757 "GREASEPENCIL",
2758 ICON_OUTLINER_OB_GREASEPENCIL,
2759 "Grease Pencil",
2760 "Grease Pencil from Curve or Mesh objects"},
2761 {0, nullptr, 0, nullptr, nullptr},
2762};
2763
2765 PointerRNA * /*ptr*/,
2766 PropertyRNA * /*prop*/,
2767 bool *r_free)
2768{
2769 if (!C) { /* needed for docs */
2770 return convert_target_items;
2771 }
2772
2773 EnumPropertyItem *item = nullptr;
2774 int totitem = 0;
2775
2779 if (U.experimental.use_new_point_cloud_type) {
2781 }
2783
2784 RNA_enum_item_end(&item, &totitem);
2785
2786 *r_free = true;
2787
2788 return item;
2789}
2790
2791static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
2792{
2793 Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
2794 Curve *curve = static_cast<Curve *>(ob->data);
2795
2796 Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
2797 if (mesh == nullptr) {
2798 /* Unable to convert the curve to a mesh. */
2799 return;
2800 }
2801
2803 /* Replace curve used by the object itself. */
2804 ob->data = mesh;
2805 ob->type = OB_MESH;
2806 id_us_min(&curve->id);
2807 id_us_plus(&mesh->id);
2808 /* Change objects which are using same curve.
2809 * A bit annoying, but:
2810 * - It's possible to have multiple curve objects selected which are sharing the same curve
2811 * data-block. We don't want mesh to be created for every of those objects.
2812 * - This is how conversion worked for a long time. */
2813 LISTBASE_FOREACH (Object *, other_object, &bmain->objects) {
2814 if (other_object->data == curve) {
2815 other_object->type = OB_MESH;
2816
2817 id_us_min((ID *)other_object->data);
2818 other_object->data = ob->data;
2819 id_us_plus((ID *)other_object->data);
2820 }
2821 }
2822}
2823
2825{
2826 Scene *scene = CTX_data_scene(C);
2827 Base *base_act = CTX_data_active_base(C);
2828 Object *obact = base_act ? base_act->object : nullptr;
2829
2830 if (obact == nullptr || obact->data == nullptr || !ID_IS_EDITABLE(obact) ||
2832 {
2833 return false;
2834 }
2835
2836 return (ID_IS_EDITABLE(scene) && (BKE_object_is_in_editmode(obact) == false) &&
2837 (base_act->flag & BASE_SELECTED));
2838}
2839
2840/* Helper for object_convert_exec */
2842 Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
2843{
2844 if (ob == nullptr) {
2845 ob = base->object;
2846 }
2847
2848 Object *obn = (Object *)BKE_id_copy(bmain, &ob->id);
2849 id_us_min(&obn->id);
2851 BKE_collection_object_add_from(bmain, scene, ob, obn);
2852
2853 BKE_view_layer_synced_ensure(scene, view_layer);
2854 Base *basen = BKE_view_layer_base_find(view_layer, obn);
2855 base_select(basen, BA_SELECT);
2856 base_select(base, BA_DESELECT);
2857
2858 /* XXX: An ugly hack needed because if we re-run depsgraph with some new meta-ball objects
2859 * having same 'family name' as orig ones, they will affect end result of meta-ball computation.
2860 * For until we get rid of that name-based thingy in meta-balls, that should do the trick
2861 * (this is weak, but other solution (to change name of `obn`) is even worse IMHO).
2862 * See #65996. */
2863 const bool is_meta_ball = (obn->type == OB_MBALL);
2864 void *obdata = obn->data;
2865 if (is_meta_ball) {
2866 obn->type = OB_EMPTY;
2867 obn->data = nullptr;
2868 }
2869
2870 /* XXX Doing that here is stupid, it means we update and re-evaluate the whole depsgraph every
2871 * time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since
2872 * we do not yet have duplicated obdata.
2873 * However, that is a safe solution for now. Proper, longer-term solution is to refactor
2874 * object_convert_exec to:
2875 * - duplicate all data it needs to in a first loop.
2876 * - do a single update.
2877 * - convert data in a second loop. */
2879 CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
2880 CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
2882 scene->customdata_mask = customdata_mask_prev;
2883
2884 if (is_meta_ball) {
2885 obn->type = OB_MBALL;
2886 obn->data = obdata;
2887 }
2888
2889 return basen;
2890}
2891
2893{
2894 Main *bmain = CTX_data_main(C);
2896 Scene *scene = CTX_data_scene(C);
2897 ViewLayer *view_layer = CTX_data_view_layer(C);
2898 Base *basen = nullptr, *basact = nullptr;
2899 Object *ob1, *obact = CTX_data_active_object(C);
2900 const short target = RNA_enum_get(op->ptr, "target");
2901 bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
2902 const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata");
2903
2904 int mballConverted = 0;
2905 bool gpencilConverted = false;
2906 bool gpencilCurveConverted = false;
2907
2908 /* don't forget multiple users! */
2909
2910 {
2911 FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
2912 ob->flag &= ~OB_DONE;
2913
2914 /* flag data that's not been edited (only needed for !keep_original) */
2915 if (ob->data) {
2916 ((ID *)ob->data)->tag |= ID_TAG_DOIT;
2917 }
2918
2919 /* possible metaball basis is not in this scene */
2920 if (ob->type == OB_MBALL && target == OB_MESH) {
2921 if (BKE_mball_is_basis(ob) == false) {
2922 Object *ob_basis;
2923 ob_basis = BKE_mball_basis_find(scene, ob);
2924 if (ob_basis) {
2925 ob_basis->flag &= ~OB_DONE;
2926 }
2927 }
2928 }
2929 }
2931 }
2932
2933 Vector<PointerRNA> selected_editable_bases;
2934 CTX_data_selected_editable_bases(C, &selected_editable_bases);
2935
2936 /* Ensure we get all meshes calculated with a sufficient data-mask,
2937 * needed since re-evaluating single modifiers causes bugs if they depend
2938 * on other objects data masks too, see: #50950. */
2939 {
2940 for (const PointerRNA &ptr : selected_editable_bases) {
2941 Base *base = static_cast<Base *>(ptr.data);
2942 Object *ob = base->object;
2943
2944 /* The way object type conversion works currently (enforcing conversion of *all* objects
2945 * using converted object-data, even some un-selected/hidden/another scene ones,
2946 * sounds totally bad to me.
2947 * However, changing this is more design than bug-fix, not to mention convoluted code below,
2948 * so that will be for later.
2949 * But at the very least, do not do that with linked IDs! */
2950 if ((!BKE_id_is_editable(bmain, &ob->id) ||
2951 (ob->data && !BKE_id_is_editable(bmain, static_cast<ID *>(ob->data)))) &&
2952 !keep_original)
2953 {
2954 keep_original = true;
2955 BKE_report(op->reports,
2956 RPT_INFO,
2957 "Converting some non-editable object/object data, enforcing 'Keep Original' "
2958 "option to True");
2959 }
2960
2962 }
2963
2964 CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
2965 CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
2967 scene->customdata_mask = customdata_mask_prev;
2968 }
2969 for (const PointerRNA &ptr : selected_editable_bases) {
2970 Object *newob = nullptr;
2971 Base *base = static_cast<Base *>(ptr.data);
2972 Object *ob = base->object;
2973
2974 if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
2975 if (ob->type != target) {
2976 base->flag &= ~SELECT;
2977 ob->flag &= ~SELECT;
2978 }
2979
2980 /* obdata already modified */
2981 if (!IS_TAGGED(ob->data)) {
2982 /* When 2 objects with linked data are selected, converting both
2983 * would keep modifiers on all but the converted object #26003. */
2984 if (ob->type == OB_MESH) {
2985 BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
2986 }
2987 if (ob->type == OB_GPENCIL_LEGACY) {
2988 BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
2990 }
2991 }
2992 }
2993 else if (ob->type == OB_MESH && target == OB_CURVES_LEGACY) {
2994 ob->flag |= OB_DONE;
2995
2996 if (keep_original) {
2997 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
2998 newob = basen->object;
2999
3000 /* Decrement original mesh's usage count. */
3001 Mesh *mesh = static_cast<Mesh *>(newob->data);
3002 id_us_min(&mesh->id);
3003
3004 /* Make a new copy of the mesh. */
3005 newob->data = BKE_id_copy(bmain, &mesh->id);
3006 }
3007 else {
3008 newob = ob;
3009 }
3010
3011 BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
3012
3013 if (newob->type == OB_CURVES_LEGACY) {
3014 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3015 if (newob->rigidbody_object != nullptr) {
3016 ED_rigidbody_object_remove(bmain, scene, newob);
3017 }
3018 }
3019 }
3020 else if (target == OB_CURVES) {
3021 ob->flag |= OB_DONE;
3022
3024 bke::GeometrySet geometry;
3025 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3026 geometry = *ob_eval->runtime->geometry_set_eval;
3027 }
3028
3029 if (geometry.has_curves()) {
3030 if (keep_original) {
3031 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3032 newob = basen->object;
3033
3034 /* Decrement original curve's usage count. */
3035 Curve *legacy_curve = static_cast<Curve *>(newob->data);
3036 id_us_min(&legacy_curve->id);
3037
3038 /* Make a copy of the curve. */
3039 newob->data = BKE_id_copy(bmain, &legacy_curve->id);
3040 }
3041 else {
3042 newob = ob;
3043 }
3044
3045 const Curves *curves_eval = geometry.get_curves();
3046 Curves *new_curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, newob->id.name + 2));
3047
3048 newob->data = new_curves;
3049 newob->type = OB_CURVES;
3050
3051 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3052 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3053
3055 BKE_object_free_modifiers(newob, 0);
3056 }
3057 else if (geometry.has_grease_pencil()) {
3058 if (keep_original) {
3059 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3060 newob = basen->object;
3061
3062 /* Decrement original curve's usage count. */
3063 Curve *legacy_curve = static_cast<Curve *>(newob->data);
3064 id_us_min(&legacy_curve->id);
3065
3066 /* Make a copy of the curve. */
3067 newob->data = BKE_id_copy(bmain, &legacy_curve->id);
3068 }
3069 else {
3070 newob = ob;
3071 }
3072
3073 Curves *new_curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, newob->id.name + 2));
3074 newob->data = new_curves;
3075 newob->type = OB_CURVES;
3076
3077 if (const Curves *curves_eval = geometry.get_curves()) {
3078 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3079 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3080 }
3081 else if (const GreasePencil *grease_pencil = geometry.get_grease_pencil()) {
3083 ed::greasepencil::retrieve_visible_drawings(*scene, *grease_pencil, false);
3084 if (drawings.size() > 0) {
3085 Array<bke::GeometrySet> geometries(drawings.size());
3086 for (const int i : drawings.index_range()) {
3087 Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
3088 curves_id->geometry.wrap() = drawings[i].drawing.strokes();
3089 geometries[i] = bke::GeometrySet::from_curves(curves_id);
3090 }
3091 bke::GeometrySet joined_curves = geometry::join_geometries(geometries, {});
3092
3093 new_curves->geometry.wrap() = joined_curves.get_curves()->geometry.wrap();
3094 new_curves->geometry.wrap().tag_topology_changed();
3095 BKE_object_material_from_eval_data(bmain, newob, &joined_curves.get_curves()->id);
3096 }
3097 }
3098
3100 BKE_object_free_modifiers(newob, 0);
3101 }
3102 else {
3103 BKE_reportf(op->reports,
3105 "Object '%s' has no evaluated grease pencil data",
3106 ob->id.name + 2);
3107 }
3108 }
3109 else if (ob->type == OB_GREASE_PENCIL && target == OB_MESH) {
3110 /* Mostly same as converting to OB_CURVES, the mesh will be converted from Curves afterwards
3111 * . */
3112
3113 ob->flag |= OB_DONE;
3114
3116 bke::GeometrySet geometry;
3117 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3118 geometry = *ob_eval->runtime->geometry_set_eval;
3119 }
3120
3121 if (geometry.has_curves()) {
3122 if (keep_original) {
3123 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3124 newob = basen->object;
3125
3126 /* Decrement original curve's usage count. */
3127 Curve *legacy_curve = static_cast<Curve *>(newob->data);
3128 id_us_min(&legacy_curve->id);
3129
3130 /* Make a copy of the curve. */
3131 newob->data = BKE_id_copy(bmain, &legacy_curve->id);
3132 }
3133 else {
3134 newob = ob;
3135 }
3136
3137 const Curves *curves_eval = geometry.get_curves();
3138 Curves *new_curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, newob->id.name + 2));
3139
3140 newob->data = new_curves;
3141 newob->type = OB_CURVES;
3142
3143 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3144 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3145
3147 BKE_object_free_modifiers(newob, 0);
3148 }
3149 else if (geometry.has_grease_pencil()) {
3150 if (keep_original) {
3151 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3152 newob = basen->object;
3153
3154 /* Decrement original curve's usage count. */
3155 Curve *legacy_curve = static_cast<Curve *>(newob->data);
3156 id_us_min(&legacy_curve->id);
3157
3158 /* Make a copy of the curve. */
3159 newob->data = BKE_id_copy(bmain, &legacy_curve->id);
3160 }
3161 else {
3162 newob = ob;
3163 }
3164
3165 /* Do not link `new_curves` to `bmain` since it's temporary. */
3166 Curves *new_curves = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, newob->id.name + 2));
3167
3168 newob->data = new_curves;
3169 newob->type = OB_CURVES;
3170
3171 if (const Curves *curves_eval = geometry.get_curves()) {
3172 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3173 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3174 }
3175 else if (const GreasePencil *grease_pencil = geometry.get_grease_pencil()) {
3177 ed::greasepencil::retrieve_visible_drawings(*scene, *grease_pencil, false);
3178 Array<bke::GeometrySet> geometries(drawings.size());
3179 for (const int i : drawings.index_range()) {
3180 Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
3181 curves_id->geometry.wrap() = drawings[i].drawing.strokes();
3182 const int layer_index = drawings[i].layer_index;
3183 const bke::greasepencil::Layer *layer = grease_pencil->layers()[layer_index];
3184 blender::float4x4 to_object = layer->to_object_space(*ob);
3185 bke::CurvesGeometry &new_curves = curves_id->geometry.wrap();
3186 MutableSpan<blender::float3> positions = new_curves.positions_for_write();
3187 for (const int point_i : new_curves.points_range()) {
3188 positions[point_i] = blender::math::transform_point(to_object, positions[point_i]);
3189 }
3190 geometries[i] = bke::GeometrySet::from_curves(curves_id);
3191 }
3192 if (geometries.size() > 0) {
3193 bke::GeometrySet joined_curves = geometry::join_geometries(geometries, {});
3194
3195 new_curves->geometry.wrap() = joined_curves.get_curves()->geometry.wrap();
3196 new_curves->geometry.wrap().tag_topology_changed();
3197 BKE_object_material_from_eval_data(bmain, newob, &joined_curves.get_curves()->id);
3198 }
3199 }
3200
3201 Mesh *new_mesh = static_cast<Mesh *>(BKE_id_new(bmain, ID_ME, newob->id.name + 2));
3202 newob->data = new_mesh;
3203 newob->type = OB_MESH;
3204
3205 Mesh *mesh = bke::curve_to_wire_mesh(new_curves->geometry.wrap(), {});
3206 if (!mesh) {
3207 mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
3208 }
3209 BKE_mesh_nomain_to_mesh(mesh, new_mesh, newob);
3210 BKE_object_material_from_eval_data(bmain, newob, &new_curves->id);
3211
3212 /* Free `new_curves` because it is just an intermediate. */
3213 BKE_id_free(nullptr, new_curves);
3214
3216 BKE_object_free_modifiers(newob, 0);
3217 }
3218 else {
3220 op->reports, RPT_WARNING, "Object '%s' has no evaluated curves data", ob->id.name + 2);
3221 }
3222 }
3223 else if (ob->type == OB_MESH && target == OB_POINTCLOUD) {
3224 ob->flag |= OB_DONE;
3225
3226 if (keep_original) {
3227 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3228 newob = basen->object;
3229
3230 /* Decrement original mesh's usage count. */
3231 Mesh *mesh = static_cast<Mesh *>(newob->data);
3232 id_us_min(&mesh->id);
3233
3234 /* Make a new copy of the mesh. */
3235 newob->data = BKE_id_copy(bmain, &mesh->id);
3236 }
3237 else {
3238 newob = ob;
3239 }
3240
3241 BKE_mesh_to_pointcloud(bmain, depsgraph, scene, newob);
3242
3243 if (newob->type == OB_POINTCLOUD) {
3244 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3245 ED_rigidbody_object_remove(bmain, scene, newob);
3246 }
3247 }
3248 else if (ob->type == OB_MESH) {
3249 ob->flag |= OB_DONE;
3250
3251 if (keep_original) {
3252 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3253 newob = basen->object;
3254
3255 /* Decrement original mesh's usage count. */
3256 Mesh *mesh = static_cast<Mesh *>(newob->data);
3257 id_us_min(&mesh->id);
3258
3259 /* Make a new copy of the mesh. */
3260 newob->data = BKE_id_copy(bmain, &mesh->id);
3261 }
3262 else {
3263 newob = ob;
3264 }
3265
3266 /* make new mesh data from the original copy */
3267 /* NOTE: get the mesh from the original, not from the copy in some
3268 * cases this doesn't give correct results (when MDEF is used for eg)
3269 */
3270 const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
3271 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
3272 Mesh *new_mesh = mesh_eval ? BKE_mesh_copy_for_eval(*mesh_eval) :
3273 BKE_mesh_new_nomain(0, 0, 0, 0);
3274 BKE_object_material_from_eval_data(bmain, newob, &new_mesh->id);
3275 /* Anonymous attributes shouldn't be available on the applied geometry. */
3276 new_mesh->attributes_for_write().remove_anonymous();
3277 if (do_merge_customdata) {
3279 }
3280
3281 Mesh *ob_data_mesh = (Mesh *)newob->data;
3282
3283 if (ob_data_mesh->key) {
3284 /* NOTE(@ideasman42): Clearing the shape-key is needed when the
3285 * number of vertices remains unchanged. Otherwise using this operator
3286 * to "Apply Visual Geometry" will evaluate using the existing shape-key
3287 * which doesn't have the "evaluated" coordinates from `new_mesh`.
3288 * See #128839 for details.
3289 *
3290 * While shape-keys could be supported, this is more of a feature to consider.
3291 * As there is already a `MESH_OT_blend_from_shape` operator,
3292 * it's not clear this is especially useful or needed. */
3293 if (!CustomData_has_layer(&new_mesh->vert_data, CD_SHAPEKEY)) {
3294 id_us_min(&ob_data_mesh->key->id);
3295 ob_data_mesh->key = nullptr;
3296 }
3297 }
3298 BKE_mesh_nomain_to_mesh(new_mesh, ob_data_mesh, newob);
3299
3300 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3301
3302 if (!keep_original) {
3304 }
3305 }
3306 else if (ob->type == OB_FONT) {
3307 ob->flag |= OB_DONE;
3308
3309 if (keep_original) {
3310 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3311 newob = basen->object;
3312
3313 /* Decrement original curve's usage count. */
3314 id_us_min(&((Curve *)newob->data)->id);
3315
3316 /* Make a new copy of the curve. */
3317 newob->data = BKE_id_copy(bmain, static_cast<ID *>(ob->data));
3318 }
3319 else {
3320 newob = ob;
3321 }
3322
3323 Curve *cu = static_cast<Curve *>(newob->data);
3324
3326 BKE_vfont_to_curve_ex(ob_eval,
3327 static_cast<Curve *>(ob_eval->data),
3328 FO_EDIT,
3329 &cu->nurb,
3330 nullptr,
3331 nullptr,
3332 nullptr,
3333 nullptr);
3334
3335 newob->type = OB_CURVES_LEGACY;
3336 cu->type = OB_CURVES_LEGACY;
3337
3338 if (cu->vfont) {
3339 id_us_min(&cu->vfont->id);
3340 cu->vfont = nullptr;
3341 }
3342 if (cu->vfontb) {
3343 id_us_min(&cu->vfontb->id);
3344 cu->vfontb = nullptr;
3345 }
3346 if (cu->vfonti) {
3347 id_us_min(&cu->vfonti->id);
3348 cu->vfonti = nullptr;
3349 }
3350 if (cu->vfontbi) {
3351 id_us_min(&cu->vfontbi->id);
3352 cu->vfontbi = nullptr;
3353 }
3354
3355 if (!keep_original) {
3356 /* other users */
3357 if (ID_REAL_USERS(&cu->id) > 1) {
3358 for (ob1 = static_cast<Object *>(bmain->objects.first); ob1;
3359 ob1 = static_cast<Object *>(ob1->id.next))
3360 {
3361 if (ob1->data == ob->data && ob1 != ob) {
3362 ob1->type = OB_CURVES_LEGACY;
3363 DEG_id_tag_update(&ob1->id,
3365 }
3366 }
3367 }
3368 }
3369
3370 LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
3371 nu->charidx = 0;
3372 }
3373
3374 cu->flag &= ~CU_3D;
3376
3377 if (target == OB_MESH) {
3378 /* No assumption should be made that the resulting objects is a mesh, as conversion can
3379 * fail. */
3381 /* Meshes doesn't use the "curve cache". */
3383 }
3384 }
3385 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
3386 ob->flag |= OB_DONE;
3387
3388 if (target == OB_MESH) {
3389 if (keep_original) {
3390 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3391 newob = basen->object;
3392
3393 /* Decrement original curve's usage count. */
3394 id_us_min(&((Curve *)newob->data)->id);
3395
3396 /* make a new copy of the curve */
3397 newob->data = BKE_id_copy(bmain, static_cast<ID *>(ob->data));
3398 }
3399 else {
3400 newob = ob;
3401 }
3402
3403 /* No assumption should be made that the resulting objects is a mesh, as conversion can
3404 * fail. */
3406 /* Meshes don't use the "curve cache". */
3408 }
3409 }
3410 else if (ob->type == OB_MBALL && target == OB_MESH) {
3411 Object *baseob;
3412
3413 base->flag &= ~BASE_SELECTED;
3414 ob->base_flag &= ~BASE_SELECTED;
3415
3416 baseob = BKE_mball_basis_find(scene, ob);
3417
3418 if (ob != baseob) {
3419 /* If mother-ball is converting it would be marked as done later. */
3420 ob->flag |= OB_DONE;
3421 }
3422
3423 if (!(baseob->flag & OB_DONE)) {
3424 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, baseob);
3425 newob = basen->object;
3426
3427 MetaBall *mb = static_cast<MetaBall *>(newob->data);
3428 id_us_min(&mb->id);
3429
3430 /* Find the evaluated mesh of the basis metaball object. */
3431 Object *object_eval = DEG_get_evaluated_object(depsgraph, baseob);
3432 Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
3433
3434 id_us_plus(&mesh->id);
3435 newob->data = mesh;
3436 newob->type = OB_MESH;
3437
3438 if (obact->type == OB_MBALL) {
3439 basact = basen;
3440 }
3441
3442 baseob->flag |= OB_DONE;
3443 mballConverted = 1;
3444 }
3445 }
3446 else if (ob->type == OB_POINTCLOUD && target == OB_MESH) {
3447 ob->flag |= OB_DONE;
3448
3449 if (keep_original) {
3450 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3451 newob = basen->object;
3452
3453 /* Decrement original point cloud's usage count. */
3454 PointCloud *pointcloud = static_cast<PointCloud *>(newob->data);
3455 id_us_min(&pointcloud->id);
3456
3457 /* Make a new copy of the point cloud. */
3458 newob->data = BKE_id_copy(bmain, &pointcloud->id);
3459 }
3460 else {
3461 newob = ob;
3462 }
3463
3464 BKE_pointcloud_to_mesh(bmain, depsgraph, scene, newob);
3465
3466 if (newob->type == OB_MESH) {
3467 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3468 ED_rigidbody_object_remove(bmain, scene, newob);
3469 }
3470 }
3471 else if (ob->type == OB_CURVES && target == OB_MESH) {
3472 ob->flag |= OB_DONE;
3473
3475 bke::GeometrySet geometry;
3476 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3477 geometry = *ob_eval->runtime->geometry_set_eval;
3478 }
3479
3480 if (keep_original) {
3481 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3482 newob = basen->object;
3483
3484 Curves *curves = static_cast<Curves *>(newob->data);
3485 id_us_min(&curves->id);
3486
3487 newob->data = BKE_id_copy(bmain, &curves->id);
3488 }
3489 else {
3490 newob = ob;
3491 }
3492
3493 Mesh *new_mesh = static_cast<Mesh *>(BKE_id_new(bmain, ID_ME, newob->id.name + 2));
3494 newob->data = new_mesh;
3495 newob->type = OB_MESH;
3496
3497 if (const Mesh *mesh_eval = geometry.get_mesh()) {
3498 BKE_mesh_nomain_to_mesh(BKE_mesh_copy_for_eval(*mesh_eval), new_mesh, newob);
3499 BKE_object_material_from_eval_data(bmain, newob, &mesh_eval->id);
3500 new_mesh->attributes_for_write().remove_anonymous();
3501 }
3502 else if (const Curves *curves_eval = geometry.get_curves()) {
3503 Mesh *mesh = bke::curve_to_wire_mesh(curves_eval->geometry.wrap(),
3505 if (!mesh) {
3506 mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
3507 }
3508 BKE_mesh_nomain_to_mesh(mesh, new_mesh, newob);
3509 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3510 }
3511 else {
3512 BKE_reportf(op->reports,
3514 "Object '%s' has no evaluated mesh or curves data",
3515 ob->id.name + 2);
3516 }
3517
3519 BKE_object_free_modifiers(newob, 0);
3520 }
3521 else if (ob->type == OB_CURVES && target == OB_GREASE_PENCIL) {
3522 ob->flag |= OB_DONE;
3523
3525 bke::GeometrySet geometry;
3526 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3527 geometry = *ob_eval->runtime->geometry_set_eval;
3528 }
3529
3530 if (keep_original) {
3531 basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, nullptr);
3532 newob = basen->object;
3533
3534 Curves *curves = static_cast<Curves *>(newob->data);
3535 id_us_min(&curves->id);
3536
3537 newob->data = BKE_id_copy(bmain, &curves->id);
3538 }
3539 else {
3540 newob = ob;
3541 }
3542
3543 GreasePencil *new_grease_pencil = static_cast<GreasePencil *>(
3544 BKE_id_new(bmain, ID_GP, newob->id.name + 2));
3545 newob->data = new_grease_pencil;
3546 newob->type = OB_GREASE_PENCIL;
3547
3548 if (const GreasePencil *grease_pencil_eval = geometry.get_grease_pencil()) {
3550 BKE_grease_pencil_copy_for_eval(grease_pencil_eval), new_grease_pencil);
3551 BKE_object_material_from_eval_data(bmain, newob, &grease_pencil_eval->id);
3552 new_grease_pencil->attributes_for_write().remove_anonymous();
3553 }
3554 else if (const Curves *curves_eval = geometry.get_curves()) {
3555 GreasePencil *grease_pencil = BKE_grease_pencil_new_nomain();
3556 /* Insert a default layer and place the drawing on frame 1. */
3557 const std::string layer_name = "Layer";
3558 const int frame_number = 1;
3559 bke::greasepencil::Layer &layer = grease_pencil->add_layer(layer_name);
3560 bke::greasepencil::Drawing *drawing = grease_pencil->insert_frame(layer, frame_number);
3561 BLI_assert(drawing != nullptr);
3562 drawing->strokes_for_write() = curves_eval->geometry.wrap();
3563
3564 BKE_grease_pencil_nomain_to_grease_pencil(grease_pencil, new_grease_pencil);
3565 BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
3566 }
3567 else {
3568 BKE_reportf(op->reports,
3570 "Object '%s' has no evaluated grease pencil or curves data",
3571 ob->id.name + 2);
3572 }
3573
3575 BKE_object_free_modifiers(newob, 0);
3576 }
3577 else {
3578 continue;
3579 }
3580
3581 /* Ensure new object has consistent material data with its new obdata. */
3582 if (newob) {
3583 BKE_object_materials_test(bmain, newob, static_cast<ID *>(newob->data));
3584 }
3585
3586 /* tag obdata if it was been changed */
3587
3588 /* If the original object is active then make this object active */
3589 if (basen) {
3590 if (ob == obact) {
3591 /* Store new active base to update view layer. */
3592 basact = basen;
3593 }
3594
3595 basen = nullptr;
3596 }
3597
3598 if (!keep_original && (ob->flag & OB_DONE)) {
3599 /* NOTE: Tag transform for update because object parenting to curve with path is handled
3600 * differently from all other cases. Converting curve to mesh and mesh to curve will likely
3601 * affect the way children are evaluated.
3602 * It is not enough to tag only geometry and rely on the curve parenting relations because
3603 * this relation is lost when curve is converted to mesh. */
3605 ((ID *)ob->data)->tag &= ~ID_TAG_DOIT; /* flag not to convert this datablock again */
3606 }
3607 }
3608
3609 if (!keep_original) {
3610 if (mballConverted) {
3611 /* We need to remove non-basis MBalls first, otherwise we won't be able to detect them if
3612 * their basis happens to be removed first. */
3613 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
3614 if (ob_mball->type == OB_MBALL) {
3615 Object *ob_basis = nullptr;
3616 if (!BKE_mball_is_basis(ob_mball) &&
3617 ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
3618 {
3619 base_free_and_unlink(bmain, scene, ob_mball);
3620 }
3621 }
3622 }
3624 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
3625 if (ob_mball->type == OB_MBALL) {
3626 if (ob_mball->flag & OB_DONE) {
3627 if (BKE_mball_is_basis(ob_mball)) {
3628 base_free_and_unlink(bmain, scene, ob_mball);
3629 }
3630 }
3631 }
3632 }
3634 }
3635 /* Remove curves and meshes converted to Grease Pencil object. */
3636 if (gpencilConverted) {
3637 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) {
3638 if (ELEM(ob_delete->type, OB_CURVES_LEGACY, OB_MESH)) {
3639 if (ob_delete->flag & OB_DONE) {
3640 base_free_and_unlink(bmain, scene, ob_delete);
3641 }
3642 }
3643 }
3645 }
3646 }
3647 else {
3648 /* Remove Text curves converted to Grease Pencil object to avoid duplicated curves. */
3649 if (gpencilCurveConverted) {
3650 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) {
3651 if (ELEM(ob_delete->type, OB_CURVES_LEGACY) && (ob_delete->flag & OB_DONE)) {
3652 base_free_and_unlink(bmain, scene, ob_delete);
3653 }
3654 }
3656 }
3657 }
3658
3659 // XXX: editmode_enter(C, 0);
3660 // XXX: exit_editmode(C, EM_FREEDATA|); /* free data, but no undo. */
3661
3662 if (basact) {
3663 /* active base was changed */
3664 base_activate(C, basact);
3665 view_layer->basact = basact;
3666 }
3667 else {
3668 BKE_view_layer_synced_ensure(scene, view_layer);
3669 Object *object = BKE_view_layer_active_object_get(view_layer);
3670 if (object->flag & OB_DONE) {
3673 }
3674 }
3675
3681
3682 return OPERATOR_FINISHED;
3683}
3684
3685static void object_convert_ui(bContext * /*C*/, wmOperator *op)
3686{
3687 uiLayout *layout = op->layout;
3688
3689 uiLayoutSetPropSep(layout, true);
3690
3691 uiItemR(layout, op->ptr, "target", UI_ITEM_NONE, nullptr, ICON_NONE);
3692 uiItemR(layout, op->ptr, "keep_original", UI_ITEM_NONE, nullptr, ICON_NONE);
3693
3694 const int target = RNA_enum_get(op->ptr, "target");
3695 if (target == OB_MESH) {
3696 uiItemR(layout, op->ptr, "merge_customdata", UI_ITEM_NONE, nullptr, ICON_NONE);
3697 }
3698 else if (target == OB_GPENCIL_LEGACY) {
3699 uiItemR(layout, op->ptr, "thickness", UI_ITEM_NONE, nullptr, ICON_NONE);
3700 uiItemR(layout, op->ptr, "angle", UI_ITEM_NONE, nullptr, ICON_NONE);
3701 uiItemR(layout, op->ptr, "offset", UI_ITEM_NONE, nullptr, ICON_NONE);
3702 uiItemR(layout, op->ptr, "seams", UI_ITEM_NONE, nullptr, ICON_NONE);
3703 uiItemR(layout, op->ptr, "faces", UI_ITEM_NONE, nullptr, ICON_NONE);
3704 }
3705}
3706
3708{
3709 PropertyRNA *prop;
3710
3711 /* identifiers */
3712 ot->name = "Convert To";
3713 ot->description = "Convert selected objects to another type";
3714 ot->idname = "OBJECT_OT_convert";
3715
3716 /* api callbacks */
3721
3722 /* flags */
3724
3725 /* properties */
3726 ot->prop = prop = RNA_def_enum(
3727 ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
3729
3730 prop = RNA_def_boolean(ot->srna,
3731 "keep_original",
3732 false,
3733 "Keep Original",
3734 "Keep original objects instead of replacing them");
3736
3738 ot->srna,
3739 "merge_customdata",
3740 true,
3741 "Merge UVs",
3742 "Merge UV coordinates that share a vertex to account for imprecision in some modifiers");
3743
3745 "angle",
3746 0,
3747 nullptr,
3748 DEG2RADF(0.0f),
3749 DEG2RADF(180.0f),
3750 "Threshold Angle",
3751 "Threshold to determine ends of the strokes",
3752 DEG2RADF(0.0f),
3753 DEG2RADF(180.0f));
3755
3756 RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100);
3757 RNA_def_boolean(ot->srna, "seams", false, "Only Seam Edges", "Convert only seam edges");
3758 RNA_def_boolean(ot->srna, "faces", true, "Export Faces", "Export faces as filled strokes");
3760 "offset",
3761 0.01f,
3762 0.0,
3764 "Stroke Offset",
3765 "Offset strokes from fill",
3766 0.0,
3767 100.00);
3768}
3769
3772/* -------------------------------------------------------------------- */
3777 Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new)
3778{
3779 if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
3780 BKE_collection_object_add_from(bmain, scene, base_src->object, object_new);
3781 }
3782 else {
3783 LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
3784 BKE_collection_object_add(bmain, layer_collection->collection, object_new);
3785 }
3786}
3787
3788static void object_add_sync_local_view(Base *base_src, Base *base_new)
3789{
3790 base_new->local_view_bits = base_src->local_view_bits;
3791}
3792
3793static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new)
3794{
3795 /* 1) duplis should end up in same collection as the original
3796 * 2) Rigid Body sim participants MUST always be part of a collection...
3797 */
3798 /* XXX: is 2) really a good measure here? */
3799 if (object_src->rigidbody_object || object_src->rigidbody_constraint) {
3800 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
3801 if (BKE_collection_has_object(collection, object_src)) {
3802 BKE_collection_object_add(bmain, collection, object_new);
3803 }
3804 }
3805 }
3806}
3807
3814 Object *ob,
3815 const eDupli_ID_Flags dupflag,
3816 const eLibIDDuplicateFlags duplicate_options,
3817 Object **r_ob_new)
3818{
3819 if (ob->mode & OB_MODE_POSE) {
3820 return;
3821 }
3822
3823 Object *obn = static_cast<Object *>(
3824 ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)));
3825 if (r_ob_new) {
3826 *r_ob_new = obn;
3827 }
3829 return;
3830}
3831
3833 Scene *scene,
3834 ViewLayer *view_layer,
3835 Object *ob,
3836 const eDupli_ID_Flags dupflag,
3837 const eLibIDDuplicateFlags duplicate_options,
3838 Object **r_ob_new)
3839{
3840 Object *object_new = nullptr;
3841 object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new);
3842 if (r_ob_new) {
3843 *r_ob_new = object_new;
3844 }
3845 if (object_new == nullptr) {
3846 return nullptr;
3847 }
3848
3849 BKE_view_layer_synced_ensure(scene, view_layer);
3850 Base *base_src = BKE_view_layer_base_find(view_layer, ob);
3851 object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new);
3852 BKE_view_layer_synced_ensure(scene, view_layer);
3853 Base *base_new = BKE_view_layer_base_find(view_layer, object_new);
3854 if (base_src && base_new) {
3855 object_add_sync_local_view(base_src, base_new);
3856 }
3857 object_add_sync_rigid_body(bmain, ob, object_new);
3858 return base_new;
3859}
3860
3862 Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag)
3863{
3864 Base *basen;
3865 Object *ob;
3866
3867 basen = object_add_duplicate_internal(bmain,
3868 scene,
3869 view_layer,
3870 base->object,
3871 dupflag,
3874 nullptr);
3875 if (basen == nullptr) {
3876 return nullptr;
3877 }
3878
3879 ob = basen->object;
3880
3881 /* Link own references to the newly duplicated data #26816.
3882 * Note that this function can be called from edit-mode code, in which case we may have to
3883 * enforce remapping obdata (by default this is forbidden in edit mode). */
3884 const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0;
3885 BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag);
3886
3887 /* Correct but the caller must do this. */
3888 // DAG_relations_tag_update(bmain);
3889
3890 if (ob->data != nullptr) {
3892 }
3893
3895
3896 return basen;
3897}
3898
3899/* contextual operator dupli */
3901{
3902 Main *bmain = CTX_data_main(C);
3903 Scene *scene = CTX_data_scene(C);
3904 ViewLayer *view_layer = CTX_data_view_layer(C);
3905 const bool linked = RNA_boolean_get(op->ptr, "linked");
3906 const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag;
3907
3908 /* We need to handle that here ourselves, because we may duplicate several objects, in which case
3909 * we also want to remap pointers between those... */
3911
3912 /* Duplicate the selected objects, remember data needed to process
3913 * after the sync. */
3914 struct DuplicateObjectLink {
3915 Base *base_src = nullptr;
3916 Object *object_new = nullptr;
3917
3918 DuplicateObjectLink(Base *base_src) : base_src(base_src) {}
3919 };
3920
3921 Vector<DuplicateObjectLink> object_base_links;
3922 CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
3923 object_base_links.append(DuplicateObjectLink(base));
3924 }
3926
3927 bool new_objects_created = false;
3928 for (DuplicateObjectLink &link : object_base_links) {
3930 link.base_src->object,
3931 dupflag,
3933 &link.object_new);
3934 if (link.object_new) {
3935 new_objects_created = true;
3936 }
3937 }
3938
3939 if (!new_objects_created) {
3940 return OPERATOR_CANCELLED;
3941 }
3942
3943 /* Sync that could tag the view_layer out of sync. */
3944 for (DuplicateObjectLink &link : object_base_links) {
3945 /* note that this is safe to do with this context iterator,
3946 * the list is made in advance */
3947 base_select(link.base_src, BA_DESELECT);
3948 if (link.object_new) {
3949 object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new);
3950 object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new);
3951 }
3952 }
3953
3954 /* Sync the view layer. Everything else should not tag the view_layer out of sync. */
3955 BKE_view_layer_synced_ensure(scene, view_layer);
3956 const Base *active_base = BKE_view_layer_active_base_get(view_layer);
3957 for (DuplicateObjectLink &link : object_base_links) {
3958 if (!link.object_new) {
3959 continue;
3960 }
3961
3962 Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new);
3963 BLI_assert(base_new);
3964 base_select(base_new, BA_SELECT);
3965 if (active_base == link.base_src) {
3966 base_activate(C, base_new);
3967 }
3968
3969 if (link.object_new->data) {
3970 DEG_id_tag_update(static_cast<ID *>(link.object_new->data), 0);
3971 }
3972
3973 object_add_sync_local_view(link.base_src, base_new);
3974 }
3975
3976 /* Note that this will also clear newid pointers and tags. */
3978
3980
3983
3986
3987 return OPERATOR_FINISHED;
3988}
3989
3991{
3992 PropertyRNA *prop;
3993
3994 /* identifiers */
3995 ot->name = "Duplicate Objects";
3996 ot->description = "Duplicate selected objects";
3997 ot->idname = "OBJECT_OT_duplicate";
3998
3999 /* api callbacks */
4002
4003 /* flags */
4005
4006 /* to give to transform */
4007 prop = RNA_def_boolean(ot->srna,
4008 "linked",
4009 false,
4010 "Linked",
4011 "Duplicate object but not object data, linking to the original data");
4013
4014 prop = RNA_def_enum(
4017}
4018
4021/* -------------------------------------------------------------------- */
4028{
4029 Main *bmain = CTX_data_main(C);
4030 Scene *scene = CTX_data_scene(C);
4031 ViewLayer *view_layer = CTX_data_view_layer(C);
4032 const bool linked = RNA_boolean_get(op->ptr, "linked");
4033 const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag;
4034
4035 /* Find object, create fake base. */
4036
4037 Object *ob = reinterpret_cast<Object *>(
4039
4040 if (ob == nullptr) {
4041 BKE_report(op->reports, RPT_ERROR, "Object not found");
4042 return OPERATOR_CANCELLED;
4043 }
4044
4045 /* prepare dupli */
4047 bmain,
4048 scene,
4049 view_layer,
4050 ob,
4051 dupflag,
4052 /* Sub-process flag because the new-ID remapping (#BKE_libblock_relink_to_newid()) in this
4053 * function will only work if the object is already linked in the view layer, which is not
4054 * the case here. So we have to do the new-ID relinking ourselves
4055 * (#copy_object_set_idnew()).
4056 */
4058 nullptr);
4059
4060 if (basen == nullptr) {
4061 BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
4062 return OPERATOR_CANCELLED;
4063 }
4064
4065 basen->object->visibility_flag &= ~OB_HIDE_VIEWPORT;
4066 /* Do immediately, as #copy_object_set_idnew() below operates on visible objects. */
4067 BKE_base_eval_flags(basen);
4068
4069 /* #object_add_duplicate_internal() doesn't deselect other objects,
4070 * unlike #object_add_common() or #BKE_view_layer_base_deselect_all(). */
4071 base_deselect_all(scene, view_layer, nullptr, SEL_DESELECT);
4072 base_select(basen, BA_SELECT);
4073 base_activate(C, basen);
4074
4076
4077 /* TODO(sergey): Only update relations for the current scene. */
4079
4085
4086 PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
4087 if (RNA_property_is_set(op->ptr, prop_matrix)) {
4088 Object *ob_add = basen->object;
4090 op->ptr, prop_matrix, ob_add->runtime->object_to_world.base_ptr());
4091 BKE_object_apply_mat4(ob_add, ob_add->object_to_world().ptr(), true, true);
4092
4094 }
4095 else if (CTX_wm_region_view3d(C)) {
4096 int mval[2];
4097 if (object_add_drop_xy_get(C, op, &mval)) {
4098 location_from_view(C, basen->object->loc);
4099 ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
4100 }
4101 }
4102
4103 return OPERATOR_FINISHED;
4104}
4105
4107{
4108 /* identifiers */
4109 ot->name = "Add Object";
4110 ot->description = "Add named object";
4111 ot->idname = "OBJECT_OT_add_named";
4112
4113 /* api callbacks */
4117
4118 /* flags */
4120
4121 PropertyRNA *prop;
4123 "linked",
4124 false,
4125 "Linked",
4126 "Duplicate object but not object data, linking to the original data");
4127
4129
4130 prop = RNA_def_float_matrix(
4131 ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
4133
4135}
4136
4139/* -------------------------------------------------------------------- */
4147{
4148 Main *bmain = CTX_data_main(C);
4149 const Scene *scene = CTX_data_scene(C);
4150 ViewLayer *view_layer = CTX_data_view_layer(C);
4151
4152 Object *ob = reinterpret_cast<Object *>(
4154
4155 if (!ob) {
4156 BKE_view_layer_synced_ensure(scene, view_layer);
4157 ob = BKE_view_layer_active_object_get(view_layer);
4158 }
4159
4160 if (ob == nullptr) {
4161 BKE_report(op->reports, RPT_ERROR, "Object not found");
4162 return OPERATOR_CANCELLED;
4163 }
4164
4165 /* Don't transform a linked object. There's just nothing to do here in this case, so return
4166 * #OPERATOR_FINISHED. */
4167 if (!BKE_id_is_editable(bmain, &ob->id)) {
4168 return OPERATOR_FINISHED;
4169 }
4170
4171 /* Ensure the locations are updated so snap reads the evaluated active location. */
4173
4174 PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
4175 if (RNA_property_is_set(op->ptr, prop_matrix)) {
4178 view_layer, nullptr, &params);
4179
4180 float matrix[4][4];
4181 RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
4182
4183 float mat_src_unit[4][4];
4184 float mat_dst_unit[4][4];
4185 float final_delta[4][4];
4186
4187 normalize_m4_m4(mat_src_unit, ob->object_to_world().ptr());
4188 normalize_m4_m4(mat_dst_unit, matrix);
4189 invert_m4(mat_src_unit);
4190 mul_m4_m4m4(final_delta, mat_dst_unit, mat_src_unit);
4191
4192 object_xform_array_m4(objects.data(), objects.size(), final_delta);
4193 }
4194 else if (CTX_wm_region_view3d(C)) {
4195 int mval[2];
4196 if (object_add_drop_xy_get(C, op, &mval)) {
4197 float cursor[3];
4198 location_from_view(C, cursor);
4199 ED_view3d_cursor3d_position(C, mval, false, cursor);
4200
4201 /* Use the active objects location since this is the ID which the user selected to drop.
4202 *
4203 * This transforms all selected objects, so that dropping a single object which links in
4204 * other objects will have their relative transformation preserved.
4205 * For example a child/parent relationship or other objects used with a boolean modifier.
4206 *
4207 * The caller is responsible for ensuring the selection state gives useful results.
4208 * Link/append does this using #FILE_AUTOSELECT. */
4210 }
4211 }
4212
4213 return OPERATOR_FINISHED;
4214}
4215
4217{
4218 /* identifiers */
4219 ot->name = "Place Object Under Mouse";
4220 ot->description = "Snap selected item(s) to the mouse location";
4221 ot->idname = "OBJECT_OT_transform_to_mouse";
4222
4223 /* api callbacks */
4227
4228 /* flags */
4230
4231 PropertyRNA *prop;
4232 prop = RNA_def_string(
4233 ot->srna,
4234 "name",
4235 nullptr,
4236 MAX_ID_NAME - 2,
4237 "Name",
4238 "Object name to place (uses the active object when this and 'session_uid' are unset)");
4240 prop = RNA_def_int(ot->srna,
4241 "session_uid",
4242 0,
4243 INT32_MIN,
4244 INT32_MAX,
4245 "Session UUID",
4246 "Session UUID of the object to place (uses the active object when this and "
4247 "'name' are unset)",
4248 INT32_MIN,
4249 INT32_MAX);
4251
4252 prop = RNA_def_float_matrix(
4253 ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
4255
4257}
4258
4261/* -------------------------------------------------------------------- */
4266{
4268
4269 if (ob == nullptr || ob->data == nullptr || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
4271 {
4272 return false;
4273 }
4274
4275 if (ELEM(ob->type,
4276 OB_MESH,
4278 OB_SURF,
4282 {
4283 return true;
4284 }
4285 return false;
4286}
4287
4289{
4290 Main *bmain = CTX_data_main(C);
4292
4293 if (ob->mode & OB_MODE_EDIT) {
4294 BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
4295 return OPERATOR_CANCELLED;
4296 }
4298 BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
4299 return OPERATOR_CANCELLED;
4300 }
4302 BKE_reportf(op->reports,
4304 "Cannot edit object '%s' as it is used by override collections",
4305 ob->id.name + 2);
4306 return OPERATOR_CANCELLED;
4307 }
4308
4309 if (ob->type == OB_GPENCIL_LEGACY) {
4310 bGPdata *gpd = (bGPdata *)ob->data;
4311 if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
4312 BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
4313 return OPERATOR_CANCELLED;
4314 }
4315 }
4316
4317 int ret = OPERATOR_CANCELLED;
4318 if (ob->type == OB_MESH) {
4320 }
4321 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
4323 }
4324 else if (ob->type == OB_ARMATURE) {
4326 }
4327 else if (ob->type == OB_GREASE_PENCIL) {
4329 }
4330
4331 if (ret & OPERATOR_FINISHED) {
4332 /* Even though internally failure to invert is accounted for with a fallback,
4333 * show a warning since the result may not be what the user expects. See #80077.
4334 *
4335 * Failure to invert the matrix is typically caused by zero scaled axes
4336 * (which can be caused by constraints, even if the input scale isn't zero).
4337 *
4338 * Internally the join functions use #invert_m4_m4_safe_ortho which creates
4339 * an inevitable matrix from one that has one or more degenerate axes.
4340 *
4341 * In most cases we don't worry about special handling for non-inevitable matrices however for
4342 * joining objects there may be flat 2D objects where it's not obvious the scale is zero.
4343 * In this case, using #invert_m4_m4_safe_ortho works as well as we can expect,
4344 * joining the contents, flattening on the axis that's zero scaled.
4345 * If the zero scale is removed, the data on this axis remains un-scaled
4346 * (something that wouldn't work for #invert_m4_m4_safe). */
4347 float imat_test[4][4];
4348 if (!invert_m4_m4(imat_test, ob->object_to_world().ptr())) {
4349 BKE_report(op->reports,
4351 "Active object final transform has one or more zero scaled axes");
4352 }
4353 }
4354
4355 return ret;
4356}
4357
4359{
4360 /* identifiers */
4361 ot->name = "Join";
4362 ot->description = "Join selected objects into active object";
4363 ot->idname = "OBJECT_OT_join";
4364
4365 /* api callbacks */
4368
4369 /* flags */
4371}
4372
4375/* -------------------------------------------------------------------- */
4380{
4382
4383 if (ob == nullptr || ob->data == nullptr || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
4385 {
4386 return false;
4387 }
4388
4389 /* only meshes supported at the moment */
4390 if (ob->type == OB_MESH) {
4391 return ED_operator_screenactive(C);
4392 }
4393 return false;
4394}
4395
4397{
4398 Main *bmain = CTX_data_main(C);
4400
4401 if (ob->mode & OB_MODE_EDIT) {
4402 BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
4403 return OPERATOR_CANCELLED;
4404 }
4406 BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
4407 return OPERATOR_CANCELLED;
4408 }
4410 BKE_reportf(op->reports,
4412 "Cannot edit object '%s' as it is used by override collections",
4413 ob->id.name + 2);
4414 return OPERATOR_CANCELLED;
4415 }
4416
4417 if (ob->type == OB_MESH) {
4419 }
4420
4421 return OPERATOR_CANCELLED;
4422}
4423
4425{
4426 /* identifiers */
4427 ot->name = "Join as Shapes";
4428 ot->description = "Copy the current resulting shape of another selected object to this one";
4429 ot->idname = "OBJECT_OT_join_shapes";
4430
4431 /* api callbacks */
4434
4435 /* flags */
4437}
4438
4441} // namespace blender::ed::object
C++ functions to deal with Armature collections (i.e. the successor of bone layers).
void ANIM_armature_bonecoll_active_set(bArmature *armature, BoneCollection *bcoll)
BoneCollection * ANIM_armature_bonecoll_new(bArmature *armature, const char *name, int parent_index=-1)
Blender kernel action and pose functionality.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:103
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:263
Camera data-block and utility functions.
#define FOREACH_SCENE_OBJECT_END
bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, bool free_us)
bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
void BKE_constraints_free(struct ListBase *list)
LayerCollection * CTX_data_layer_collection(const bContext *C)
#define CTX_DATA_BEGIN(C, Type, instance, member)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
bool CTX_data_selected_editable_bases(const bContext *C, blender::Vector< PointerRNA > *list)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
Collection * CTX_data_collection(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
#define CTX_DATA_END
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_curve_dimension_update(Curve *cu)
Definition curve.cc:437
Low-level operations for curves that cannot be defined in the C++ header yet.
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition customdata.cc:91
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
const CustomData_MeshMasks CD_MASK_MESH
display list (or rather multi purpose list) stuff.
ListBase * object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
void free_object_duplilist(ListBase *lb)
struct PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
Low-level operations for grease pencil.
void BKE_grease_pencil_nomain_to_grease_pencil(GreasePencil *grease_pencil_src, GreasePencil *grease_pencil_dst)
GreasePencil * BKE_grease_pencil_new_nomain()
GreasePencil * BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src)
LayerCollection * BKE_layer_collection_get_active(ViewLayer *view_layer)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
blender::Vector< Object * > BKE_view_layer_array_selected_objects_params(ViewLayer *view_layer, const View3D *v3d, const ObjectsInViewLayerParams *params)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
LayerCollection * BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc)
void BKE_base_eval_flags(Base *base)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
void size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL()
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:351
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1947
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:765
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
#define IS_TAGGED(_id)
void id_us_min(ID *id)
Definition lib_id.cc:359
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1175
eLibIDDuplicateFlags
@ LIB_ID_DUPLICATE_IS_ROOT_ID
@ LIB_ID_DUPLICATE_IS_SUBPROCESS
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1487
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1198
bool BKE_lib_override_library_id_is_user_deletable(Main *bmain, ID *id)
bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
Definition lib_query.cc:613
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:921
General operations, lookup, etc. for blender lights.
General operations for probes.
void BKE_lightprobe_type_set(struct LightProbe *probe, short lightprobe_type)
Definition lightprobe.cc:83
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:500
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:494
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
void BKE_object_materials_test(struct Main *bmain, struct Object *ob, struct ID *id)
void BKE_object_material_from_eval_data(struct Main *bmain, struct Object *ob_orig, const struct ID *data_eval)
short * BKE_id_material_len_p(struct ID *id)
bool BKE_mball_is_basis(const Object *ob)
Definition mball.cc:230
Object * BKE_mball_basis_find(Scene *scene, Object *ob)
Definition mball.cc:394
void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *mesh)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
Mesh * BKE_mesh_new_from_object_to_bmain(Main *bmain, Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
ModifierData * BKE_modifier_new(int type)
bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, bool is_liboverride)
void BKE_nlatrack_set_active(ListBase *tracks, NlaTrack *nlt)
NlaTrack * BKE_nlatrack_new_tail(ListBase *nla_tracks, const bool is_liboverride)
NlaStrip * BKE_nla_add_soundstrip(Main *bmain, Scene *scene, Speaker *speaker)
void BKE_nlastrip_validate_name(AnimData *adt, NlaStrip *strip)
General operations, lookup, etc. for blender objects.
void BKE_object_empty_draw_type_set(Object *ob, int value)
bool BKE_object_is_in_editmode(const Object *ob)
Object * BKE_object_add_for_data(Main *bmain, const Scene *scene, ViewLayer *view_layer, int type, const char *name, ID *data, bool do_id_user) ATTR_RETURNS_NONNULL
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) ATTR_NONNULL(1
bool BKE_object_obdata_is_libdata(const Object *ob)
void BKE_object_free_curve_cache(Object *ob)
void BKE_object_free_modifiers(Object *ob, int flag)
void BKE_object_obdata_size_init(Object *ob, float size)
Object * BKE_object_duplicate(Main *bmain, Object *ob, eDupli_ID_Flags dupflag, uint duplicate_options)
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
int BKE_object_obdata_to_type(const ID *id) ATTR_NONNULL(1)
void BKE_object_free_shaderfx(Object *ob, int flag)
void BKE_object_free_derived_caches(Object *ob)
General operations for point clouds.
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2568
void BKE_scene_object_base_flag_sync_from_base(Base *base)
Definition scene.cc:2820
General operations for speakers.
@ FO_EDIT
Definition BKE_vfont.hh:69
bool BKE_vfont_to_curve_ex(Object *ob, Curve *cu, eEditFontMode mode, ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, CharTrans **r_chartransdata)
Definition vfont.cc:1983
Volume data-block.
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int BLI_ghashutil_ptrhash(const void *key)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:752
#define BLI_ghashutil_inthash(key)
Definition BLI_ghash.h:580
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
#define M_PI_2
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mul_mat3_m4_fl(float R[4][4], float f)
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void normalize_m4_m4(float rmat[4][4], const float mat[4][4]) ATTR_NONNULL()
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void rescale_m4(float mat[4][4], const float scale[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3])
bool invert_m4(float mat[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
bool invert_m3(float mat[3][3])
void eul_to_mat3(float mat[3][3], const float eul[3])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
#define DEG2RADF(_deg)
void quat_to_eul(float eul[3], const float quat[4])
void mat3_normalized_to_eul(float eul[3], const float mat[3][3])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void copy_qt_qt(float q[4], const float a[4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STRNCPY_UTF8(dst, src)
unsigned short ushort
unsigned int uint
#define UNPACK3(a)
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_ID
#define BLT_I18NCONTEXT_ID_GPENCIL
#define BLT_I18NCONTEXT_ID_LIGHT
#define BLT_I18NCONTEXT_ID_OBJECT
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define CTX_DATA_(context, msgid)
#define IFACE_(msgid)
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_type_tag(Main *bmain, short id_type)
void DEG_id_tag_update_ex(Main *bmain, ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
void DEG_graph_tag_relations_update(Depsgraph *graph)
Object * DEG_get_original_object(Object *object)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
#define ID_EXTRA_USERS(id)
Definition DNA_ID.h:623
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SELECT
Definition DNA_ID.h:1068
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_EDITORS
Definition DNA_ID.h:1078
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1044
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1071
#define MAX_ID_NAME
Definition DNA_ID.h:377
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ ID_TAG_NEW
Definition DNA_ID.h:865
@ ID_TAG_INDIRECT
Definition DNA_ID.h:794
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
#define ID_NEW_SET(_id, _idn)
Definition DNA_ID.h:707
ID_Type
@ ID_IM
@ ID_CV
@ ID_ME
@ ID_GR
@ ID_OB
@ ID_GP
Object groups, one object can be in many groups at once.
@ CU_NURBS
@ CU_PRIM_PATH
@ CU_3D
@ CU_PATH
@ CD_PROP_FLOAT2
#define GPENCIL_ANY_MODE(gpd)
@ GREASE_PENCIL_STROKE_ORDER_3D
@ BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT
@ LA_AREA
@ LA_LOCAL
@ LA_SPOT
@ LA_SUN
@ LIGHTPROBE_TYPE_PLANE
@ LIGHTPROBE_TYPE_VOLUME
@ LIGHTPROBE_TYPE_SPHERE
@ LINEART_SOURCE_SCENE
@ LINEART_SOURCE_OBJECT
@ LINEART_SOURCE_COLLECTION
@ eModifierType_GreasePencilLineart
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ NUM_PFIELD_TYPES
@ PFIELD_FLUIDFLOW
@ PFIELD_HARMONIC
@ PFIELD_TURBULENCE
@ PFIELD_LENNARDJ
Object is a sort of wrapper for general info.
#define MAX_DUPLI_RECUR
@ OB_MODIFIER_FLAG_ADD_REST_POSITION
@ OB_DONE
@ PAROBJECT
@ GREASE_PENCIL_LINEART_SCENE
@ GP_STROKE
@ GREASE_PENCIL_LINEART_COLLECTION
@ GREASE_PENCIL_LINEART_OBJECT
@ GP_MONKEY
@ GP_EMPTY
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
@ OB_EMPTY_IMAGE_DEPTH_BACK
@ OB_DRAWBOUNDOX
@ OB_USE_GPENCIL_LIGHTS
@ OB_DRAW_IN_FRONT
@ OB_DUPLI
@ OB_DUPLICOLLECTION
@ OB_SINGLE_ARROW
@ OB_EMPTY_IMAGE
@ OB_EMPTY_IMAGE_HIDE_BACK
@ OB_EMPTY_IMAGE_HIDE_PERSPECTIVE
#define BASE_SELECTED(v3d, base)
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_MOVIE
@ FILE_TYPE_FOLDER
@ FILE_TYPE_IMAGE
@ FILE_DEFAULTDISPLAY
eDupli_ID_Flags
@ USER_ADD_VIEWALIGNED
@ USER_ADD_CURSORALIGNED
@ USER_ADD_EDITMODE
@ V3D_AROUND_ACTIVE
@ RV3D_PERSP
@ OPERATOR_RUNNING_MODAL
MetaElem * ED_mball_add_primitive(bContext *C, Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type)
int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
Definition meshtools.cc:731
int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
Definition meshtools.cc:318
#define OBJECT_ADD_SIZE_MAXF
Definition ED_object.hh:295
void ED_outliner_select_sync_from_object_tag(bContext *C)
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
bool ED_operator_screenactive(bContext *C)
bool ED_operator_objectmode(bContext *C)
bool ED_operator_scene_editable(bContext *C)
bool ED_operator_objectmode_poll_msg(bContext *C)
@ SEL_DESELECT
@ TFM_TRANSLATION
float ED_view3d_grid_scale(const Scene *scene, const View3D *v3d, const char **r_grid_unit)
Object * ED_view3d_give_object_under_cursor(bContext *C, const int mval[2])
bool ED_view3d_snap_selected_to_location(bContext *C, wmOperator *op, const float snap_target_global[3], int pivot_point)
void ED_view3d_cursor3d_position(bContext *C, const int mval[2], bool use_depth, float r_cursor_co[3])
float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit)
Read Guarded memory(de)allocation.
const EnumPropertyItem * RNA_collection_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
PropertyFlag
Definition RNA_types.hh:201
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:321
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_SKIP_PRESET
Definition RNA_types.hh:343
@ PROP_HIDDEN
Definition RNA_types.hh:239
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ ALERT_ICON_NONE
@ WM_FILESEL_RELPATH
Definition WM_api.hh:933
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DRAW
Definition WM_types.hh:428
#define ND_OB_ACTIVE
Definition WM_types.hh:407
#define ND_DATA
Definition WM_types.hh:475
#define NC_ANIMATION
Definition WM_types.hh:355
#define ND_OB_SELECT
Definition WM_types.hh:409
#define NC_SCENE
Definition WM_types.hh:345
#define NA_ADDED
Definition WM_types.hh:552
#define ND_LAYER_CONTENT
Definition WM_types.hh:420
#define ND_MODIFIER
Definition WM_types.hh:429
#define ND_PARENT
Definition WM_types.hh:434
#define ND_NLA
Definition WM_types.hh:464
#define NC_OBJECT
Definition WM_types.hh:346
EditBone * ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
unsigned int U
Definition btGjkEpa3.h:78
int64_t size() const
void append(const T &value)
IndexRange index_range() const
MutableSpan< float3 > positions_for_write()
IndexRange points_range() const
bke::CurvesGeometry & strokes_for_write()
local_group_size(16, 16) .push_constant(Type b
#define printf
const Depsgraph * depsgraph
int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
static int duplicate_exec(bContext *C, wmOperator *op)
Nurb * ED_curve_add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
draw_view in_light_buf[] float
#define rot(x, k)
int ED_grease_pencil_join_objects_exec(bContext *C, wmOperator *op)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition iris.cc:202
bool object_has_geometry_set_instances(const Object &object)
bke::CurvesGeometry primitive_random_sphere(const int curves_size, const int points_per_curve)
void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob)
Definition curves_add.cc:61
void create_suzanne(Main &bmain, Object &object, const float4x4 &matrix, const int frame_number)
void create_blank(Main &bmain, Object &object, const int frame_number)
void create_stroke(Main &bmain, Object &object, const float4x4 &matrix, const int frame_number)
static uint dupliobject_instancer_hash(const void *ptr)
void OBJECT_OT_metaball_add(wmOperatorType *ot)
static int object_join_exec(bContext *C, wmOperator *op)
static int object_delete_exec(bContext *C, wmOperator *op)
void add_unit_props_radius(wmOperatorType *ot)
static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
Object * add_type(bContext *C, int type, const char *name, const float loc[3], const float rot[3], bool enter_editmode, unsigned short local_view_bits) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL
void OBJECT_OT_curves_empty_hair_add(wmOperatorType *ot)
static Base * duplibase_for_convert(Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
static void object_add_duplicate_internal(Main *bmain, Object *ob, const eDupli_ID_Flags dupflag, const eLibIDDuplicateFlags duplicate_options, Object **r_ob_new)
void OBJECT_OT_text_add(wmOperatorType *ot)
static int effector_add_exec(bContext *C, wmOperator *op)
Object * add_type_with_obdata(bContext *C, int type, const char *name, const float loc[3], const float rot[3], bool enter_editmode, ushort local_view_bits, ID *obdata)
static const char * get_light_defname(int type)
static int lightprobe_add_exec(bContext *C, wmOperator *op)
static void object_add_drop_xy_props(wmOperatorType *ot)
void object_xform_array_m4(Object **objects, uint objects_len, const float matrix[4][4])
static int collection_drop_exec(bContext *C, wmOperator *op)
void OBJECT_OT_delete(wmOperatorType *ot)
static bool object_convert_poll(bContext *C)
void OBJECT_OT_transform_to_mouse(wmOperatorType *ot)
static bool object_join_poll(bContext *C)
void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
void add_unit_props_size(wmOperatorType *ot)
static const char * get_effector_defname(ePFieldType type)
static const EnumPropertyItem align_options[]
static EnumPropertyItem rna_enum_gpencil_add_stroke_depth_order_items[]
float new_primitive_matrix(bContext *C, Object *obedit, const float loc[3], const float rot[3], const float scale[3], float primmat[4][4])
static int object_data_instance_add_exec(bContext *C, wmOperator *op)
static int object_light_add_exec(bContext *C, wmOperator *op)
void rotation_from_view(bContext *C, float rot[3], char align_axis)
static int object_grease_pencil_add_exec(bContext *C, wmOperator *op)
void base_activate(bContext *C, Base *base)
static int join_shapes_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem field_type_items[]
void OBJECT_OT_collection_external_asset_drop(wmOperatorType *ot)
void OBJECT_OT_data_instance_add(wmOperatorType *ot)
void OBJECT_OT_armature_add(wmOperatorType *ot)
void OBJECT_OT_speaker_add(wmOperatorType *ot)
static void object_add_sync_base_collection(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new)
static int collection_instance_add_exec(bContext *C, wmOperator *op)
static int object_curves_random_add_exec(bContext *C, wmOperator *op)
static int object_pointcloud_add_exec(bContext *C, wmOperator *op)
static void object_add_sync_local_view(Base *base_src, Base *base_new)
static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
void base_select(Base *base, eObjectSelect_Mode mode)
static bool dupliobject_cmp(const void *a_, const void *b_)
void base_free_and_unlink_no_indirect_check(Main *bmain, Scene *scene, Object *ob)
static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new)
void add_unit_props_radius_ex(wmOperatorType *ot, float default_value)
void rotation_from_quat(float rot[3], const float quat[4], char align_axis)
static bool object_curves_empty_hair_add_poll(bContext *C)
static void object_convert_ui(bContext *, wmOperator *op)
static void view_align_update(Main *, Scene *, PointerRNA *ptr)
static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem * convert_target_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
static const char * get_lightprobe_defname(int type)
void OBJECT_OT_join_shapes(wmOperatorType *ot)
void OBJECT_OT_grease_pencil_add(wmOperatorType *ot)
static bool join_shapes_poll(bContext *C)
void OBJECT_OT_convert(wmOperatorType *ot)
bool parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *const ob, Object *const par, int partype, bool xmirror, bool keep_transform, const int vert_par[3])
static int object_add_text_exec(bContext *C, wmOperator *op)
bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
static void copy_object_set_idnew(bContext *C)
static int object_speaker_add_exec(bContext *C, wmOperator *op)
static bool object_pointcloud_add_poll(bContext *C)
void OBJECT_OT_effector_add(wmOperatorType *ot)
void OBJECT_OT_add_named(wmOperatorType *ot)
Base * add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, eDupli_ID_Flags dupflag)
void OBJECT_OT_light_add(wmOperatorType *ot)
static EnumPropertyItem lightprobe_type_items[]
static int object_add_exec(bContext *C, wmOperator *op)
static int object_transform_to_mouse_exec(bContext *C, wmOperator *op)
void OBJECT_OT_empty_image_add(wmOperatorType *ot)
static bool object_image_add_poll(bContext *C)
static int object_delete_invoke(bContext *C, wmOperator *op, const wmEvent *)
static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int(*r_mval)[2])
void OBJECT_OT_empty_add(wmOperatorType *ot)
static int object_convert_exec(bContext *C, wmOperator *op)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
static const EnumPropertyItem convert_target_items[]
static int object_instance_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
static int object_image_add_exec(bContext *C, wmOperator *op)
bool base_deselect_all(const Scene *scene, ViewLayer *view_layer, View3D *v3d, int action)
void init_transform_on_add(Object *object, const float loc[3], const float rot[3])
void OBJECT_OT_add(wmOperatorType *ot)
void add_generic_props(wmOperatorType *ot, bool do_editmode)
static int object_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static uint dupliobject_hash(const void *ptr)
static int object_armature_add_exec(bContext *C, wmOperator *op)
void OBJECT_OT_curves_random_add(wmOperatorType *ot)
void location_from_view(bContext *C, float loc[3])
void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
static void make_object_duplilist_real(bContext *C, Depsgraph *depsgraph, Scene *scene, Base *base, const bool use_base_parent, const bool use_hierarchy)
static bool object_add_drop_xy_is_set(const wmOperator *op)
void add_mesh_props(wmOperatorType *ot)
void OBJECT_OT_duplicate(wmOperatorType *ot)
void OBJECT_OT_join(wmOperatorType *ot)
void add_generic_get_opts(bContext *C, wmOperator *op, char view_align_axis, float r_loc[3], float r_rot[3], float r_scale[3], bool *r_enter_editmode, unsigned short *r_local_view_bits, bool *r_is_view_aligned)
bool editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
void OBJECT_OT_camera_add(wmOperatorType *ot)
static int object_camera_add_exec(bContext *C, wmOperator *op)
static int object_metaball_add_exec(bContext *C, wmOperator *op)
static std::optional< CollectionAddInfo > collection_add_info_get_from_op(bContext *C, wmOperator *op)
static int object_empty_add_exec(bContext *C, wmOperator *op)
static int object_add_named_exec(bContext *C, wmOperator *op)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
#define hash
Definition noise.c:154
const EnumPropertyItem rna_enum_light_type_items[]
return ret
const EnumPropertyItem rna_enum_id_type_items[]
Definition rna_ID.cc:35
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_property_float_default(PropertyRNA *prop, float value)
PropertyRNA * RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, const int rows, const int columns, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_update_runtime(PropertyRNA *prop, RNAPropertyUpdateFunc func)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item, int value)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_object_empty_drawtype_items[]
const EnumPropertyItem rna_enum_metaelem_type_items[]
const EnumPropertyItem rna_enum_object_gpencil_type_items[]
const EnumPropertyItem rna_enum_object_type_items[]
const EnumPropertyItem rna_enum_dummy_NULL_items[]
Definition rna_rna.cc:29
#define FLT_MAX
Definition stdcycles.h:14
#define INT32_MAX
Definition stdint.h:137
#define INT32_MIN
Definition stdint.h:136
ListBase nla_tracks
short flag
struct Object * object
unsigned short local_view_bits
float drawsize
struct VFont * vfont
struct VFont * vfontb
EditNurb * editnurb
struct VFont * vfonti
ListBase nurb
struct VFont * vfontbi
CurvesGeometry geometry
struct Object * surface
char * surface_uv_map
int persistent_id[8]
ListBase nurbs
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
struct Collection * collection
float energy
short type
void * first
ListBase scenes
Definition BKE_main.hh:210
ListBase collections
Definition BKE_main.hh:231
ListBase gpencils
Definition BKE_main.hh:240
ListBase objects
Definition BKE_main.hh:212
CustomData corner_data
CustomData vert_data
struct Key * key
char name[64]
short transflag
ListBase constraints
struct Collection * instance_collection
short base_flag
ObjectRuntimeHandle * runtime
struct RigidBodyOb * rigidbody_object
struct Material ** mat
float loc[3]
struct PartDeflect * pd
float scale[3]
float parentinv[4][4]
char empty_drawtype
short visibility_flag
uint8_t modifier_flag
float empty_drawsize
struct AnimData * adt
char empty_image_depth
struct Object * parent
struct RigidBodyCon * rigidbody_constraint
char parsubstr[64]
char empty_image_visibility_flag
void * data
Definition RNA_types.hh:42
struct Object * camera
struct View3D * localvd
short scenelock
unsigned short local_view_uid
struct Base * basact
const c_style_mat & ptr() const
const Curves * get_curves() const
int xy[2]
Definition WM_types.hh:726
int mval[2]
Definition WM_types.hh:728
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
const EnumPropertyItem rna_enum_transform_mode_type_items[]
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operator_properties_confirm_or_exec(wmOperatorType *ot)
bool WM_operator_properties_id_lookup_is_set(PointerRNA *ptr)
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
void WM_operator_properties_id_lookup(wmOperatorType *ot, const bool add_name_prop)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
int WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
void WM_operator_view3d_unit_defaults(bContext *C, wmOperator *op)
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
ID * WM_operator_drop_load_path(bContext *C, wmOperator *op, const short idcode)
Scene * WM_window_get_active_scene(const wmWindow *win)