Blender V5.0
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
8
9#include <cctype>
10#include <cstdlib>
11#include <cstring>
12#include <optional>
13
14#include "DNA_anim_types.h"
15#include "DNA_camera_types.h"
17#include "DNA_curve_types.h"
19#include "DNA_key_types.h"
20#include "DNA_light_types.h"
22#include "DNA_material_types.h"
23#include "DNA_mesh_types.h"
24#include "DNA_meta_types.h"
25#include "DNA_modifier_types.h"
27#include "DNA_object_types.h"
29#include "DNA_scene_types.h"
30#include "DNA_vfont_types.h"
31
32#include "BLI_array_utils.hh"
33#include "BLI_bounds.hh"
34#include "BLI_ghash.h"
35#include "BLI_listbase.h"
36#include "BLI_math_color.h"
37#include "BLI_math_matrix.h"
39#include "BLI_math_rotation.h"
41#include "BLI_rand.hh"
42#include "BLI_string.h"
43#include "BLI_string_utf8.h"
44#include "BLI_utildefines.h"
45#include "BLI_vector.hh"
46
47#include "BLT_translation.hh"
48
49#include "BKE_action.hh"
50#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"
59#include "BKE_curve_to_mesh.hh"
60#include "BKE_curves.h"
61#include "BKE_curves.hh"
62#include "BKE_customdata.hh"
63#include "BKE_deform.hh"
64#include "BKE_displist.h"
65#include "BKE_duplilist.hh"
66#include "BKE_effect.h"
67#include "BKE_geometry_set.hh"
69#include "BKE_grease_pencil.hh"
70#include "BKE_key.hh"
71#include "BKE_lattice.hh"
72#include "BKE_layer.hh"
73#include "BKE_lib_id.hh"
74#include "BKE_lib_override.hh"
75#include "BKE_lib_query.hh"
76#include "BKE_lib_remap.hh"
77#include "BKE_library.hh"
78#include "BKE_light.h"
79#include "BKE_lightprobe.h"
80#include "BKE_main.hh"
81#include "BKE_material.hh"
82#include "BKE_mball.hh"
83#include "BKE_mesh.hh"
84#include "BKE_mesh_runtime.hh"
85#include "BKE_modifier.hh"
86#include "BKE_nla.hh"
87#include "BKE_node.hh"
88#include "BKE_object.hh"
89#include "BKE_object_types.hh"
90#include "BKE_particle.h"
91#include "BKE_pointcloud.hh"
92#include "BKE_report.hh"
93#include "BKE_scene.hh"
94#include "BKE_speaker.h"
95#include "BKE_vfont.hh"
96#include "BKE_volume.hh"
97
98#include "DEG_depsgraph.hh"
100#include "DEG_depsgraph_query.hh"
101
102#include "GEO_join_geometries.hh"
103#include "GEO_mesh_to_curve.hh"
104
105#include "RNA_access.hh"
106#include "RNA_define.hh"
107#include "RNA_enum_types.hh"
108
109#include "UI_interface_layout.hh"
110
111#include "WM_api.hh"
112#include "WM_types.hh"
113
114#include "ED_armature.hh"
115#include "ED_curve.hh"
116#include "ED_curves.hh"
117#include "ED_gpencil_legacy.hh"
118#include "ED_grease_pencil.hh"
119#include "ED_mball.hh"
120#include "ED_mesh.hh"
121#include "ED_node.hh"
122#include "ED_object.hh"
123#include "ED_outliner.hh"
124#include "ED_physics.hh"
125#include "ED_pointcloud.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/* -------------------------------------------------------------------- */
151
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
207
208/* -------------------------------------------------------------------- */
211
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 wmOperator *op,
273 const wmEvent *event)
274{
275 if (!object_add_drop_xy_is_set(op)) {
276 RNA_int_set(op->ptr, "drop_x", event->xy[0]);
277 RNA_int_set(op->ptr, "drop_y", event->xy[1]);
278 }
279 return op->type->exec(C, op);
280}
281
283
284/* -------------------------------------------------------------------- */
287
288void location_from_view(bContext *C, float loc[3])
289{
290 const Scene *scene = CTX_data_scene(C);
291 copy_v3_v3(loc, scene->cursor.location);
292}
293
294void rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
295{
296 BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
297
298 switch (align_axis) {
299 case 'X': {
300 /* Same as 'rv3d->viewinv[1]' */
301 const float axis_y[4] = {0.0f, 1.0f, 0.0f};
302 float quat_y[4], quat[4];
303 axis_angle_to_quat(quat_y, axis_y, M_PI_2);
304 mul_qt_qtqt(quat, viewquat, quat_y);
305 quat_to_eul(rot, quat);
306 break;
307 }
308 case 'Y': {
309 quat_to_eul(rot, viewquat);
310 rot[0] -= float(M_PI_2);
311 break;
312 }
313 case 'Z': {
314 quat_to_eul(rot, viewquat);
315 break;
316 }
317 }
318}
319
320void rotation_from_view(bContext *C, float rot[3], const char align_axis)
321{
323 BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
324 if (rv3d) {
325 float viewquat[4];
326 copy_qt_qt(viewquat, rv3d->viewquat);
327 viewquat[0] *= -1.0f;
328 rotation_from_quat(rot, viewquat, align_axis);
329 }
330 else {
331 zero_v3(rot);
332 }
333}
334
335void init_transform_on_add(Object *object, const float loc[3], const float rot[3])
336{
337 if (loc) {
338 copy_v3_v3(object->loc, loc);
339 }
340
341 if (rot) {
342 copy_v3_v3(object->rot, rot);
343 }
344
345 BKE_object_to_mat4(object, object->runtime->object_to_world.ptr());
346}
347
349 Object *obedit,
350 const float loc[3],
351 const float rot[3],
352 const float scale[3],
353 float r_primmat[4][4])
354{
355 Scene *scene = CTX_data_scene(C);
356 View3D *v3d = CTX_wm_view3d(C);
357 float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
358
359 unit_m4(r_primmat);
360
361 eul_to_mat3(rmat, rot);
362 invert_m3(rmat);
363
364 /* inverse transform for initial rotation and object */
365 copy_m3_m4(mat, obedit->object_to_world().ptr());
366 mul_m3_m3m3(cmat, rmat, mat);
367 invert_m3_m3(imat, cmat);
368 copy_m4_m3(r_primmat, imat);
369
370 /* center */
371 copy_v3_v3(r_primmat[3], loc);
372 sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world().location());
373 invert_m3_m3(imat, mat);
374 mul_m3_v3(imat, r_primmat[3]);
375
376 if (scale != nullptr) {
377 rescale_m4(r_primmat, scale);
378 }
379
380 {
381 const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
382 ED_scene_grid_scale(scene, nullptr);
383 return dia;
384 }
385
386 // return 1.0f;
387}
388
390
391/* -------------------------------------------------------------------- */
394
395static void view_align_update(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
396{
398}
399
401{
403 ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
404}
405
406void add_unit_props_radius_ex(wmOperatorType *ot, float default_value)
407{
409 ot->srna, "radius", default_value, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
410}
411
416
417void add_generic_props(wmOperatorType *ot, bool do_editmode)
418{
419 PropertyRNA *prop;
420
421 if (do_editmode) {
422 prop = RNA_def_boolean(ot->srna,
423 "enter_editmode",
424 false,
425 "Enter Edit Mode",
426 "Enter edit mode when adding this object");
428 }
429 /* NOTE: this property gets hidden for add-camera operator. */
430 prop = RNA_def_enum(
431 ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
433
434 prop = RNA_def_float_vector_xyz(ot->srna,
435 "location",
436 3,
437 nullptr,
440 "Location",
441 "Location for the newly added object",
442 -1000.0f,
443 1000.0f);
445 prop = RNA_def_float_rotation(ot->srna,
446 "rotation",
447 3,
448 nullptr,
451 "Rotation",
452 "Rotation for the newly added object",
453 DEG2RADF(-360.0f),
454 DEG2RADF(360.0f));
456
457 prop = RNA_def_float_vector_xyz(ot->srna,
458 "scale",
459 3,
460 nullptr,
463 "Scale",
464 "Scale for the newly added object",
465 -1000.0f,
466 1000.0f);
468}
469
471{
472 RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
473}
474
476 wmOperator *op,
477 const char view_align_axis,
478 float r_loc[3],
479 float r_rot[3],
480 float r_scale[3],
481 bool *r_enter_editmode,
482 ushort *r_local_view_bits,
483 bool *r_is_view_aligned)
484{
485 /* Edit Mode! (optional) */
486 {
487 bool _enter_editmode;
488 if (!r_enter_editmode) {
489 r_enter_editmode = &_enter_editmode;
490 }
491 /* Only to ensure the value is _always_ set.
492 * Typically the property will exist when the argument is non-null. */
493 *r_enter_editmode = false;
494
495 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "enter_editmode");
496 if (prop != nullptr) {
497 if (RNA_property_is_set(op->ptr, prop) && r_enter_editmode) {
498 *r_enter_editmode = RNA_property_boolean_get(op->ptr, prop);
499 }
500 else {
501 *r_enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
502 RNA_property_boolean_set(op->ptr, prop, *r_enter_editmode);
503 }
504 }
505 }
506
507 if (r_local_view_bits) {
508 View3D *v3d = CTX_wm_view3d(C);
509 *r_local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uid : 0;
510 }
511
512 /* Location! */
513 {
514 float _loc[3];
515 if (!r_loc) {
516 r_loc = _loc;
517 }
518
519 if (RNA_struct_property_is_set(op->ptr, "location")) {
520 RNA_float_get_array(op->ptr, "location", r_loc);
521 }
522 else {
523 location_from_view(C, r_loc);
524 RNA_float_set_array(op->ptr, "location", r_loc);
525 }
526 }
527
528 /* Rotation! */
529 {
530 bool _is_view_aligned;
531 float _rot[3];
532 if (!r_is_view_aligned) {
533 r_is_view_aligned = &_is_view_aligned;
534 }
535 if (!r_rot) {
536 r_rot = _rot;
537 }
538
539 if (RNA_struct_property_is_set(op->ptr, "rotation")) {
540 /* If rotation is set, always use it. Alignment (and corresponding user preference)
541 * can be ignored since this is in world space anyways.
542 * To not confuse (e.g. on redo), don't set it to #ALIGN_WORLD in the op UI though. */
543 *r_is_view_aligned = false;
544 RNA_float_get_array(op->ptr, "rotation", r_rot);
545 }
546 else {
547 int alignment = ALIGN_WORLD;
548 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "align");
549
550 if (RNA_property_is_set(op->ptr, prop)) {
551 /* If alignment is set, always use it. */
552 *r_is_view_aligned = alignment == ALIGN_VIEW;
553 alignment = RNA_property_enum_get(op->ptr, prop);
554 }
555 else {
556 /* If alignment is not set, use User Preferences. */
557 *r_is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
558 if (*r_is_view_aligned) {
560 alignment = ALIGN_VIEW;
561 }
562 else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) {
564 alignment = ALIGN_CURSOR;
565 }
566 else {
568 alignment = ALIGN_WORLD;
569 }
570 }
571 switch (alignment) {
572 case ALIGN_WORLD:
573 RNA_float_get_array(op->ptr, "rotation", r_rot);
574 break;
575 case ALIGN_VIEW:
576 rotation_from_view(C, r_rot, view_align_axis);
577 RNA_float_set_array(op->ptr, "rotation", r_rot);
578 break;
579 case ALIGN_CURSOR: {
580 const Scene *scene = CTX_data_scene(C);
581 const float3x3 tmat = scene->cursor.matrix<float3x3>();
582 mat3_normalized_to_eul(r_rot, tmat.ptr());
583 RNA_float_set_array(op->ptr, "rotation", r_rot);
584 break;
585 }
586 }
587 }
588 }
589
590 /* Scale! */
591 {
592 float _scale[3];
593 if (!r_scale) {
594 r_scale = _scale;
595 }
596
597 /* For now this is optional, we can make it always use. */
598 copy_v3_fl(r_scale, 1.0f);
599
600 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "scale");
601 if (prop != nullptr) {
602 if (RNA_property_is_set(op->ptr, prop)) {
603 RNA_property_float_get_array(op->ptr, prop, r_scale);
604 }
605 else {
606 copy_v3_fl(r_scale, 1.0f);
607 RNA_property_float_set_array(op->ptr, prop, r_scale);
608 }
609 }
610 }
611}
612
614 const int type,
615 const char *name,
616 const float loc[3],
617 const float rot[3],
618 const bool enter_editmode,
619 const ushort local_view_bits,
620 ID *obdata)
621{
622 Main *bmain = CTX_data_main(C);
623 Scene *scene = CTX_data_scene(C);
624 ViewLayer *view_layer = CTX_data_view_layer(C);
625
626 {
627 BKE_view_layer_synced_ensure(scene, view_layer);
628 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
629 if (obedit != nullptr) {
630 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
631 }
632 }
633
634 /* deselects all, sets active object */
635 Object *ob;
636 if (obdata != nullptr) {
637 BLI_assert(type == BKE_object_obdata_to_type(obdata));
638 ob = BKE_object_add_for_data(bmain, scene, view_layer, type, name, obdata, true);
639 const short *materials_len_p = BKE_id_material_len_p(obdata);
640 if (materials_len_p && *materials_len_p > 0) {
641 BKE_object_materials_sync_length(bmain, ob, static_cast<ID *>(ob->data));
642 }
643 }
644 else {
645 ob = BKE_object_add(bmain, scene, view_layer, type, name);
646 }
647
648 BKE_view_layer_synced_ensure(scene, view_layer);
649 Base *ob_base_act = BKE_view_layer_active_base_get(view_layer);
650 /* While not getting a valid base is not a good thing, it can happen in convoluted corner cases,
651 * better not crash on it in releases. */
652 BLI_assert(ob_base_act != nullptr);
653 if (ob_base_act != nullptr) {
654 ob_base_act->local_view_bits = local_view_bits;
655 /* editor level activate, notifiers */
656 base_activate(C, ob_base_act);
657 }
658
659 /* more editor stuff */
660 init_transform_on_add(ob, loc, rot);
661
662 /* TODO(sergey): This is weird to manually tag objects for update, better to
663 * use DEG_id_tag_update here perhaps.
664 */
665 DEG_id_type_tag(bmain, ID_OB);
667 if (ob->data != nullptr) {
669 }
670
671 if (enter_editmode) {
672 editmode_enter_ex(bmain, scene, ob, 0);
673 }
674
676
678
680
681 return ob;
682}
683
685 const int type,
686 const char *name,
687 const float loc[3],
688 const float rot[3],
689 const bool enter_editmode,
690 const ushort local_view_bits)
691{
692 return add_type_with_obdata(C, type, name, loc, rot, enter_editmode, local_view_bits, nullptr);
693}
694
696{
697 return ELEM(ob->type,
698 OB_MESH,
700 OB_SURF,
701 OB_FONT,
702 OB_CURVES,
704 OB_LATTICE);
705}
706
707/* for object add operator */
709{
710 ushort local_view_bits;
711 bool enter_editmode;
712 float loc[3], rot[3], radius;
714 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
715
716 radius = RNA_float_get(op->ptr, "radius");
717 Object *ob = add_type(
718 C, RNA_enum_get(op->ptr, "type"), nullptr, loc, rot, enter_editmode, local_view_bits);
719
720 if (ob->type == OB_LATTICE) {
721 /* lattice is a special case!
722 * we never want to scale the obdata since that is the rest-state */
723 copy_v3_fl(ob->scale, radius);
724 }
725 else {
726 BKE_object_obdata_size_init(ob, radius);
727 }
728
729 return OPERATOR_FINISHED;
730}
731
733{
734 /* identifiers */
735 ot->name = "Add Object";
736 ot->description = "Add an object to the scene";
737 ot->idname = "OBJECT_OT_add";
738
739 /* API callbacks. */
740 ot->exec = object_add_exec;
742
743 /* flags */
745
746 /* properties */
748 PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
750
751 add_generic_props(ot, true);
752}
753
754/* -------------------------------------------------------------------- */
757
759 bContext *C, const float orientation_matrix[3][3], Vector<Object *> &r_targets)
760{
761 ViewLayer *view_layer = CTX_data_view_layer(C);
762 View3D *v3d = CTX_wm_view3d(C);
764
765 Bounds<float3> local_bounds;
766 local_bounds.min = float3(FLT_MAX);
767 local_bounds.max = float3(-FLT_MAX);
768 bool has_bounds = false;
769
770 float inverse_orientation_matrix[3][3];
771 invert_m3_m3_safe_ortho(inverse_orientation_matrix, orientation_matrix);
772
773 LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
774 if (!BASE_SELECTED_EDITABLE(v3d, base) || !object_can_have_lattice_modifier(base->object)) {
775 continue;
776 }
777
778 r_targets.append(base->object);
779 const Object *object_eval = DEG_get_evaluated(depsgraph, base->object);
780 if (object_eval && DEG_object_transform_is_evaluated(*object_eval)) {
781 if (std::optional<Bounds<float3>> object_bounds = BKE_object_boundbox_get(object_eval)) {
782 const float (*object_to_world_matrix)[4] = object_eval->object_to_world().ptr();
783 /* Generate all 8 corners of the bounding box. */
784 std::array<float3, 8> corners = bounds::corners(*object_bounds);
785 for (float3 &corner : corners) {
786 mul_m4_v3(object_to_world_matrix, corner);
787 mul_m3_v3(inverse_orientation_matrix, corner);
788 local_bounds.min = math::min(local_bounds.min, corner);
789 local_bounds.max = math::max(local_bounds.max, corner);
790 }
791 has_bounds = true;
792 }
793 }
794 }
795
796 if (has_bounds) {
797 return local_bounds;
798 }
799 return std::nullopt;
800}
801
803{
804 Main *bmain = CTX_data_main(C);
805 Scene *scene = CTX_data_scene(C);
806 Object *ob_active = CTX_data_active_object(C);
807 ushort local_view_bits;
808 bool enter_editmode;
809 float location[3], rotation_euler[3];
812 C, op, 'Z', location, rotation_euler, nullptr, &enter_editmode, &local_view_bits, nullptr);
813
814 const float margin = RNA_float_get(op->ptr, "margin");
815 const bool add_modifiers = RNA_boolean_get(op->ptr, "add_modifiers");
816 const int resolution_u = RNA_int_get(op->ptr, "resolution_u");
817 const int resolution_v = RNA_int_get(op->ptr, "resolution_v");
818 const int resolution_w = RNA_int_get(op->ptr, "resolution_w");
820 float orientation_matrix[3][3];
821
822 if (ob_active) {
823 copy_m3_m4(orientation_matrix, ob_active->object_to_world().ptr());
824 normalize_m3(orientation_matrix);
825 }
826 else {
827 unit_m3(orientation_matrix);
828 }
829
830 Vector<Object *> targets;
831 std::optional<Bounds<float3>> bounds_opt =
833
834 /* Disable fit to selected when there are no valid targets
835 * (either nothing is selected or meshes with no geometry). */
836 if (targets.is_empty() || !bounds_opt.has_value()) {
837 RNA_boolean_set(op->ptr, "fit_to_selected", false);
838 }
839 const bool fit_to_selected = RNA_boolean_get(op->ptr, "fit_to_selected");
840
841 Object *ob_lattice = add_type(
842 C, OB_LATTICE, nullptr, location, rotation_euler, enter_editmode, local_view_bits);
843 Lattice *lt = (Lattice *)ob_lattice->data;
844
845 if (fit_to_selected && bounds_opt.has_value()) {
846 /* Calculate the center and size of this combined bounding box. */
847 const float3 center_local = bounds_opt->center();
848 const float3 size_local = bounds_opt->size() + float3(margin * 2);
849
850 /* Orient lattice center and apply rotation. */
851 float3 center_world = center_local;
852 mul_m3_v3(orientation_matrix, center_world);
853 BKE_object_mat3_to_rot(ob_lattice, orientation_matrix, false);
854
855 copy_v3_v3(ob_lattice->loc, center_world);
856 copy_v3_v3(ob_lattice->scale, size_local);
857
858 /* Prevent invalid or zero lattice size, fallback to 1.0f. */
859 for (int i = 0; i < 3; i++) {
860 if (!isfinite(ob_lattice->scale[i]) || ob_lattice->scale[i] <= FLT_EPSILON) {
861 ob_lattice->scale[i] = 1.0f;
862 }
863 }
864 }
865 else {
866 /* Fallback when fit to selected is off. */
867 copy_v3_fl(ob_lattice->scale, RNA_float_get(op->ptr, "radius"));
868
869 /* Apply user specified Euler rotation instead of cached quat. */
870 ob_lattice->rotmode = ROT_MODE_EUL;
871 copy_v3_v3(ob_lattice->rot, rotation_euler);
872 }
873
874 if (add_modifiers) {
875 for (Object *ob : targets) {
876 BLI_assert(ob != ob_lattice);
878
880 op->reports, bmain, scene, ob, nullptr, eModifierType_Lattice);
881 if (UNLIKELY(lmd == nullptr)) {
882 continue;
883 }
884
885 lmd->object = ob_lattice;
888 }
889 }
890
892 lt, max_ii(1, resolution_u), max_ii(1, resolution_v), max_ii(1, resolution_w), ob_lattice);
893
895 return OPERATOR_FINISHED;
896}
897
899 wmOperator *op,
900 const PropertyRNA *prop)
901{
902 const char *prop_id = RNA_property_identifier(prop);
903
904 /* Shows only relevant redo properties.
905 * If `fit_to_selected` is:
906 * - true: location & rotation are ignored.
907 * - false: margin is ignored since it only applies to the "fit".
908 */
909 if (RNA_boolean_get(op->ptr, "fit_to_selected")) {
910 if (STR_ELEM(prop_id, "radius", "align", "location", "rotation")) {
911 return false;
912 }
913 }
914 else {
915 if (STREQ(prop_id, "margin")) {
916 return false;
917 }
918 }
919 return true;
920}
921
923{
924 /* identifiers */
925 ot->name = "Add Lattice Deformer";
926 ot->description = "Add a lattice and use it to deform selected objects";
927 ot->idname = "OBJECT_OT_lattice_add_to_selected";
928
929 /* API callbacks. */
933
935
936 /* properties */
937 PropertyRNA *prop;
938
939 prop = RNA_def_boolean(ot->srna,
940 "fit_to_selected",
941 true,
942 "Fit to Selected",
943 "Resize lattice to fit selected deformable objects");
945
947 prop = RNA_def_float(ot->srna,
948 "margin",
949 0.0f,
950 0.0f,
951 FLT_MAX,
952 "Margin",
953 "Add margin to lattice dimensions",
954 0.0f,
955 10.0f);
957
958 prop = RNA_def_boolean(ot->srna,
959 "add_modifiers",
960 true,
961 "Add Modifiers",
962 "Automatically add lattice modifiers to selected objects");
964
965 prop = RNA_def_int(ot->srna,
966 "resolution_u",
967 2,
968 1,
969 64,
970 "Resolution U",
971 "Lattice resolution in U direction",
972 1,
973 64);
975
976 prop = RNA_def_int(
977 ot->srna, "resolution_v", 2, 1, 64, "V", "Lattice resolution in V direction", 1, 64);
979
980 prop = RNA_def_int(
981 ot->srna, "resolution_w", 2, 1, 64, "W", "Lattice resolution in W direction", 1, 64);
982 add_generic_props(ot, true);
983}
984
986
987/* -------------------------------------------------------------------- */
990
991/* for object add operator */
992static const char *get_lightprobe_defname(int type)
993{
994 switch (type) {
996 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Volume");
998 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Plane");
1000 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sphere");
1001 default:
1002 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
1003 }
1004}
1005
1007{
1008 bool enter_editmode;
1009 ushort local_view_bits;
1010 float loc[3], rot[3];
1012 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1013
1014 int type = RNA_enum_get(op->ptr, "type");
1015 float radius = RNA_float_get(op->ptr, "radius");
1016
1017 Object *ob = add_type(
1018 C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
1019 copy_v3_fl(ob->scale, radius);
1020
1021 LightProbe *probe = (LightProbe *)ob->data;
1022
1023 BKE_lightprobe_type_set(probe, type);
1024
1025 return OPERATOR_FINISHED;
1026}
1027
1029{
1030 /* identifiers */
1031 ot->name = "Add Light Probe";
1032 ot->description = "Add a light probe object";
1033 ot->idname = "OBJECT_OT_lightprobe_add";
1034
1035 /* API callbacks. */
1036 ot->exec = lightprobe_add_exec;
1037 ot->poll = ED_operator_objectmode;
1038
1039 /* flags */
1040 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1041
1042 /* properties */
1043 ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
1044
1046 add_generic_props(ot, true);
1047}
1048
1050
1051/* -------------------------------------------------------------------- */
1054
1055/* for object add operator */
1056
1057static const char *get_effector_defname(ePFieldType type)
1058{
1059 switch (type) {
1060 case PFIELD_FORCE:
1061 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Force");
1062 case PFIELD_VORTEX:
1063 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Vortex");
1064 case PFIELD_MAGNET:
1065 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Magnet");
1066 case PFIELD_WIND:
1067 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Wind");
1068 case PFIELD_GUIDE:
1069 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
1070 case PFIELD_TEXTURE:
1071 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "TextureField");
1072 case PFIELD_HARMONIC:
1073 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Harmonic");
1074 case PFIELD_CHARGE:
1075 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Charge");
1076 case PFIELD_LENNARDJ:
1077 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Lennard-Jones");
1078 case PFIELD_BOID:
1079 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Boid");
1080 case PFIELD_TURBULENCE:
1081 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Turbulence");
1082 case PFIELD_DRAG:
1083 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Drag");
1084 case PFIELD_FLUIDFLOW:
1085 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "FluidField");
1086 case PFIELD_NULL:
1087 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
1088 case NUM_PFIELD_TYPES:
1089 break;
1090 }
1091
1092 BLI_assert(false);
1093 return CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
1094}
1095
1097{
1098 bool enter_editmode;
1099 ushort local_view_bits;
1100 float loc[3], rot[3];
1102 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1103
1104 const ePFieldType type = static_cast<ePFieldType>(RNA_enum_get(op->ptr, "type"));
1105 float dia = RNA_float_get(op->ptr, "radius");
1106
1107 Object *ob;
1108 if (type == PFIELD_GUIDE) {
1109 Main *bmain = CTX_data_main(C);
1110 Scene *scene = CTX_data_scene(C);
1111 ob = add_type(
1112 C, OB_CURVES_LEGACY, get_effector_defname(type), loc, rot, false, local_view_bits);
1113
1114 Curve *cu = static_cast<Curve *>(ob->data);
1115 cu->flag |= CU_PATH | CU_3D;
1116 editmode_enter_ex(bmain, scene, ob, 0);
1117
1118 float mat[4][4];
1119 new_primitive_matrix(C, ob, loc, rot, nullptr, mat);
1120 mul_mat3_m4_fl(mat, dia);
1123 if (!enter_editmode) {
1124 editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
1125 }
1126 }
1127 else {
1128 ob = add_type(C, OB_EMPTY, get_effector_defname(type), loc, rot, false, local_view_bits);
1130 if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) {
1132 }
1133 }
1134
1135 ob->pd = BKE_partdeflect_new(type);
1136
1137 return OPERATOR_FINISHED;
1138}
1139
1141{
1142 /* identifiers */
1143 ot->name = "Add Effector";
1144 ot->description = "Add an empty object with a physics effector to the scene";
1145 ot->idname = "OBJECT_OT_effector_add";
1146
1147 /* API callbacks. */
1148 ot->exec = effector_add_exec;
1149 ot->poll = ED_operator_objectmode;
1150
1151 /* flags */
1152 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1153
1154 /* properties */
1155 ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
1156
1158 add_generic_props(ot, true);
1159}
1160
1162
1163/* -------------------------------------------------------------------- */
1166
1168{
1169 View3D *v3d = CTX_wm_view3d(C);
1170 Scene *scene = CTX_data_scene(C);
1171
1172 /* force view align for cameras */
1173 RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
1174
1175 ushort local_view_bits;
1176 bool enter_editmode;
1177 float loc[3], rot[3];
1178 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1179
1180 Object *ob = add_type(C, OB_CAMERA, nullptr, loc, rot, false, local_view_bits);
1181
1182 if (v3d) {
1183 if (v3d->camera == nullptr) {
1184 v3d->camera = ob;
1185 }
1186 if (v3d->scenelock && scene->camera == nullptr) {
1187 scene->camera = ob;
1188 }
1189 }
1190
1191 Camera *cam = static_cast<Camera *>(ob->data);
1192 cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
1193 ED_scene_grid_scale(scene, nullptr);
1194
1195 return OPERATOR_FINISHED;
1196}
1197
1199{
1200 PropertyRNA *prop;
1201
1202 /* identifiers */
1203 ot->name = "Add Camera";
1204 ot->description = "Add a camera object to the scene";
1205 ot->idname = "OBJECT_OT_camera_add";
1206
1207 /* API callbacks. */
1208 ot->exec = object_camera_add_exec;
1209 ot->poll = ED_operator_objectmode;
1210
1211 /* flags */
1212 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1213
1214 add_generic_props(ot, true);
1215
1216 /* hide this for cameras, default */
1217 prop = RNA_struct_type_find_property(ot->srna, "align");
1219}
1220
1222
1223/* -------------------------------------------------------------------- */
1226
1228{
1229 Main *bmain = CTX_data_main(C);
1230 Scene *scene = CTX_data_scene(C);
1231 ViewLayer *view_layer = CTX_data_view_layer(C);
1232
1233 ushort local_view_bits;
1234 bool enter_editmode;
1235 float loc[3], rot[3];
1237 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1238
1239 bool newob = false;
1240 BKE_view_layer_synced_ensure(scene, view_layer);
1241 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
1242 if (obedit == nullptr || obedit->type != OB_MBALL) {
1243 obedit = add_type(C, OB_MBALL, nullptr, loc, rot, true, local_view_bits);
1244 newob = true;
1245 }
1246 else {
1248 }
1249
1250 float mat[4][4];
1251 new_primitive_matrix(C, obedit, loc, rot, nullptr, mat);
1252 /* Halving here is done to account for constant values from #BKE_mball_element_add.
1253 * While the default radius of the resulting meta element is 2,
1254 * we want to pass in 1 so other values such as resolution are scaled by 1.0. */
1255 float dia = RNA_float_get(op->ptr, "radius") / 2;
1256
1257 ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type"));
1258
1259 /* userdef */
1260 if (newob && !enter_editmode) {
1261 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1262 }
1263 else {
1264 /* Only needed in edit-mode (#add_type normally handles this). */
1266 }
1267
1268 return OPERATOR_FINISHED;
1269}
1270
1272{
1273 /* identifiers */
1274 ot->name = "Add Metaball";
1275 ot->description = "Add an metaball object to the scene";
1276 ot->idname = "OBJECT_OT_metaball_add";
1277
1278 /* API callbacks. */
1279 ot->invoke = WM_menu_invoke;
1282
1283 /* flags */
1284 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1285
1286 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
1287
1289 add_generic_props(ot, true);
1290}
1291
1293
1294/* -------------------------------------------------------------------- */
1297
1299{
1300 Object *obedit = CTX_data_edit_object(C);
1301 bool enter_editmode;
1302 ushort local_view_bits;
1303 float loc[3], rot[3];
1304
1306 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1307
1308 if (obedit && obedit->type == OB_FONT) {
1309 return OPERATOR_CANCELLED;
1310 }
1311
1312 obedit = add_type(C, OB_FONT, nullptr, loc, rot, enter_editmode, local_view_bits);
1313 BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
1314
1315 return OPERATOR_FINISHED;
1316}
1317
1319{
1320 /* identifiers */
1321 ot->name = "Add Text";
1322 ot->description = "Add a text object to the scene";
1323 ot->idname = "OBJECT_OT_text_add";
1324
1325 /* API callbacks. */
1326 ot->exec = object_add_text_exec;
1327 ot->poll = ED_operator_objectmode;
1328
1329 /* flags */
1330 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1331
1332 /* properties */
1334 add_generic_props(ot, true);
1335}
1336
1338
1339/* -------------------------------------------------------------------- */
1342
1344{
1345 Main *bmain = CTX_data_main(C);
1346 Scene *scene = CTX_data_scene(C);
1347 ViewLayer *view_layer = CTX_data_view_layer(C);
1348 BKE_view_layer_synced_ensure(scene, view_layer);
1349 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
1350
1352 bool newob = false;
1353 bool enter_editmode;
1354 ushort local_view_bits;
1355 float loc[3], rot[3], dia;
1356 bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
1357
1359 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, &enter_editmode, &local_view_bits, nullptr);
1360
1361 if ((obedit == nullptr) || (obedit->type != OB_ARMATURE)) {
1362 obedit = add_type(C, OB_ARMATURE, nullptr, loc, rot, true, local_view_bits);
1363 editmode_enter_ex(bmain, scene, obedit, 0);
1364 newob = true;
1365 }
1366 else {
1368 }
1369
1370 if (obedit == nullptr) {
1371 BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
1372 return OPERATOR_CANCELLED;
1373 }
1374
1375 /* Give the Armature its default bone collection. */
1376 bArmature *armature = static_cast<bArmature *>(obedit->data);
1377 BoneCollection *default_bonecoll = ANIM_armature_bonecoll_new(armature, "");
1378 ANIM_armature_bonecoll_active_set(armature, default_bonecoll);
1379
1380 dia = RNA_float_get(op->ptr, "radius");
1381 ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
1382
1383 /* userdef */
1384 if (newob && !enter_editmode) {
1385 editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
1386 }
1387
1388 return OPERATOR_FINISHED;
1389}
1390
1392{
1393 /* identifiers */
1394 ot->name = "Add Armature";
1395 ot->description = "Add an armature object to the scene";
1396 ot->idname = "OBJECT_OT_armature_add";
1397
1398 /* API callbacks. */
1400 ot->poll = ED_operator_objectmode;
1401
1402 /* flags */
1403 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1404
1405 /* properties */
1407 add_generic_props(ot, true);
1408}
1409
1411
1412/* -------------------------------------------------------------------- */
1415
1417{
1418 Object *ob;
1419 int type = RNA_enum_get(op->ptr, "type");
1420 ushort local_view_bits;
1421 float loc[3], rot[3];
1422
1424 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1425
1426 ob = add_type(C, OB_EMPTY, nullptr, loc, rot, false, local_view_bits);
1427
1429 BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
1430
1431 return OPERATOR_FINISHED;
1432}
1433
1435{
1436 /* identifiers */
1437 ot->name = "Add Empty";
1438 ot->description = "Add an empty object to the scene";
1439 ot->idname = "OBJECT_OT_empty_add";
1440
1441 /* API callbacks. */
1442 ot->invoke = WM_menu_invoke;
1443 ot->exec = object_empty_add_exec;
1444 ot->poll = ED_operator_objectmode;
1445
1446 /* flags */
1447 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1448
1449 /* properties */
1450 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
1451
1453 add_generic_props(ot, false);
1454}
1455
1457{
1458 Image *ima = nullptr;
1459
1460 ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
1461 if (!ima) {
1462 return OPERATOR_CANCELLED;
1463 }
1464
1465 if (!ED_operator_objectmode(C)) {
1466 BKE_report(op->reports, RPT_ERROR, "Image objects can only be added in Object Mode");
1467 return OPERATOR_CANCELLED;
1468 }
1469
1470 /* Add new empty. */
1471 ushort local_view_bits;
1472 float loc[3], rot[3];
1473
1474 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1475
1476 Object *ob = add_type(C, OB_EMPTY, nullptr, loc, rot, false, local_view_bits);
1477 ob->empty_drawsize = 5.0f;
1478
1479 if (RNA_boolean_get(op->ptr, "background")) {
1480 /* When "background" has been set to "true", set image to render in the background. */
1483
1485 if (rv3d->persp != RV3D_PERSP) {
1487 }
1488 }
1489
1491
1492 ob->data = ima;
1493
1494 return OPERATOR_FINISHED;
1495}
1496
1498{
1499 if (!RNA_struct_property_is_set(op->ptr, "align")) {
1500 /* Default to Aligned unless something else was explicitly passed. */
1501 RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
1502 }
1503
1504 /* Check if the user has not specified the image to load.
1505 * If they have not, assume this is a drag an drop operation. */
1506 if (!RNA_struct_property_is_set(op->ptr, "filepath") &&
1508 {
1511 }
1512
1513 if (!RNA_struct_property_is_set(op->ptr, "background")) {
1514 /* Check if we should switch to "background" mode. */
1516 if (rv3d->persp != RV3D_PERSP) {
1517 RNA_boolean_set(op->ptr, "background", true);
1518 }
1519 }
1520
1521 float loc[3];
1522 location_from_view(C, loc);
1523 ED_view3d_cursor3d_position(C, event->mval, false, loc);
1524 RNA_float_set_array(op->ptr, "location", loc);
1525
1526 Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
1527
1528 /* Either change empty under cursor or create a new empty. */
1529 if (!ob_cursor || ob_cursor->type != OB_EMPTY) {
1530 return object_image_add_exec(C, op);
1531 }
1532 /* User dropped an image on an existing image. */
1533 Image *ima = nullptr;
1534
1535 ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
1536 if (!ima) {
1537 return OPERATOR_CANCELLED;
1538 }
1539 /* Handled below. */
1540 id_us_min(&ima->id);
1541
1542 Scene *scene = CTX_data_scene(C);
1545
1547
1548 id_us_min(static_cast<ID *>(ob_cursor->data));
1549 ob_cursor->data = ima;
1550 id_us_plus(static_cast<ID *>(ob_cursor->data));
1551 return OPERATOR_FINISHED;
1552}
1553
1555{
1556 return CTX_wm_region_view3d(C);
1557}
1558
1560{
1561 /* identifiers */
1562 ot->name = "Add Empty Image/Drop Image to Empty";
1563 ot->description = "Add an empty image type to scene with data";
1564 ot->idname = "OBJECT_OT_empty_image_add";
1565
1566 /* API callbacks. */
1567 ot->invoke = object_image_add_invoke;
1568 ot->exec = object_image_add_exec;
1569 ot->poll = object_image_add_poll;
1570
1571 /* flags */
1572 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1573
1574 /* properties */
1582
1584 add_generic_props(ot, false);
1585 PropertyRNA *prop;
1586 prop = RNA_def_boolean(ot->srna,
1587 "background",
1588 false,
1589 "Put in Background",
1590 "Make the image render behind all objects");
1592 /* Hide the filepath and relative path prop */
1593 prop = RNA_struct_type_find_property(ot->srna, "filepath");
1595 prop = RNA_struct_type_find_property(ot->srna, "relative_path");
1597}
1598
1600
1601/* -------------------------------------------------------------------- */
1604
1607 "2D",
1608 0,
1609 "2D Layers",
1610 "Display strokes using Grease Pencil layers to define order"},
1611 {GP_DRAWMODE_3D, "3D", 0, "3D Location", "Display strokes using real 3D position in 3D space"},
1612 {0, nullptr, 0, nullptr, nullptr},
1613};
1614
1616{
1617 Main *bmain = CTX_data_main(C);
1618 Scene *scene = CTX_data_scene(C);
1619 Object *original_active_object = CTX_data_active_object(C);
1620 /* TODO: For now, only support adding the 'Stroke' type. */
1621 const int type = RNA_enum_get(op->ptr, "type");
1622
1623 ushort local_view_bits;
1624 float loc[3], rot[3];
1625
1626 /* NOTE: We use 'Y' here (not 'Z'), as. */
1628 add_generic_get_opts(C, op, 'Y', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1629
1630 const char *ob_name = nullptr;
1631 switch (type) {
1632 case GP_EMPTY: {
1633 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "GPencil");
1634 break;
1635 }
1636 case GP_STROKE: {
1637 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Stroke");
1638 break;
1639 }
1640 case GP_MONKEY: {
1641 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "Suzanne");
1642 break;
1643 }
1647 ob_name = CTX_DATA_(BLT_I18NCONTEXT_ID_GPENCIL, "LineArt");
1648 break;
1649 }
1650 default: {
1651 break;
1652 }
1653 }
1654
1655 Object *object = add_type(C, OB_GREASE_PENCIL, ob_name, loc, rot, false, local_view_bits);
1656 GreasePencil &grease_pencil_id = *static_cast<GreasePencil *>(object->data);
1657 const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front");
1658 const bool use_lights = RNA_boolean_get(op->ptr, "use_lights");
1659
1660 switch (type) {
1661 case GP_EMPTY: {
1662 greasepencil::create_blank(*bmain, *object, scene->r.cfra);
1663 break;
1664 }
1665 case GP_STROKE: {
1666 const float radius = RNA_float_get(op->ptr, "radius");
1667 const float3 scale(radius);
1668
1669 float4x4 mat;
1670 new_primitive_matrix(C, object, loc, rot, scale, mat.ptr());
1671
1672 greasepencil::create_stroke(*bmain, *object, mat, scene->r.cfra);
1673 break;
1674 }
1675 case GP_MONKEY: {
1676 const float radius = RNA_float_get(op->ptr, "radius");
1677 const float3 scale(radius);
1678
1679 float4x4 mat;
1680 new_primitive_matrix(C, object, loc, rot, scale, mat.ptr());
1681
1682 greasepencil::create_suzanne(*bmain, *object, mat, scene->r.cfra);
1683 break;
1684 }
1688 const int type = RNA_enum_get(op->ptr, "type");
1689 const int stroke_depth_order = RNA_enum_get(op->ptr, "stroke_depth_order");
1690 const float stroke_depth_offset = RNA_float_get(op->ptr, "stroke_depth_offset");
1691
1692 greasepencil::create_blank(*bmain, *object, scene->r.cfra);
1693
1694 auto *grease_pencil = reinterpret_cast<GreasePencil *>(object->data);
1696 auto *md = reinterpret_cast<GreasePencilLineartModifierData *>(new_md);
1697
1698 BLI_addtail(&object->modifiers, md);
1699 BKE_modifier_unique_name(&object->modifiers, new_md);
1700 BKE_modifiers_persistent_uid_init(*object, *new_md);
1701
1703 md->source_type = LINEART_SOURCE_COLLECTION;
1704 md->source_collection = CTX_data_collection(C);
1705 }
1706 else if (type == GREASE_PENCIL_LINEART_OBJECT) {
1707 md->source_type = LINEART_SOURCE_OBJECT;
1708 md->source_object = original_active_object;
1709 }
1710 else {
1711 /* Whole scene. */
1712 md->source_type = LINEART_SOURCE_SCENE;
1713 }
1714 /* Only created one layer and one material. */
1715 STRNCPY_UTF8(md->target_layer, grease_pencil->get_active_layer()->name().c_str());
1716 md->target_material = BKE_object_material_get(object, 0);
1717 if (md->target_material) {
1718 id_us_plus(&md->target_material->id);
1719 }
1720
1721 if (!use_in_front) {
1722 if (stroke_depth_order == GP_DRAWMODE_3D) {
1723 grease_pencil->flag |= GREASE_PENCIL_STROKE_ORDER_3D;
1724 }
1725 md->stroke_depth_offset = stroke_depth_offset;
1726 }
1727
1728 break;
1729 }
1730 }
1731
1732 SET_FLAG_FROM_TEST(object->dtx, use_in_front, OB_DRAW_IN_FRONT);
1734
1735 for (blender::bke::greasepencil::Layer *layer : grease_pencil_id.layers_for_write()) {
1736 SET_FLAG_FROM_TEST(layer->as_node().flag, use_lights, GP_LAYER_TREE_NODE_USE_LIGHTS);
1737 }
1738
1739 DEG_id_tag_update(&grease_pencil_id.id, ID_RECALC_GEOMETRY);
1740 WM_main_add_notifier(NC_GEOM | ND_DATA, &grease_pencil_id.id);
1741
1742 return OPERATOR_FINISHED;
1743}
1744
1746 wmOperator *op,
1747 const wmEvent * /*event*/)
1748{
1749 const int type = RNA_enum_get(op->ptr, "type");
1750
1751 /* Only disable "use_in_front" if it's one of the non-LineArt types */
1752 if (ELEM(type, GP_EMPTY, GP_STROKE, GP_MONKEY)) {
1753 RNA_boolean_set(op->ptr, "use_in_front", false);
1754 }
1755
1756 return object_grease_pencil_add_exec(C, op);
1757}
1758
1760{
1761 /* identifiers */
1762 ot->name = "Add Grease Pencil";
1763 ot->description = "Add a Grease Pencil object to the scene";
1764 ot->idname = "OBJECT_OT_grease_pencil_add";
1765
1766 /* API callbacks. */
1769 ot->poll = ED_operator_objectmode;
1770
1771 /* flags */
1772 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1773
1774 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
1776 RNA_def_boolean(ot->srna,
1777 "use_in_front",
1778 true,
1779 "Show In Front",
1780 "Show Line Art Grease Pencil in front of everything");
1781 RNA_def_float(ot->srna,
1782 "stroke_depth_offset",
1783 0.05f,
1784 0.0f,
1785 FLT_MAX,
1786 "Stroke Offset",
1787 "Stroke offset for the Line Art modifier",
1788 0.0f,
1789 0.5f);
1791 ot->srna, "use_lights", true, "Use Lights", "Use lights for this Grease Pencil object");
1793 ot->srna,
1794 "stroke_depth_order",
1797 "Stroke Depth Order",
1798 "Defines how the strokes are ordered in 3D space (for objects not displayed 'In Front')");
1799
1801 add_generic_props(ot, false);
1802}
1803
1805
1806/* -------------------------------------------------------------------- */
1809
1810static const char *get_light_defname(int type)
1811{
1812 switch (type) {
1813 case LA_LOCAL:
1814 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
1815 case LA_SUN:
1816 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
1817 case LA_SPOT:
1818 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
1819 case LA_AREA:
1820 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
1821 default:
1822 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
1823 }
1824}
1825
1827{
1828 Object *ob;
1829 Light *la;
1830 int type = RNA_enum_get(op->ptr, "type");
1831 ushort local_view_bits;
1832 float loc[3], rot[3];
1833
1835 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
1836
1837 ob = add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
1838
1839 float size = RNA_float_get(op->ptr, "radius");
1840 /* Better defaults for light size. */
1841 switch (type) {
1842 case LA_LOCAL:
1843 case LA_SPOT:
1844 break;
1845 case LA_AREA:
1846 size *= 4.0f;
1847 break;
1848 default:
1849 size *= 0.5f;
1850 break;
1851 }
1853
1854 la = (Light *)ob->data;
1855 la->type = type;
1856
1857 if (type == LA_SUN) {
1858 la->energy = 1.0f;
1859 }
1860
1861 return OPERATOR_FINISHED;
1862}
1863
1865{
1866 /* identifiers */
1867 ot->name = "Add Light";
1868 ot->description = "Add a light object to the scene";
1869 ot->idname = "OBJECT_OT_light_add";
1870
1871 /* API callbacks. */
1872 ot->invoke = WM_menu_invoke;
1873 ot->exec = object_light_add_exec;
1874 ot->poll = ED_operator_objectmode;
1875
1876 /* flags */
1877 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1878
1879 /* properties */
1880 ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
1882
1884 add_generic_props(ot, false);
1885}
1886
1888
1889/* -------------------------------------------------------------------- */
1892
1894 /* The collection that is supposed to be added, determined through operator properties. */
1896 /* The local-view bits (if any) the object should have set to become visible in current context.
1897 */
1899 /* The transform that should be applied to the collection, determined through operator properties
1900 * if set (e.g. to place the collection under the cursor), otherwise through context (e.g. 3D
1901 * cursor location). */
1902 float loc[3], rot[3], scale[3];
1903};
1904
1905static std::optional<CollectionAddInfo> collection_add_info_get_from_op(bContext *C,
1906 wmOperator *op)
1907{
1908 CollectionAddInfo add_info{};
1909
1910 Main *bmain = CTX_data_main(C);
1911
1912 PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location");
1913
1914 add_info.collection = reinterpret_cast<Collection *>(
1916
1917 bool update_location_if_necessary = false;
1918 if (add_info.collection) {
1919 update_location_if_necessary = true;
1920 }
1921 else {
1922 add_info.collection = static_cast<Collection *>(
1923 BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection")));
1924 }
1925
1926 if (update_location_if_necessary && CTX_wm_region_view3d(C)) {
1927 int mval[2];
1928 if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
1929 location_from_view(C, add_info.loc);
1930 ED_view3d_cursor3d_position(C, mval, false, add_info.loc);
1931 RNA_property_float_set_array(op->ptr, prop_location, add_info.loc);
1932 }
1933 }
1934
1935 if (add_info.collection == nullptr) {
1936 return std::nullopt;
1937 }
1938
1940 op,
1941 'Z',
1942 add_info.loc,
1943 add_info.rot,
1944 add_info.scale,
1945 nullptr,
1946 &add_info.local_view_bits,
1947 nullptr);
1948
1949 ViewLayer *view_layer = CTX_data_view_layer(C);
1950
1951 /* Avoid dependency cycles. */
1952 LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
1953 while (BKE_collection_cycle_find(active_lc->collection, add_info.collection)) {
1954 active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
1955 }
1956
1957 return add_info;
1958}
1959
1961{
1962 std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
1963 if (!add_info) {
1964 return OPERATOR_CANCELLED;
1965 }
1966
1967 Object *ob = add_type(C,
1968 OB_EMPTY,
1969 add_info->collection->id.name + 2,
1970 add_info->loc,
1971 add_info->rot,
1972 false,
1973 add_info->local_view_bits);
1974 /* `add_type()` does not have scale argument so copy that value separately. */
1975 copy_v3_v3(ob->scale, add_info->scale);
1976 ob->instance_collection = add_info->collection;
1977 ob->empty_drawsize = U.collection_instance_empty_size;
1979 id_us_plus(&add_info->collection->id);
1980
1981 return OPERATOR_FINISHED;
1982}
1983
1985 wmOperator *op,
1986 const wmEvent *event)
1987{
1988 if (!object_add_drop_xy_is_set(op)) {
1989 RNA_int_set(op->ptr, "drop_x", event->xy[0]);
1990 RNA_int_set(op->ptr, "drop_y", event->xy[1]);
1991 }
1992
1994 return WM_enum_search_invoke(C, op, event);
1995 }
1996 return op->type->exec(C, op);
1997}
1998
2000{
2001 PropertyRNA *prop;
2002
2003 /* identifiers */
2004 ot->name = "Add Collection Instance";
2005 ot->description = "Add a collection instance";
2006 ot->idname = "OBJECT_OT_collection_instance_add";
2007
2008 /* API callbacks. */
2011 ot->poll = ED_operator_objectmode;
2012
2013 /* flags */
2014 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2015
2016 /* properties */
2018 ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
2019 prop = RNA_def_enum(ot->srna, "collection", rna_enum_dummy_NULL_items, 0, "Collection", "");
2022 ot->prop = prop;
2023 add_generic_props(ot, false);
2024
2026
2028}
2029
2031
2032/* -------------------------------------------------------------------- */
2050
2052{
2053 Main *bmain = CTX_data_main(C);
2054 LayerCollection *active_collection = CTX_data_layer_collection(C);
2055 std::optional<CollectionAddInfo> add_info = collection_add_info_get_from_op(C, op);
2056 if (!add_info) {
2057 return OPERATOR_CANCELLED;
2058 }
2059
2060 if (RNA_boolean_get(op->ptr, "use_instance")) {
2061 BKE_collection_child_remove(bmain, active_collection->collection, add_info->collection);
2064
2065 Object *ob = add_type(C,
2066 OB_EMPTY,
2067 add_info->collection->id.name + 2,
2068 add_info->loc,
2069 add_info->rot,
2070 false,
2071 add_info->local_view_bits);
2072 ob->instance_collection = add_info->collection;
2073 ob->empty_drawsize = U.collection_instance_empty_size;
2075 id_us_plus(&add_info->collection->id);
2076 }
2077 else if (ID_IS_EDITABLE(&add_info->collection->id)) {
2078 ViewLayer *view_layer = CTX_data_view_layer(C);
2079 float delta_mat[4][4];
2080 unit_m4(delta_mat);
2081
2082 const float scale[3] = {1.0f, 1.0f, 1.0f};
2083 loc_eul_size_to_mat4(delta_mat, add_info->loc, add_info->rot, scale);
2084
2085 float offset[3];
2086 /* Reverse apply the instance offset, so toggling the Instance option doesn't cause the
2087 * collection to jump. */
2088 negate_v3_v3(offset, add_info->collection->instance_offset);
2089 translate_m4(delta_mat, UNPACK3(offset));
2090
2093 view_layer, nullptr, &params);
2094 object_xform_array_m4(objects.data(), objects.size(), delta_mat);
2095 }
2096
2097 return OPERATOR_FINISHED;
2098}
2099
2101{
2102 PropertyRNA *prop;
2103
2104 /* identifiers */
2105 /* Name should only be displayed in the drag tooltip. */
2106 ot->name = "Add Collection";
2107 ot->description = "Add the dragged collection to the scene";
2108 ot->idname = "OBJECT_OT_collection_external_asset_drop";
2109
2110 /* API callbacks. */
2112 ot->exec = collection_drop_exec;
2113 ot->poll = ED_operator_objectmode;
2114
2115 /* flags */
2117
2118 /* properties */
2120
2121 add_generic_props(ot, false);
2122
2123 prop = RNA_def_boolean(ot->srna,
2124 "use_instance",
2125 true,
2126 "Instance",
2127 "Add the dropped collection as collection instance");
2129
2131
2132 prop = RNA_def_enum(ot->srna, "collection", rna_enum_dummy_NULL_items, 0, "Collection", "");
2135 ot->prop = prop;
2136}
2137
2139
2140/* -------------------------------------------------------------------- */
2145
2147{
2148 Main *bmain = CTX_data_main(C);
2149 ID *id = nullptr;
2150 ushort local_view_bits;
2151 float loc[3], rot[3];
2152
2153 PropertyRNA *prop_type = RNA_struct_find_property(op->ptr, "type");
2154 PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location");
2155
2156 const short id_type = RNA_property_enum_get(op->ptr, prop_type);
2158 if (id == nullptr) {
2159 return OPERATOR_CANCELLED;
2160 }
2161 const int object_type = BKE_object_obdata_to_type(id);
2162 if (object_type == -1) {
2163 return OPERATOR_CANCELLED;
2164 }
2165
2166 if (CTX_wm_region_view3d(C)) {
2167 int mval[2];
2168 if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
2169 location_from_view(C, loc);
2170 ED_view3d_cursor3d_position(C, mval, false, loc);
2171 RNA_property_float_set_array(op->ptr, prop_location, loc);
2172 }
2173 }
2174
2175 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2176
2177 add_type_with_obdata(C, object_type, id->name + 2, loc, rot, false, local_view_bits, id);
2178
2179 return OPERATOR_FINISHED;
2180}
2181
2183{
2184 /* identifiers */
2185 ot->name = "Add Object Data Instance";
2186 ot->description = "Add an object data instance";
2187 ot->idname = "OBJECT_OT_data_instance_add";
2188
2189 /* API callbacks. */
2192 ot->poll = ED_operator_objectmode;
2193
2194 /* flags */
2195 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2196
2197 /* properties */
2199 PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_id_type_items, 0, "Type", "");
2201 add_generic_props(ot, false);
2202
2204}
2205
2207
2208/* -------------------------------------------------------------------- */
2211
2213{
2214 Main *bmain = CTX_data_main(C);
2215 Scene *scene = CTX_data_scene(C);
2216
2217 ushort local_view_bits;
2218 float loc[3], rot[3];
2219 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2220
2221 Object *ob = add_type(C, OB_SPEAKER, nullptr, loc, rot, false, local_view_bits);
2222 const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob);
2223
2224 /* To make it easier to start using this immediately in NLA, a default sound clip is created
2225 * ready to be moved around to re-time the sound and/or make new sound clips. */
2226 {
2227 /* create new data for NLA hierarchy */
2228 AnimData *adt = BKE_animdata_ensure_id(&ob->id);
2229 NlaTrack *nlt = BKE_nlatrack_new_tail(&adt->nla_tracks, is_liboverride);
2231 NlaStrip *strip = BKE_nla_add_soundstrip(bmain, scene, static_cast<Speaker *>(ob->data));
2232 strip->start = scene->r.cfra;
2233 strip->end += strip->start;
2234
2235 /* hook them up */
2236 BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
2237
2238 /* Auto-name the strip, and give the track an interesting name. */
2239 STRNCPY_UTF8(nlt->name, DATA_("SoundTrack"));
2240 BKE_nlastrip_validate_name(adt, strip);
2241
2243 }
2244
2245 return OPERATOR_FINISHED;
2246}
2247
2249{
2250 /* identifiers */
2251 ot->name = "Add Speaker";
2252 ot->description = "Add a speaker object to the scene";
2253 ot->idname = "OBJECT_OT_speaker_add";
2254
2255 /* API callbacks. */
2257 ot->poll = ED_operator_objectmode;
2258
2259 /* flags */
2260 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2261
2262 add_generic_props(ot, true);
2263}
2264
2266
2267/* -------------------------------------------------------------------- */
2270
2272{
2273 ushort local_view_bits;
2274 float loc[3], rot[3];
2275 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2276
2277 Object *object = add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits);
2278
2279 Curves *curves_id = static_cast<Curves *>(object->data);
2280 curves_id->geometry.wrap() = ed::curves::primitive_random_sphere(500, 8);
2281
2282 return OPERATOR_FINISHED;
2283}
2284
2286{
2287 /* identifiers */
2288 ot->name = "Add Random Curves";
2289 ot->description = "Add a curves object with random curves to the scene";
2290 ot->idname = "OBJECT_OT_curves_random_add";
2291
2292 /* API callbacks. */
2294 ot->poll = ED_operator_objectmode;
2295
2296 /* flags */
2297 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2298
2299 add_generic_props(ot, false);
2300}
2301
2303{
2304 Scene *scene = CTX_data_scene(C);
2305
2306 ushort local_view_bits;
2307 add_generic_get_opts(C, op, 'Z', nullptr, nullptr, nullptr, nullptr, &local_view_bits, nullptr);
2308
2309 Object *surface_ob = CTX_data_active_object(C);
2310 BLI_assert(surface_ob != nullptr);
2311
2312 Object *curves_ob = add_type(C, OB_CURVES, nullptr, nullptr, nullptr, false, local_view_bits);
2313 BKE_object_apply_mat4(curves_ob, surface_ob->object_to_world().ptr(), false, false);
2314
2315 /* Set surface object. */
2316 Curves *curves_id = static_cast<Curves *>(curves_ob->data);
2317 curves_id->surface = surface_ob;
2318
2319 /* Parent to surface object. */
2320 parent_set(op->reports, C, scene, curves_ob, surface_ob, PAR_OBJECT, false, true, nullptr);
2321
2322 /* Decide which UV map to use for attachment. */
2323 Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data);
2324 const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->corner_data,
2326 if (uv_name != nullptr) {
2327 curves_id->surface_uv_map = BLI_strdup(uv_name);
2328 }
2329
2330 /* Add deformation modifier. */
2332
2333 /* Make sure the surface object has a rest position attribute which is necessary for
2334 * deformations. */
2336
2337 return OPERATOR_FINISHED;
2338}
2339
2341{
2342 if (!ED_operator_objectmode(C)) {
2343 return false;
2344 }
2346 if (ob == nullptr || ob->type != OB_MESH) {
2347 CTX_wm_operator_poll_msg_set(C, "No active mesh object");
2348 return false;
2349 }
2350 return true;
2351}
2352
2354{
2355 ot->name = "Add Empty Curves";
2356 ot->description = "Add an empty curve object to the scene with the selected mesh as surface";
2357 ot->idname = "OBJECT_OT_curves_empty_hair_add";
2358
2361
2362 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2363
2364 add_generic_props(ot, false);
2365}
2366
2368
2369/* -------------------------------------------------------------------- */
2372
2374{
2375 ushort local_view_bits;
2376 float loc[3], rot[3];
2377 add_generic_get_opts(C, op, 'Z', loc, rot, nullptr, nullptr, &local_view_bits, nullptr);
2378
2379 Object *object = add_type(C, OB_POINTCLOUD, nullptr, loc, rot, false, local_view_bits);
2380 PointCloud &pointcloud = *static_cast<PointCloud *>(object->data);
2381 pointcloud.totpoint = 400;
2382
2383 bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
2385 "position", bke::AttrDomain::Point);
2387 "radius", bke::AttrDomain::Point);
2388
2389 RandomNumberGenerator rng(0);
2390 for (const int i : position.span.index_range()) {
2391 position.span[i] = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
2392 radii.span[i] = 0.05f * rng.get_float();
2393 }
2394
2395 position.finish();
2396 radii.finish();
2397
2398 return OPERATOR_FINISHED;
2399}
2400
2402{
2403 ot->name = "Add Point Cloud";
2404 ot->description = "Add a point cloud object to the scene";
2405 ot->idname = "OBJECT_OT_pointcloud_random_add";
2406
2408 ot->poll = ED_operator_objectmode;
2409
2410 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2411
2412 add_generic_props(ot, false);
2413}
2414
2416
2417/* -------------------------------------------------------------------- */
2420
2421void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
2422{
2423 if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
2425 {
2426 /* We cannot delete indirectly used object... */
2427 printf(
2428 "WARNING, undeletable object '%s', should have been caught before reaching this "
2429 "function!",
2430 ob->id.name + 2);
2431 return;
2432 }
2434 /* Do not delete objects used by overrides of collections. */
2435 return;
2436 }
2437
2439
2440 BKE_scene_collections_object_remove(bmain, scene, ob, true);
2441}
2442
2449
2451{
2452 Main *bmain = CTX_data_main(C);
2453 Scene *scene = CTX_data_scene(C);
2455 const bool use_global = RNA_boolean_get(op->ptr, "use_global");
2456 const bool confirm = op->flag & OP_IS_INVOKE;
2457 uint changed_count = 0;
2458 uint tagged_count = 0;
2459
2460 if (CTX_data_edit_object(C)) {
2461 return OPERATOR_CANCELLED;
2462 }
2463
2464 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2465
2466 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2467 if (ob->id.tag & ID_TAG_INDIRECT) {
2468 /* Can this case ever happen? */
2469 BKE_reportf(op->reports,
2471 "Cannot delete indirectly linked object '%s'",
2472 ob->id.name + 2);
2473 continue;
2474 }
2475
2476 if (!BKE_lib_override_library_id_is_user_deletable(bmain, &ob->id)) {
2477 BKE_reportf(op->reports,
2479 "Cannot delete object '%s' as it is used by override collections",
2480 ob->id.name + 2);
2481 continue;
2482 }
2483
2484 if (ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0 &&
2486 {
2487 BKE_reportf(op->reports,
2489 "Cannot delete object '%s' from scene '%s', indirectly used objects need at "
2490 "least one user",
2491 ob->id.name + 2,
2492 scene->id.name + 2);
2493 continue;
2494 }
2495
2496 /* Use multi tagged delete if `use_global=True`, or the object is used only in one scene. */
2497 if (use_global || ID_REAL_USERS(ob) <= 1) {
2498 ob->id.tag |= ID_TAG_DOIT;
2499 tagged_count += 1;
2500 }
2501 else {
2502 /* Object is used in multiple scenes. Delete the object from the current scene only. */
2504 changed_count += 1;
2505 }
2506 }
2508
2509 if ((changed_count + tagged_count) == 0) {
2510 return OPERATOR_CANCELLED;
2511 }
2512
2513 if (tagged_count > 0) {
2515 }
2516
2517 if (confirm) {
2518 BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", (changed_count + tagged_count));
2519 }
2520
2521 /* delete has to handle all open scenes */
2523 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
2524 scene = WM_window_get_active_scene(win);
2525
2526 if (scene->id.tag & ID_TAG_DOIT) {
2527 scene->id.tag &= ~ID_TAG_DOIT;
2528
2530
2534 }
2535 }
2536
2537 return OPERATOR_FINISHED;
2538}
2539
2541 wmOperator *op,
2542 const wmEvent * /*event*/)
2543{
2544 if (RNA_boolean_get(op->ptr, "confirm")) {
2546 op,
2547 IFACE_("Delete selected objects?"),
2548 nullptr,
2549 IFACE_("Delete"),
2551 false);
2552 }
2553 return object_delete_exec(C, op);
2554}
2555
2557{
2558 /* identifiers */
2559 ot->name = "Delete";
2560 ot->description = "Delete selected objects";
2561 ot->idname = "OBJECT_OT_delete";
2562
2563 /* API callbacks. */
2564 ot->invoke = object_delete_invoke;
2565 ot->exec = object_delete_exec;
2566 ot->poll = ED_operator_objectmode;
2567
2568 /* flags */
2569 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2570
2571 PropertyRNA *prop;
2572 prop = RNA_def_boolean(
2573 ot->srna, "use_global", false, "Delete Globally", "Remove object from all scenes");
2576}
2577
2579
2580/* -------------------------------------------------------------------- */
2583
2584/* after copying objects, copied data should get new pointers */
2586{
2587 Main *bmain = CTX_data_main(C);
2588
2589 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
2591 }
2593
2594#ifndef NDEBUG
2595 /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
2596 ID *id_iter;
2597 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2598 if (GS(id_iter->name) == ID_OB) {
2599 /* Not all duplicated objects would be used by other newly duplicated data, so their flag
2600 * will not always be cleared. */
2601 continue;
2602 }
2603 BLI_assert((id_iter->tag & ID_TAG_NEW) == 0);
2604 }
2606#endif
2607
2609}
2610
2612
2613/* -------------------------------------------------------------------- */
2616
2617/* XXX TODO: That whole hierarchy handling based on persistent_id tricks is
2618 * very confusing and convoluted, and it will fail in many cases besides basic ones.
2619 * Think this should be replaced by a proper tree-like representation of the instantiations,
2620 * should help a lot in both readability, and precise consistent rebuilding of hierarchy.
2621 */
2622
2636static uint dupliobject_hash(const void *ptr)
2637{
2638 const DupliObject *dob = static_cast<const DupliObject *>(ptr);
2640
2641 if (dob->type == OB_DUPLICOLLECTION) {
2642 for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
2643 hash ^= (dob->persistent_id[i] ^ i);
2644 }
2645 }
2646 else {
2647 hash ^= (dob->persistent_id[0] ^ 0);
2648 }
2649 return hash;
2650}
2651
2659{
2660 const DupliObject *dob = static_cast<const DupliObject *>(ptr);
2662 for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
2663 hash ^= (dob->persistent_id[i] ^ i);
2664 }
2665 return hash;
2666}
2667
2671static bool dupliobject_cmp(const void *a_, const void *b_)
2672{
2673 const DupliObject *a = static_cast<const DupliObject *>(a_);
2674 const DupliObject *b = static_cast<const DupliObject *>(b_);
2675
2676 if (a->ob != b->ob) {
2677 return true;
2678 }
2679
2680 if (a->type != b->type) {
2681 return true;
2682 }
2683
2684 if (a->type == OB_DUPLICOLLECTION) {
2685 for (int i = 1; (i < MAX_DUPLI_RECUR); i++) {
2686 if (a->persistent_id[i] != b->persistent_id[i]) {
2687 return true;
2688 }
2689 if (a->persistent_id[i] == INT_MAX) {
2690 break;
2691 }
2692 }
2693 }
2694 else {
2695 if (a->persistent_id[0] != b->persistent_id[0]) {
2696 return true;
2697 }
2698 }
2699
2700 /* matching */
2701 return false;
2702}
2703
2704/* Compare function that matches dupliobject_instancer_hash. */
2705static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
2706{
2707 const DupliObject *a = static_cast<const DupliObject *>(a_);
2708 const DupliObject *b = static_cast<const DupliObject *>(b_);
2709
2710 for (int i = 0; (i < MAX_DUPLI_RECUR); i++) {
2711 if (a->persistent_id[i] != b->persistent_id[i]) {
2712 return true;
2713 }
2714 if (a->persistent_id[i] == INT_MAX) {
2715 break;
2716 }
2717 }
2718
2719 /* matching */
2720 return false;
2721}
2722
2724 Depsgraph *depsgraph,
2725 Scene *scene,
2726 Base *base,
2727 const bool use_base_parent,
2728 const bool use_hierarchy)
2729{
2730 Main *bmain = CTX_data_main(C);
2731 ViewLayer *view_layer = CTX_data_view_layer(C);
2732 GHash *parent_gh = nullptr, *instancer_gh = nullptr;
2733
2734 Object *object_eval = DEG_get_evaluated(depsgraph, base->object);
2735
2736 if (!(base->object->transflag & OB_DUPLI) &&
2738 {
2739 return;
2740 }
2741
2742 DupliList duplilist;
2743 object_duplilist(depsgraph, scene, object_eval, nullptr, duplilist);
2744
2745 if (duplilist.is_empty()) {
2746 return;
2747 }
2748
2750 if (use_hierarchy) {
2751 parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
2752
2753 if (use_base_parent) {
2754 instancer_gh = BLI_ghash_new(
2756 }
2757 }
2758
2759 for (DupliObject &dob : duplilist) {
2760 Object *ob_src = DEG_get_original(dob.ob);
2761 Object *ob_dst = static_cast<Object *>(ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id)));
2762 id_us_min(&ob_dst->id);
2763
2764 /* font duplis can have a totcol without material, we get them from parent
2765 * should be implemented better...
2766 */
2767 if (ob_dst->mat == nullptr) {
2768 ob_dst->totcol = 0;
2769 }
2770
2771 BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
2772 BKE_view_layer_synced_ensure(scene, view_layer);
2773 Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
2774 BLI_assert(base_dst != nullptr);
2775
2776 base_select(base_dst, BA_SELECT);
2778
2780
2781 /* make sure apply works */
2782 BKE_animdata_free(&ob_dst->id, true);
2783 ob_dst->adt = nullptr;
2784
2785 ob_dst->parent = nullptr;
2787 ob_dst->runtime->curve_cache = nullptr;
2788 const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0;
2789 ob_dst->transflag &= ~OB_DUPLI;
2790 /* Remove instantiated collection, it's annoying to keep it here
2791 * (and get potentially a lot of usages of it then...). */
2792 id_us_min((ID *)ob_dst->instance_collection);
2793 ob_dst->instance_collection = nullptr;
2794
2795 copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob.mat);
2796 BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world().ptr(), false, false);
2797
2798 dupli_map.add(&dob, ob_dst);
2799
2800 if (parent_gh) {
2801 void **val;
2802 /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
2803 * 'the same', this avoids trying to insert same key several time and
2804 * raise asserts in debug builds... */
2805 if (!BLI_ghash_ensure_p(parent_gh, &dob, &val)) {
2806 *val = ob_dst;
2807 }
2808
2809 if (is_dupli_instancer && instancer_gh) {
2810 /* Same as above, we may have several 'hits'. */
2811 if (!BLI_ghash_ensure_p(instancer_gh, &dob, &val)) {
2812 *val = ob_dst;
2813 }
2814 }
2815 }
2816 }
2817
2818 for (DupliObject &dob : duplilist) {
2819 Object *ob_src = dob.ob;
2820 Object *ob_dst = dupli_map.lookup(&dob);
2821
2822 /* Remap new object to itself, and clear again newid pointer of orig object. */
2823 BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0);
2824
2826
2827 if (use_hierarchy) {
2828 /* original parents */
2829 Object *ob_src_par = ob_src->parent;
2830 Object *ob_dst_par = nullptr;
2831
2832 /* find parent that was also made real */
2833 if (ob_src_par) {
2834 /* OK to keep most of the members uninitialized,
2835 * they won't be read, this is simply for a hash lookup. */
2836 DupliObject dob_key;
2837 dob_key.ob = ob_src_par;
2838 dob_key.type = dob.type;
2839 if (dob.type == OB_DUPLICOLLECTION) {
2840 memcpy(&dob_key.persistent_id[1],
2841 &dob.persistent_id[1],
2842 sizeof(dob.persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
2843 }
2844 else {
2845 dob_key.persistent_id[0] = dob.persistent_id[0];
2846 }
2847 ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(parent_gh, &dob_key));
2848 }
2849
2850 if (ob_dst_par) {
2851 /* allow for all possible parent types */
2852 ob_dst->partype = ob_src->partype;
2853 STRNCPY_UTF8(ob_dst->parsubstr, ob_src->parsubstr);
2854 ob_dst->par1 = ob_src->par1;
2855 ob_dst->par2 = ob_src->par2;
2856 ob_dst->par3 = ob_src->par3;
2857
2858 copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
2859
2860 ob_dst->parent = ob_dst_par;
2861 }
2862 }
2863 if (use_base_parent && ob_dst->parent == nullptr) {
2864 Object *ob_dst_par = nullptr;
2865
2866 if (instancer_gh != nullptr) {
2867 /* OK to keep most of the members uninitialized,
2868 * they won't be read, this is simply for a hash lookup. */
2869 DupliObject dob_key;
2870 /* We are looking one step upper in hierarchy, so we need to 'shift' the `persistent_id`,
2871 * ignoring the first item.
2872 * We only check on persistent_id here, since we have no idea what object it might be. */
2873 memcpy(&dob_key.persistent_id[0],
2874 &dob.persistent_id[1],
2875 sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
2876 ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(instancer_gh, &dob_key));
2877 }
2878
2879 if (ob_dst_par == nullptr) {
2880 /* Default to parenting to root object...
2881 * Always the case when use_hierarchy is false. */
2882 ob_dst_par = base->object;
2883 }
2884
2885 ob_dst->parent = ob_dst_par;
2886 ob_dst->partype = PAROBJECT;
2887 }
2888
2889 if (ob_dst->parent) {
2890 /* NOTE: this may be the parent of other objects, but it should
2891 * still work out ok */
2892 BKE_object_apply_mat4(ob_dst, dob.mat, false, true);
2893
2894 /* to set ob_dst->orig and in case there's any other discrepancies */
2896 }
2897 }
2898
2900 base->object->instance_collection = nullptr;
2901 }
2902
2903 base_select(base, BA_DESELECT);
2905
2906 if (parent_gh) {
2907 BLI_ghash_free(parent_gh, nullptr, nullptr);
2908 }
2909 if (instancer_gh) {
2910 BLI_ghash_free(instancer_gh, nullptr, nullptr);
2911 }
2912
2914
2915 base->object->transflag &= ~OB_DUPLI;
2917}
2918
2920{
2921 Main *bmain = CTX_data_main(C);
2923 Scene *scene = CTX_data_scene(C);
2924
2925 const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
2926 const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
2927
2929
2930 CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
2931 make_object_duplilist_real(C, depsgraph, scene, base, use_base_parent, use_hierarchy);
2932
2933 /* dependencies were changed */
2934 WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
2935 }
2937
2942
2943 return OPERATOR_FINISHED;
2944}
2945
2947{
2948 /* identifiers */
2949 ot->name = "Make Instances Real";
2950 ot->description = "Make instanced objects attached to this object real";
2951 ot->idname = "OBJECT_OT_duplicates_make_real";
2952
2953 /* API callbacks. */
2955
2956 ot->poll = ED_operator_objectmode;
2957
2958 /* flags */
2959 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2960
2961 ot->prop = RNA_def_boolean(ot->srna,
2962 "use_base_parent",
2963 false,
2964 "Parent",
2965 "Parent newly created objects to the original instancer");
2968 ot->srna, "use_hierarchy", false, "Keep Hierarchy", "Maintain parent child relationships");
2969}
2970
2972
2973/* -------------------------------------------------------------------- */
2976
2979 "CURVE",
2980 ICON_OUTLINER_OB_CURVE,
2981 "Curve",
2982 "Curve from Mesh or Text objects"},
2983 {OB_MESH,
2984 "MESH",
2985 ICON_OUTLINER_OB_MESH,
2986 "Mesh",
2987 "Mesh from Curve, Surface, Metaball, Text, or Point Cloud objects"},
2989 "POINTCLOUD",
2990 ICON_OUTLINER_OB_POINTCLOUD,
2991 "Point Cloud",
2992 "Point Cloud from Mesh objects"},
2993 {OB_CURVES, "CURVES", ICON_OUTLINER_OB_CURVES, "Curves", "Curves from evaluated curve data"},
2995 "GREASEPENCIL",
2996 ICON_OUTLINER_OB_GREASEPENCIL,
2997 "Grease Pencil",
2998 "Grease Pencil from Curve or Mesh objects"},
2999 {0, nullptr, 0, nullptr, nullptr},
3000};
3001
3003 PointerRNA * /*ptr*/,
3004 PropertyRNA * /*prop*/,
3005 bool *r_free)
3006{
3007 if (!C) { /* needed for docs */
3008 return convert_target_items;
3009 }
3010
3011 EnumPropertyItem *item = nullptr;
3012 int totitem = 0;
3013
3019
3020 RNA_enum_item_end(&item, &totitem);
3021
3022 *r_free = true;
3023
3024 return item;
3025}
3026
3027static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
3028{
3029 Object *object_eval = DEG_get_evaluated(depsgraph, ob);
3030 Curve *curve = static_cast<Curve *>(ob->data);
3031
3032 Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
3033 if (mesh == nullptr) {
3034 /* Unable to convert the curve to a mesh. */
3035 return;
3036 }
3037
3039 /* Replace curve used by the object itself. */
3040 ob->data = mesh;
3041 ob->type = OB_MESH;
3042 id_us_min(&curve->id);
3043 id_us_plus(&mesh->id);
3044 /* Change objects which are using same curve.
3045 * A bit annoying, but:
3046 * - It's possible to have multiple curve objects selected which are sharing the same curve
3047 * data-block. We don't want mesh to be created for every of those objects.
3048 * - This is how conversion worked for a long time. */
3049 LISTBASE_FOREACH (Object *, other_object, &bmain->objects) {
3050 if (other_object->data == curve) {
3051 other_object->type = OB_MESH;
3052
3053 id_us_min((ID *)other_object->data);
3054 other_object->data = ob->data;
3055 id_us_plus((ID *)other_object->data);
3056 }
3057 }
3058}
3059
3061{
3062 Scene *scene = CTX_data_scene(C);
3063 if (!ID_IS_EDITABLE(scene)) {
3064 return false;
3065 }
3066 ViewLayer *view_layer = CTX_data_view_layer(C);
3067 BKE_view_layer_synced_ensure(scene, view_layer);
3068 /* Don't use `active_object` in the context, it's important this value
3069 * is from the view-layer as it's used to check if Blender is in object mode. */
3070 Object *obact = BKE_view_layer_active_object_get(view_layer);
3071 if (obact && obact->mode != OB_MODE_OBJECT) {
3072 return false;
3073 }
3074
3075 /* Note that `obact` may not be editable,
3076 * only check the active object to ensure Blender is in object mode. */
3077 return true;
3078}
3079
3080/* Helper for object_convert_exec */
3082 Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
3083{
3084 if (ob == nullptr) {
3085 ob = base->object;
3086 }
3087
3088 Object *obn = (Object *)BKE_id_copy(bmain, &ob->id);
3089 id_us_min(&obn->id);
3091 BKE_collection_object_add_from(bmain, scene, ob, obn);
3092
3093 BKE_view_layer_synced_ensure(scene, view_layer);
3094 Base *basen = BKE_view_layer_base_find(view_layer, obn);
3095 base_select(basen, BA_SELECT);
3096 base_select(base, BA_DESELECT);
3097
3098 /* XXX: An ugly hack needed because if we re-run depsgraph with some new meta-ball objects
3099 * having same 'family name' as orig ones, they will affect end result of meta-ball computation.
3100 * For until we get rid of that name-based thingy in meta-balls, that should do the trick
3101 * (this is weak, but other solution (to change name of `obn`) is even worse IMHO).
3102 * See #65996. */
3103 const bool is_meta_ball = (obn->type == OB_MBALL);
3104 void *obdata = obn->data;
3105 if (is_meta_ball) {
3106 obn->type = OB_EMPTY;
3107 obn->data = nullptr;
3108 }
3109
3110 /* XXX Doing that here is stupid, it means we update and re-evaluate the whole depsgraph every
3111 * time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since
3112 * we do not yet have duplicated obdata.
3113 * However, that is a safe solution for now. Proper, longer-term solution is to refactor
3114 * object_convert_exec to:
3115 * - duplicate all data it needs to in a first loop.
3116 * - do a single update.
3117 * - convert data in a second loop. */
3119 CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
3122 scene->customdata_mask = customdata_mask_prev;
3123
3124 if (is_meta_ball) {
3125 obn->type = OB_MBALL;
3126 obn->data = obdata;
3127 }
3128
3129 return basen;
3130}
3131
3147
3149{
3150 if (info.keep_original) {
3151 *r_new_base = duplibase_for_convert(
3152 info.bmain, info.depsgraph, info.scene, info.view_layer, &base, nullptr);
3153 Object *newob = (*r_new_base)->object;
3154
3155 /* Decrement original object data usage count. */
3156 ID *original_object_data = static_cast<ID *>(newob->data);
3157 id_us_min(original_object_data);
3158
3159 /* Make a copy of the object data. */
3160 newob->data = BKE_id_copy(info.bmain, original_object_data);
3161
3162 return newob;
3163 }
3164 *r_new_base = nullptr;
3165 return base.object;
3166}
3167
3170 Base **r_new_base)
3171{
3172 Object *ob = base.object;
3173 ob->flag |= OB_DONE;
3174 Object *newob = get_object_for_conversion(base, info, r_new_base);
3175
3176 BKE_mesh_to_curve(info.bmain, info.depsgraph, info.scene, newob);
3177
3178 if (newob->type == OB_CURVES_LEGACY) {
3179 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3180 if (newob->rigidbody_object != nullptr) {
3181 ED_rigidbody_object_remove(info.bmain, info.scene, newob);
3182 }
3183 }
3184
3185 return newob;
3186}
3187
3190 Base **r_new_base)
3191{
3192 Object *ob = base.object, *newob = nullptr;
3193 ob->flag |= OB_DONE;
3194
3195 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3197 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3198 geometry = *ob_eval->runtime->geometry_set_eval;
3199 }
3200
3201 if (geometry.has_curves()) {
3202 newob = get_object_for_conversion(base, info, r_new_base);
3203
3204 const Curves *curves_eval = geometry.get_curves();
3205 Curves *new_curves = BKE_id_new<Curves>(info.bmain, newob->id.name + 2);
3206
3207 newob->data = new_curves;
3208 newob->type = OB_CURVES;
3209
3210 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3211 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3212
3214 BKE_object_free_modifiers(newob, 0);
3215 }
3216 else {
3217 BKE_reportf(info.reports,
3219 "Object '%s' has no evaluated Curve or Grease Pencil data",
3220 ob->id.name + 2);
3221 }
3222
3223 return newob;
3224}
3225
3228 Base **r_new_base)
3229{
3230 Object *ob = base.object, *newob = nullptr;
3231 ob->flag |= OB_DONE;
3232
3233 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3235 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3236 geometry = *ob_eval->runtime->geometry_set_eval;
3237 }
3238
3239 if (geometry.has_grease_pencil()) {
3240 newob = get_object_for_conversion(base, info, r_new_base);
3241
3242 Curves *new_curves = BKE_id_new<Curves>(info.bmain, newob->id.name + 2);
3243 newob->data = new_curves;
3244 newob->type = OB_CURVES;
3245
3246 if (const Curves *curves_eval = geometry.get_curves()) {
3247 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3248 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3249 }
3250 else if (const GreasePencil *grease_pencil = geometry.get_grease_pencil()) {
3252 ed::greasepencil::retrieve_visible_drawings(*info.scene, *grease_pencil, false);
3253 if (drawings.size() > 0) {
3254 Array<bke::GeometrySet> geometries(drawings.size());
3255 for (const int i : drawings.index_range()) {
3256 Curves *curves_id = BKE_id_new_nomain<Curves>(nullptr);
3257 curves_id->geometry.wrap() = drawings[i].drawing.strokes();
3258 geometries[i] = bke::GeometrySet::from_curves(curves_id);
3259 }
3260 bke::GeometrySet joined_curves = geometry::join_geometries(geometries, {});
3261
3262 new_curves->geometry.wrap() = joined_curves.get_curves()->geometry.wrap();
3263 new_curves->geometry.wrap().tag_topology_changed();
3264 BKE_object_material_from_eval_data(info.bmain, newob, &joined_curves.get_curves()->id);
3265 }
3266 }
3267
3269 BKE_object_free_modifiers(newob, 0);
3270 }
3271 else {
3272 BKE_reportf(info.reports,
3274 "Object '%s' has no evaluated Curve or Grease Pencil data",
3275 ob->id.name + 2);
3276 }
3277
3278 return newob;
3279}
3280
3282{
3283 Object *newob = convert_curves_component_to_curves(base, info, r_new_base);
3284 if (newob) {
3285 return newob;
3286 }
3287 return convert_grease_pencil_component_to_curves(base, info, r_new_base);
3288}
3289
3292 Base **r_new_base)
3293{
3294 Object *ob = base.object;
3295 ob->flag |= OB_DONE;
3296 Object *newob = get_object_for_conversion(base, info, r_new_base);
3297
3298 BKE_mesh_to_pointcloud(info.bmain, info.depsgraph, info.scene, newob);
3299
3300 if (newob->type == OB_POINTCLOUD) {
3301 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3302 ED_rigidbody_object_remove(info.bmain, info.scene, newob);
3303 }
3304
3305 return newob;
3306}
3307
3308static Object *convert_mesh_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
3309{
3310 Object *ob = base.object;
3311 ob->flag |= OB_DONE;
3312 Object *newob = get_object_for_conversion(base, info, r_new_base);
3313
3314 /* make new mesh data from the original copy */
3315 /* NOTE: get the mesh from the original, not from the copy in some
3316 * cases this doesn't give correct results (when MDEF is used for eg)
3317 */
3318 const Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3319 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
3320 Mesh *new_mesh = mesh_eval ? BKE_mesh_copy_for_eval(*mesh_eval) :
3321 BKE_mesh_new_nomain(0, 0, 0, 0);
3322 BKE_object_material_from_eval_data(info.bmain, newob, &new_mesh->id);
3323 /* Anonymous attributes shouldn't be available on the applied geometry. */
3324 new_mesh->attributes_for_write().remove_anonymous();
3325 if (info.do_merge_customdata) {
3327 }
3328
3329 Mesh *ob_data_mesh = (Mesh *)newob->data;
3330
3331 if (ob_data_mesh->key) {
3332 /* NOTE(@ideasman42): Clearing the shape-key is needed when the
3333 * number of vertices remains unchanged. Otherwise using this operator
3334 * to "Apply Visual Geometry" will evaluate using the existing shape-key
3335 * which doesn't have the "evaluated" coordinates from `new_mesh`.
3336 * See #128839 for details.
3337 *
3338 * While shape-keys could be supported, this is more of a feature to consider.
3339 * As there is already a `MESH_OT_blend_from_shape` operator,
3340 * it's not clear this is especially useful or needed. */
3341 if (!CustomData_has_layer(&new_mesh->vert_data, CD_SHAPEKEY)) {
3342 id_us_min(&ob_data_mesh->key->id);
3343 ob_data_mesh->key = nullptr;
3344 }
3345 }
3346 BKE_mesh_nomain_to_mesh(new_mesh, ob_data_mesh, newob);
3347
3348 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
3349
3350 if (!info.keep_original) {
3352 }
3353
3354 return newob;
3355}
3356
3358 Object &ob_grease_pencil,
3359 const StringRefNull name,
3360 const std::optional<float4> &stroke_color,
3361 const std::optional<float4> &fill_color)
3362{
3363 int index;
3365 &bmain, &ob_grease_pencil, DATA_(name.c_str()), &index);
3366
3367 if (stroke_color.has_value()) {
3368 copy_v4_v4(ma->gp_style->stroke_rgba, stroke_color.value());
3370 }
3371
3372 if (fill_color.has_value()) {
3373 copy_v4_v4(ma->gp_style->fill_rgba, fill_color.value());
3375 }
3376
3377 SET_FLAG_FROM_TEST(ma->gp_style->flag, stroke_color.has_value(), GP_MATERIAL_STROKE_SHOW);
3378 SET_FLAG_FROM_TEST(ma->gp_style->flag, fill_color.has_value(), GP_MATERIAL_FILL_SHOW);
3379
3380 return index;
3381}
3382
3384 public:
3387 bool operator==(const FillColorRecord &other) const
3388 {
3389 return other.color == color && other.name == name;
3390 }
3392 {
3393 return hash_string(name);
3394 }
3395};
3396
3398 Object &ob_mesh, const Mesh &mesh, Array<int> &material_remap)
3399{
3400 const short num_materials = mesh.totcol;
3401 const FillColorRecord empty_fill = {float4(1.0f), DATA_("Empty Fill")};
3402
3403 /* This function will only be called when we want to create fills out of mesh faces, so always
3404 * ensure that fills would have at least one material to be assigned to. */
3405 if (num_materials == 0) {
3406 VectorSet<FillColorRecord> fill_colors;
3407 fill_colors.add(empty_fill);
3408 material_remap.reinitialize(1);
3409 material_remap[0] = 0;
3410 return fill_colors;
3411 }
3412
3413 VectorSet<FillColorRecord> fill_colors;
3414
3415 material_remap.reinitialize(num_materials);
3416
3417 for (const int material_i : IndexRange(num_materials)) {
3418 const Material *mesh_material = BKE_object_material_get(&ob_mesh, material_i + 1);
3419 if (!mesh_material) {
3420 material_remap[material_i] = fill_colors.index_of_or_add(empty_fill);
3421 continue;
3422 }
3423 const float4 fill_color = float4(
3424 mesh_material->r, mesh_material->g, mesh_material->b, mesh_material->a);
3425 const StringRefNull material_name = BKE_id_name(mesh_material->id);
3426 const FillColorRecord record = {fill_color, material_name};
3427 material_remap[material_i] = fill_colors.index_of_or_add(record);
3428 }
3429
3430 return fill_colors;
3431}
3432static void mesh_data_to_grease_pencil(const Mesh &mesh_eval,
3433 GreasePencil &grease_pencil,
3434 const int current_frame,
3435 const bool generate_faces,
3436 const float stroke_radius,
3437 const float offset,
3438 const Array<int> &material_remap)
3439{
3440 grease_pencil.flag |= GREASE_PENCIL_STROKE_ORDER_3D;
3441
3442 if (mesh_eval.edges_num <= 0) {
3443 return;
3444 }
3445
3446 bke::greasepencil::Layer &layer_line = grease_pencil.add_layer(DATA_("Lines"));
3447 bke::greasepencil::Drawing *drawing_line = grease_pencil.insert_frame(layer_line, current_frame);
3448
3449 const Span<float3> mesh_positions = mesh_eval.vert_positions();
3450 const OffsetIndices<int> faces = mesh_eval.faces();
3451 Span<int> faces_span = faces.data();
3452 const Span<int> corner_verts = mesh_eval.corner_verts();
3453
3454 if (generate_faces && !faces.is_empty()) {
3455 bke::greasepencil::Layer &layer_fill = grease_pencil.add_layer(DATA_("Fills"));
3456 bke::greasepencil::Drawing *drawing_fill = grease_pencil.insert_frame(layer_fill,
3457 current_frame);
3458 const int fills_num = faces.size();
3459 const int fills_points_num = corner_verts.size();
3460
3461 drawing_fill->strokes_for_write().resize(fills_points_num, fills_num);
3462 bke::CurvesGeometry &curves_fill = drawing_fill->strokes_for_write();
3463 MutableSpan<float3> positions_fill = curves_fill.positions_for_write();
3464 MutableSpan<int> offsets_fill = curves_fill.offsets_for_write();
3465 MutableSpan<bool> cyclic_fill = curves_fill.cyclic_for_write();
3466 bke::SpanAttributeWriter<int> stroke_materials_fill =
3468 "material_index", bke::AttrDomain::Curve);
3469 bke::AttributeAccessor mesh_attributes = mesh_eval.attributes();
3470 VArray<int> mesh_materials = *mesh_attributes.lookup_or_default(
3471 "material_index", bke::AttrDomain::Face, 0);
3472
3473 curves_fill.fill_curve_types(CURVE_TYPE_POLY);
3474 array_utils::gather(mesh_positions, corner_verts, positions_fill);
3475 array_utils::copy(faces_span, offsets_fill);
3476 cyclic_fill.fill(true);
3477
3478 MutableSpan<int> material_span = stroke_materials_fill.span;
3479 for (const int face_i : material_span.index_range()) {
3480 /* Increase material index by 1 to accommodate the stroke material. */
3481 material_span[face_i] = material_remap[mesh_materials[face_i]] + 1;
3482 }
3483 stroke_materials_fill.finish();
3484 }
3485
3486 Mesh *mesh_copied = BKE_mesh_copy_for_eval(mesh_eval);
3487 const Span<float3> normals = mesh_copied->vert_normals();
3488
3489 std::string unique_attribute_id = BKE_attribute_calc_unique_name(
3490 AttributeOwner::from_id(&mesh_copied->id), "vertex_normal_for_conversion");
3491
3492 mesh_copied->attributes_for_write().add(
3493 unique_attribute_id,
3497
3498 const int edges_num = mesh_copied->edges_num;
3500 *mesh_copied, IndexRange(edges_num), {});
3501
3502 MutableSpan<float3> curve_positions = curves.positions_for_write();
3503 const VArraySpan<float3> point_normals = *curves.attributes().lookup<float3>(
3504 unique_attribute_id);
3505
3506 threading::parallel_for(curve_positions.index_range(), 8192, [&](const IndexRange range) {
3507 for (const int point_i : range) {
3508 curve_positions[point_i] += offset * point_normals[point_i];
3509 }
3510 });
3511
3512 BKE_defgroup_copy_list(&grease_pencil.vertex_group_names, &mesh_copied->vertex_group_names);
3513
3514 curves.radius_for_write().fill(stroke_radius);
3515
3516 drawing_line->strokes_for_write() = std::move(curves);
3517 drawing_line->tag_topology_changed();
3518
3519 BKE_id_free(nullptr, mesh_copied);
3520}
3521
3524 Base **r_new_base)
3525{
3526 Object *ob = base.object;
3527 ob->flag |= OB_DONE;
3528 Object *newob = get_object_for_conversion(base, info, r_new_base);
3529
3530 const bool generate_faces = RNA_boolean_get(info.op_props, "faces");
3531 const int thickness = RNA_int_get(info.op_props, "thickness");
3532 const float offset = RNA_float_get(info.op_props, "offset");
3533
3534 /* To be compatible with the thickness value of legacy Grease Pencil. */
3535 const float stroke_radius = float(thickness) / 2 *
3537
3538 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3539 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
3540
3541 VectorSet<FillColorRecord> fill_colors;
3542 Array<int> material_remap;
3543 if (generate_faces) {
3544 fill_colors = mesh_to_grease_pencil_get_material_list(*ob_eval, *mesh_eval, material_remap);
3545 }
3546
3548 BKE_object_free_modifiers(newob, 0);
3549
3550 GreasePencil *grease_pencil = BKE_grease_pencil_add(info.bmain, BKE_id_name(mesh_eval->id));
3551 newob->data = grease_pencil;
3552 newob->type = OB_GREASE_PENCIL;
3553
3554 /* Reset object material array and count since currently the generic / grease pencil material
3555 * functions still depend on this value being coherent (The same value as
3556 * `GreasePencil::material_array_num`).
3557 */
3558 BKE_object_material_resize(info.bmain, newob, 0, true);
3559
3561 *info.bmain, *newob, DATA_("Stroke"), float4(0.0f, 0.0f, 0.0f, 1.0f), {});
3562
3563 if (generate_faces) {
3564 for (const int fill_i : fill_colors.index_range()) {
3565 const FillColorRecord &record = fill_colors[fill_i];
3566 mesh_to_grease_pencil_add_material(*info.bmain, *newob, record.name, {}, record.color);
3567 }
3568 }
3569
3570 mesh_data_to_grease_pencil(*mesh_eval,
3571 *grease_pencil,
3572 info.scene->r.cfra,
3573 generate_faces,
3574 stroke_radius,
3575 offset,
3576 material_remap);
3577
3578 return newob;
3579}
3580
3582 const ObjectType target,
3584 Base **r_new_base)
3585{
3586 switch (target) {
3587 case OB_CURVES_LEGACY:
3588 return convert_mesh_to_curves_legacy(base, info, r_new_base);
3589 case OB_CURVES:
3590 return convert_mesh_to_curves(base, info, r_new_base);
3591 case OB_POINTCLOUD:
3592 return convert_mesh_to_pointcloud(base, info, r_new_base);
3593 case OB_MESH:
3594 return convert_mesh_to_mesh(base, info, r_new_base);
3595 case OB_GREASE_PENCIL:
3596 return convert_mesh_to_grease_pencil(base, info, r_new_base);
3597 default:
3598 /* Current logic does convert mesh to mesh for any other target types. This would change
3599 * after other types of conversion are designed and implemented. */
3600 return convert_mesh_to_mesh(base, info, r_new_base);
3601 }
3602}
3603
3605{
3606 Object *ob = base.object, *newob = nullptr;
3607 ob->flag |= OB_DONE;
3608
3609 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3611 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3612 geometry = *ob_eval->runtime->geometry_set_eval;
3613 }
3614
3615 const Mesh *mesh_eval = geometry.get_mesh();
3616 const Curves *curves_eval = geometry.get_curves();
3617 Mesh *new_mesh = nullptr;
3618
3619 if (mesh_eval || curves_eval) {
3620 newob = get_object_for_conversion(base, info, r_new_base);
3621 new_mesh = BKE_id_new<Mesh>(info.bmain, newob->id.name + 2);
3622 newob->data = new_mesh;
3623 newob->type = OB_MESH;
3624 }
3625 else {
3626 BKE_reportf(info.reports,
3628 "Object '%s' has no evaluated mesh or curves data",
3629 ob->id.name + 2);
3630 return nullptr;
3631 }
3632
3633 if (mesh_eval) {
3634 BKE_mesh_nomain_to_mesh(BKE_mesh_copy_for_eval(*mesh_eval), new_mesh, newob);
3635 BKE_object_material_from_eval_data(info.bmain, newob, &mesh_eval->id);
3636 new_mesh->attributes_for_write().remove_anonymous();
3637 }
3638 else if (curves_eval) {
3639 Mesh *mesh = bke::curve_to_wire_mesh(curves_eval->geometry.wrap(),
3641 if (!mesh) {
3642 mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
3643 }
3644 BKE_mesh_nomain_to_mesh(mesh, new_mesh, newob);
3645 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3646 }
3647
3649 BKE_object_free_modifiers(newob, 0);
3650
3651 return newob;
3652}
3653
3656 Base **r_new_base)
3657{
3658 Object *ob = base.object, *newob = nullptr;
3659 ob->flag |= OB_DONE;
3660
3661 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3663 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3664 geometry = *ob_eval->runtime->geometry_set_eval;
3665 }
3666
3667 const GreasePencil *grease_pencil_eval = geometry.get_grease_pencil();
3668 const Curves *curves_eval = geometry.get_curves();
3669 GreasePencil *new_grease_pencil = nullptr;
3670
3671 if (grease_pencil_eval || curves_eval) {
3672 newob = get_object_for_conversion(base, info, r_new_base);
3673 new_grease_pencil = BKE_id_new<GreasePencil>(info.bmain, newob->id.name + 2);
3674 newob->data = new_grease_pencil;
3675 newob->type = OB_GREASE_PENCIL;
3676 }
3677 else {
3678 BKE_reportf(info.reports,
3680 "Object '%s' has no evaluated Grease Pencil or Curves data",
3681 ob->id.name + 2);
3682 return nullptr;
3683 }
3684
3685 if (grease_pencil_eval) {
3687 new_grease_pencil);
3688 BKE_object_material_from_eval_data(info.bmain, newob, &grease_pencil_eval->id);
3689 new_grease_pencil->attributes_for_write().remove_anonymous();
3690 }
3691 else if (curves_eval) {
3692 GreasePencil *grease_pencil = BKE_grease_pencil_new_nomain();
3693 /* Insert a default layer and place the drawing on frame 1. */
3694 const std::string layer_name = "Layer";
3695 const int frame_number = 1;
3696 bke::greasepencil::Layer &layer = grease_pencil->add_layer(layer_name);
3697 bke::greasepencil::Drawing *drawing = grease_pencil->insert_frame(layer, frame_number);
3698 BLI_assert(drawing != nullptr);
3699 drawing->strokes_for_write() = curves_eval->geometry.wrap();
3700 /* Default radius (1.0 unit) is too thick for converted strokes. */
3701 drawing->radii_for_write().fill(0.01f);
3702
3703 BKE_grease_pencil_nomain_to_grease_pencil(grease_pencil, new_grease_pencil);
3704 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3705 }
3706
3708 BKE_object_free_modifiers(newob, 0);
3709
3710 return newob;
3711}
3712
3714 const ObjectType target,
3716 Base **r_new_base)
3717{
3718 switch (target) {
3719 case OB_MESH:
3720 return convert_curves_to_mesh(base, info, r_new_base);
3721 case OB_GREASE_PENCIL:
3722 return convert_curves_to_grease_pencil(base, info, r_new_base);
3723 default:
3724 return convert_curves_component_to_curves(base, info, r_new_base);
3725 }
3726}
3727
3730 Base **r_new_base)
3731{
3732 Object *ob = base.object, *newob = nullptr;
3733 ob->flag |= OB_DONE;
3734
3735 /* Mostly same as converting to OB_CURVES, the mesh will be converted from Curves afterwards. */
3736
3737 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3739 if (ob_eval->runtime->geometry_set_eval != nullptr) {
3740 geometry = *ob_eval->runtime->geometry_set_eval;
3741 }
3742
3743 if (geometry.has_curves()) {
3744 newob = get_object_for_conversion(base, info, r_new_base);
3745
3746 const Curves *curves_eval = geometry.get_curves();
3747 Curves *new_curves = BKE_id_new<Curves>(info.bmain, newob->id.name + 2);
3748
3749 newob->data = new_curves;
3750 newob->type = OB_CURVES;
3751
3752 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3753 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3754
3756 BKE_object_free_modifiers(newob, 0);
3757 }
3758 else if (geometry.has_grease_pencil()) {
3759 newob = get_object_for_conversion(base, info, r_new_base);
3760
3761 /* Do not link `new_curves` to `bmain` since it's temporary. */
3762 Curves *new_curves = BKE_id_new_nomain<Curves>(newob->id.name + 2);
3763
3764 newob->data = new_curves;
3765 newob->type = OB_CURVES;
3766
3767 if (const Curves *curves_eval = geometry.get_curves()) {
3768 new_curves->geometry.wrap() = curves_eval->geometry.wrap();
3769 BKE_object_material_from_eval_data(info.bmain, newob, &curves_eval->id);
3770 }
3771 else if (const GreasePencil *grease_pencil = geometry.get_grease_pencil()) {
3773 ed::greasepencil::retrieve_visible_drawings(*info.scene, *grease_pencil, false);
3774 Array<bke::GeometrySet> geometries(drawings.size());
3775 for (const int i : drawings.index_range()) {
3776 Curves *curves_id = BKE_id_new_nomain<Curves>(nullptr);
3777 curves_id->geometry.wrap() = drawings[i].drawing.strokes();
3778 const int layer_index = drawings[i].layer_index;
3779 const bke::greasepencil::Layer *layer = grease_pencil->layers()[layer_index];
3780 blender::float4x4 to_object = layer->to_object_space(*ob);
3781 bke::CurvesGeometry &new_curves = curves_id->geometry.wrap();
3782 math::transform_points(to_object, new_curves.positions_for_write());
3783 geometries[i] = bke::GeometrySet::from_curves(curves_id);
3784 }
3785 if (geometries.size() > 0) {
3786 bke::GeometrySet joined_curves = geometry::join_geometries(geometries, {});
3787
3788 new_curves->geometry.wrap() = joined_curves.get_curves()->geometry.wrap();
3789 new_curves->geometry.wrap().tag_topology_changed();
3790 BKE_object_material_from_eval_data(info.bmain, newob, &joined_curves.get_curves()->id);
3791 }
3792 }
3793
3794 Mesh *new_mesh = BKE_id_new<Mesh>(info.bmain, newob->id.name + 2);
3795 newob->data = new_mesh;
3796 newob->type = OB_MESH;
3797
3798 Mesh *mesh = bke::curve_to_wire_mesh(new_curves->geometry.wrap(), {});
3799 if (!mesh) {
3800 mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
3801 }
3802 BKE_mesh_nomain_to_mesh(mesh, new_mesh, newob);
3803 BKE_object_material_from_eval_data(info.bmain, newob, &new_curves->id);
3804
3805 /* Free `new_curves` because it is just an intermediate. */
3806 BKE_id_free(nullptr, new_curves);
3807
3809 BKE_object_free_modifiers(newob, 0);
3810 }
3811 else {
3813 info.reports, RPT_WARNING, "Object '%s' has no evaluated curves data", ob->id.name + 2);
3814 }
3815
3816 return newob;
3817}
3818
3820 const ObjectType target,
3822 Base **r_new_base)
3823{
3824 switch (target) {
3825 case OB_CURVES:
3826 return convert_grease_pencil_component_to_curves(base, info, r_new_base);
3827 case OB_MESH:
3828 return convert_grease_pencil_to_mesh(base, info, r_new_base);
3829 default:
3830 return nullptr;
3831 }
3832 return nullptr;
3833}
3834
3836 Object *newob,
3838{
3839 Curve *cu = static_cast<Curve *>(newob->data);
3840
3841 Object *ob_eval = DEG_get_evaluated(info.depsgraph, ob);
3842 BKE_vfont_to_curve_ex(ob_eval,
3843 *static_cast<const Curve *>(ob_eval->data),
3844 FO_EDIT,
3845 &cu->nurb,
3846 nullptr,
3847 nullptr,
3848 nullptr,
3849 nullptr,
3850 nullptr);
3851
3852 newob->type = OB_CURVES_LEGACY;
3854
3855#define CURVE_VFONT_CLEAR(vfont_member) \
3856 if (cu->vfont_member) { \
3857 id_us_min(&cu->vfont_member->id); \
3858 cu->vfont_member = nullptr; \
3859 } \
3860 ((void)0)
3861
3862 CURVE_VFONT_CLEAR(vfont);
3863 CURVE_VFONT_CLEAR(vfontb);
3864 CURVE_VFONT_CLEAR(vfonti);
3865 CURVE_VFONT_CLEAR(vfontbi);
3866
3867#undef CURVE_VFONT_CLEAR
3868
3869 if (!info.keep_original) {
3870 /* other users */
3871 Object *ob1 = nullptr;
3872 if (ID_REAL_USERS(&cu->id) > 1) {
3873 for (ob1 = static_cast<Object *>(info.bmain->objects.first); ob1;
3874 ob1 = static_cast<Object *>(ob1->id.next))
3875 {
3876 if (ob1->data == ob->data && ob1 != ob) {
3877 ob1->type = OB_CURVES_LEGACY;
3878 DEG_id_tag_update(&ob1->id,
3880 }
3881 }
3882 }
3883 }
3884
3885 LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
3886 nu->charidx = 0;
3887 }
3888
3889 cu->flag &= ~CU_3D;
3891
3892 return newob;
3893}
3894
3897 Base **r_new_base)
3898{
3899 Object *ob = base.object;
3900 ob->flag |= OB_DONE;
3901 Object *newob = get_object_for_conversion(base, info, r_new_base);
3902
3903 return convert_font_to_curve_legacy_generic(ob, newob, info);
3904}
3905
3907{
3908 Object *ob = base.object;
3909 ob->flag |= OB_DONE;
3910 Object *newob = get_object_for_conversion(base, info, r_new_base);
3911 Object *curve_ob = convert_font_to_curve_legacy_generic(ob, newob, info);
3912 BLI_assert(curve_ob->type == OB_CURVES_LEGACY);
3913
3914 Curve *legacy_curve_id = static_cast<Curve *>(curve_ob->data);
3915 Curves *curves_nomain = bke::curve_legacy_to_curves(*legacy_curve_id);
3916
3917 Curves *curves_id = BKE_curves_add(info.bmain, BKE_id_name(legacy_curve_id->id));
3918 curves_id->geometry.wrap() = curves_nomain->geometry.wrap();
3919
3920 blender::bke::curves_copy_parameters(*curves_nomain, *curves_id);
3921
3922 curve_ob->data = curves_id;
3923 curve_ob->type = OB_CURVES;
3924
3925 BKE_id_free(nullptr, curves_nomain);
3926
3927 return curve_ob;
3928}
3929
3930/* Currently neither Grease Pencil nor legacy curves supports per-stroke/curve fill attribute, thus
3931 * the #fill argument applies on all strokes that are converted. */
3933 ID &from_id,
3934 Object &gp_object,
3935 const bool use_fill)
3936{
3937 short *len_p = BKE_id_material_len_p(&from_id);
3938 if (!len_p || *len_p == 0) {
3939 return;
3940 }
3941 Material ***materials = BKE_id_material_array_p(&from_id);
3942 if (!materials || !(*materials)) {
3943 return;
3944 }
3945 for (short i = 0; i < *len_p; i++) {
3946 const Material *orig_material = (*materials)[i];
3947 const char *name = orig_material ? BKE_id_name(orig_material->id) : IFACE_("Empty Material");
3948
3950 &bmain, &gp_object, name, nullptr);
3951
3952 /* If the original object has this material slot but didn't assign any material, then we don't
3953 * have anything to copy color information from. In those cases we still added an empty
3954 * material to keep the material index matching. */
3955 if (!orig_material) {
3956 continue;
3957 }
3958
3959 copy_v4_v4(gp_material->gp_style->fill_rgba, &orig_material->r);
3960
3961 SET_FLAG_FROM_TEST(gp_material->gp_style->flag, !use_fill, GP_MATERIAL_STROKE_SHOW);
3962 SET_FLAG_FROM_TEST(gp_material->gp_style->flag, use_fill, GP_MATERIAL_FILL_SHOW);
3963 }
3964}
3965
3968 Base **r_new_base)
3969{
3970 Object *ob = base.object;
3971 ob->flag |= OB_DONE;
3972 Object *newob = get_object_for_conversion(base, info, r_new_base);
3973 Object *curve_ob = convert_font_to_curve_legacy_generic(ob, newob, info);
3974 BLI_assert(curve_ob->type == OB_CURVES_LEGACY);
3975
3976 Curve *legacy_curve_id = static_cast<Curve *>(curve_ob->data);
3977 Curves *curves_nomain = bke::curve_legacy_to_curves(*legacy_curve_id);
3978
3979 GreasePencil *grease_pencil = BKE_grease_pencil_add(info.bmain,
3980 BKE_id_name(legacy_curve_id->id));
3981 bke::greasepencil::Layer &layer = grease_pencil->add_layer(DATA_("Converted Layer"));
3982
3983 const int current_frame = info.scene->r.cfra;
3984
3985 bke::greasepencil::Drawing *drawing = grease_pencil->insert_frame(layer, current_frame);
3986
3987 blender::bke::CurvesGeometry &curves = curves_nomain->geometry.wrap();
3988
3989 drawing->strokes_for_write() = std::move(curves);
3990 /* Default radius (1.0 unit) is too thick for converted strokes. */
3991 drawing->radii_for_write().fill(0.01f);
3992 drawing->tag_positions_changed();
3993
3994 curve_ob->data = grease_pencil;
3995 curve_ob->type = OB_GREASE_PENCIL;
3996 curve_ob->totcol = grease_pencil->material_array_num;
3997
3998 const bool use_fill = (legacy_curve_id->flag & (CU_FRONT | CU_BACK)) != 0;
3999 add_grease_pencil_materials_for_conversion(*info.bmain, legacy_curve_id->id, *newob, use_fill);
4000
4001 /* We don't need the intermediate font/curve data ID any more. */
4002 BKE_id_delete(info.bmain, legacy_curve_id);
4003
4004 /* For some reason this must be called, otherwise evaluated id_cow will still be the original
4005 * curves id (and that seems to only happen if "Keep Original" is enabled, and only with this
4006 * specific conversion combination), not sure why. Ref: #138793 / #146252 */
4007 DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
4008
4009 BKE_id_free(nullptr, curves_nomain);
4010
4011 return curve_ob;
4012}
4013
4014static Object *convert_font_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
4015{
4016 Object *newob = convert_font_to_curves_legacy(base, info, r_new_base);
4017
4018 /* No assumption should be made that the resulting objects is a mesh, as conversion can
4019 * fail. */
4021
4022 /* Meshes doesn't use the "curve cache". */
4024
4025 return newob;
4026}
4027
4029 const short target,
4031 Base **r_new_base)
4032{
4033 switch (target) {
4034 case OB_MESH:
4035 return convert_font_to_mesh(base, info, r_new_base);
4036 case OB_CURVES_LEGACY:
4037 return convert_font_to_curves_legacy(base, info, r_new_base);
4038 case OB_CURVES:
4039 return convert_font_to_curves(base, info, r_new_base);
4040 case OB_GREASE_PENCIL:
4041 return convert_font_to_grease_pencil(base, info, r_new_base);
4042 default:
4043 return nullptr;
4044 }
4045 return nullptr;
4046}
4047
4050 Base **r_new_base)
4051{
4052 Object *ob = base.object;
4053 ob->flag |= OB_DONE;
4054 Object *newob = get_object_for_conversion(base, info, r_new_base);
4055
4056 /* No assumption should be made that the resulting objects is a mesh, as conversion can
4057 * fail. */
4059
4060 /* Meshes doesn't use the "curve cache". */
4062
4063 return newob;
4064}
4065
4068 Base **r_new_base)
4069{
4070 Object *newob = convert_curves_component_to_curves(base, info, r_new_base);
4071 if (newob) {
4072 return newob;
4073 }
4074 return convert_grease_pencil_component_to_curves(base, info, r_new_base);
4075}
4076
4079 Base **r_new_base)
4080{
4081 Object *ob = base.object;
4082 ob->flag |= OB_DONE;
4083 Object *newob = get_object_for_conversion(base, info, r_new_base);
4084 BLI_assert(newob->type == OB_CURVES_LEGACY);
4085
4086 Curve *legacy_curve_id = static_cast<Curve *>(newob->data);
4087 Curves *curves_nomain = bke::curve_legacy_to_curves(*legacy_curve_id);
4088
4089 GreasePencil *grease_pencil = BKE_grease_pencil_add(info.bmain,
4090 BKE_id_name(legacy_curve_id->id));
4091 bke::greasepencil::Layer &layer = grease_pencil->add_layer(DATA_("Converted Layer"));
4092
4093 const int current_frame = info.scene->r.cfra;
4094
4095 bke::greasepencil::Drawing *drawing = grease_pencil->insert_frame(layer, current_frame);
4096
4097 blender::bke::CurvesGeometry &curves = curves_nomain->geometry.wrap();
4098
4099 drawing->strokes_for_write() = std::move(curves);
4100 /* Default radius (1.0 unit) is too thick for converted strokes. */
4101 drawing->radii_for_write().fill(0.01f);
4102 drawing->tag_positions_changed();
4103
4104 newob->data = grease_pencil;
4105 newob->type = OB_GREASE_PENCIL;
4106
4107 /* Some functions like #BKE_id_material_len_p still uses Object::totcol so this value must be in
4108 * sync. */
4109 newob->totcol = grease_pencil->material_array_num;
4110
4111 const bool use_fill = (legacy_curve_id->flag & (CU_FRONT | CU_BACK)) != 0;
4112 add_grease_pencil_materials_for_conversion(*info.bmain, legacy_curve_id->id, *newob, use_fill);
4113
4114 /* For some reason this must be called, otherwise evaluated id_cow will still be the original
4115 * curves id (and that seems to only happen if "Keep Original" is enabled, and only with this
4116 * specific conversion combination), not sure why. Ref: #138793 / #146252 */
4117 DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY);
4118
4119 BKE_id_free(nullptr, curves_nomain);
4120
4121 return newob;
4122}
4123
4125 const ObjectType target,
4127 Base **r_new_base)
4128{
4129 switch (target) {
4130 case OB_MESH:
4131 return convert_curves_legacy_to_mesh(base, info, r_new_base);
4132 case OB_CURVES:
4133 return convert_curves_legacy_to_curves(base, info, r_new_base);
4134 case OB_GREASE_PENCIL:
4135 return convert_curves_legacy_to_grease_pencil(base, info, r_new_base);
4136 default:
4137 return nullptr;
4138 }
4139}
4140
4143 bool &r_mball_converted,
4144 Base **r_new_base,
4145 Base **r_act_base)
4146{
4147 Object *ob = base.object;
4148 Object *newob = nullptr;
4149 Object *baseob = nullptr;
4150
4151 base.flag &= ~BASE_SELECTED;
4153
4154 baseob = BKE_mball_basis_find(info.scene, ob);
4155
4156 if (ob != baseob) {
4157 /* If mother-ball is converting it would be marked as done later. */
4158 ob->flag |= OB_DONE;
4159 }
4160
4161 if (!(baseob->flag & OB_DONE)) {
4162 *r_new_base = duplibase_for_convert(
4163 info.bmain, info.depsgraph, info.scene, info.view_layer, &base, baseob);
4164 newob = (*r_new_base)->object;
4165
4166 MetaBall *mb = static_cast<MetaBall *>(newob->data);
4167 id_us_min(&mb->id);
4168
4169 /* Find the evaluated mesh of the basis metaball object. */
4170 Object *object_eval = DEG_get_evaluated(info.depsgraph, baseob);
4171 Mesh *mesh = BKE_mesh_new_from_object_to_bmain(info.bmain, info.depsgraph, object_eval, true);
4172
4173 id_us_plus(&mesh->id);
4174 newob->data = mesh;
4175 newob->type = OB_MESH;
4176
4177 if (info.obact && (info.obact->type == OB_MBALL)) {
4178 *r_act_base = *r_new_base;
4179 }
4180
4181 baseob->flag |= OB_DONE;
4182 r_mball_converted = true;
4183 }
4184
4185 return newob;
4186}
4187
4189 const ObjectType target,
4191 bool &r_mball_converted,
4192 Base **r_new_base,
4193 Base **r_act_base)
4194{
4195 switch (target) {
4196 case OB_MESH:
4197 return convert_mball_to_mesh(base, info, r_mball_converted, r_new_base, r_act_base);
4198 default:
4199 return nullptr;
4200 }
4201}
4202
4205 Base **r_new_base)
4206{
4207 Object *ob = base.object;
4208 ob->flag |= OB_DONE;
4209 Object *newob = get_object_for_conversion(base, info, r_new_base);
4210
4211 BKE_pointcloud_to_mesh(info.bmain, info.depsgraph, info.scene, newob);
4212
4213 if (newob->type == OB_MESH) {
4214 BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
4215 ED_rigidbody_object_remove(info.bmain, info.scene, newob);
4216 }
4217
4218 return newob;
4219}
4220
4222 const ObjectType target,
4224 Base **r_new_base)
4225{
4226 switch (target) {
4227 case OB_MESH:
4228 return convert_pointcloud_to_mesh(base, info, r_new_base);
4229 default:
4230 return nullptr;
4231 }
4232}
4233
4235{
4236 Main *bmain = CTX_data_main(C);
4238 Scene *scene = CTX_data_scene(C);
4239 ViewLayer *view_layer = CTX_data_view_layer(C);
4240
4241 const short target = RNA_enum_get(op->ptr, "target");
4242 bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
4243 const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata");
4244
4245 Vector<PointerRNA> selected_editable_bases;
4246 CTX_data_selected_editable_bases(C, &selected_editable_bases);
4247
4248 /* Too expensive to detect on poll(). */
4249 if (selected_editable_bases.is_empty()) {
4250 BKE_report(op->reports, RPT_INFO, "No editable objects to convert");
4251 return OPERATOR_CANCELLED;
4252 }
4253
4254 /* Disallow conversion if any selected editable object is in Edit Mode.
4255 * This could be supported in the future, but it's a rare corner case
4256 * typically triggered only by Python scripts, see #147387. */
4257 for (const PointerRNA &ptr : selected_editable_bases) {
4258 const Object *ob = ((const Base *)ptr.data)->object;
4259 if (ob->mode & OB_MODE_EDIT) {
4260 BKE_report(
4261 op->reports, RPT_ERROR, "Cannot convert selected objects while they are in edit mode");
4262 return OPERATOR_CANCELLED;
4263 }
4264 }
4265
4266 /* don't forget multiple users! */
4267
4268 {
4269 FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
4270 ob->flag &= ~OB_DONE;
4271
4272 /* flag data that's not been edited (only needed for !keep_original) */
4273 if (ob->data) {
4274 ((ID *)ob->data)->tag |= ID_TAG_DOIT;
4275 }
4276
4277 /* possible metaball basis is not in this scene */
4278 if (ob->type == OB_MBALL && target == OB_MESH) {
4279 if (BKE_mball_is_basis(ob) == false) {
4280 Object *ob_basis;
4281 ob_basis = BKE_mball_basis_find(scene, ob);
4282 if (ob_basis) {
4283 ob_basis->flag &= ~OB_DONE;
4284 }
4285 }
4286 }
4287 }
4289 }
4290
4292 info.bmain = bmain;
4293 info.depsgraph = depsgraph;
4294 info.scene = scene;
4295 info.view_layer = view_layer;
4296 info.obact = BKE_view_layer_active_object_get(view_layer);
4297 info.keep_original = keep_original;
4298 info.do_merge_customdata = do_merge_customdata;
4299 info.op_props = op->ptr;
4300 info.reports = op->reports;
4301
4302 Base *act_base = nullptr;
4303
4304 /* Ensure we get all meshes calculated with a sufficient data-mask,
4305 * needed since re-evaluating single modifiers causes bugs if they depend
4306 * on other objects data masks too, see: #50950. */
4307 {
4308 for (const PointerRNA &ptr : selected_editable_bases) {
4309 Base *base = static_cast<Base *>(ptr.data);
4310 Object *ob = base->object;
4311
4312 /* The way object type conversion works currently (enforcing conversion of *all* objects
4313 * using converted object-data, even some un-selected/hidden/another scene ones,
4314 * sounds totally bad to me.
4315 * However, changing this is more design than bug-fix, not to mention convoluted code below,
4316 * so that will be for later.
4317 * But at the very least, do not do that with linked IDs! */
4318 if ((!BKE_id_is_editable(bmain, &ob->id) ||
4319 (ob->data && !BKE_id_is_editable(bmain, static_cast<ID *>(ob->data)))) &&
4320 !keep_original)
4321 {
4322 keep_original = true;
4323 BKE_report(op->reports,
4324 RPT_INFO,
4325 "Converting some non-editable object/object data, enforcing 'Keep Original' "
4326 "option to True");
4327 }
4328
4330 }
4331
4332 CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
4335 scene->customdata_mask = customdata_mask_prev;
4336 }
4337
4338 bool mball_converted = false;
4339 int incompatible_count = 0;
4340
4341 for (const PointerRNA &ptr : selected_editable_bases) {
4342 Object *newob = nullptr;
4343 Base *base = static_cast<Base *>(ptr.data), *new_base = nullptr;
4344 Object *ob = base->object;
4345
4346 if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
4347 if (ob->type != target) {
4348 base->flag &= ~SELECT;
4349 ob->flag &= ~SELECT;
4350 }
4351
4352 /* obdata already modified */
4353 if (!IS_TAGGED(ob->data)) {
4354 /* When 2 objects with linked data are selected, converting both
4355 * would keep modifiers on all but the converted object #26003. */
4356 if (ob->type == OB_MESH) {
4357 BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
4358 }
4359 }
4360 }
4361 else {
4362 const ObjectType target_type = ObjectType(target);
4363 switch (ob->type) {
4364 case OB_MESH:
4365 newob = convert_mesh(*base, target_type, info, &new_base);
4366 break;
4367 case OB_CURVES:
4368 newob = convert_curves(*base, target_type, info, &new_base);
4369 break;
4370 case OB_CURVES_LEGACY:
4372 case OB_SURF:
4373 newob = convert_curves_legacy(*base, target_type, info, &new_base);
4374 break;
4375 case OB_FONT:
4376 newob = convert_font(*base, target_type, info, &new_base);
4377 break;
4378 case OB_GREASE_PENCIL:
4379 newob = convert_grease_pencil(*base, target_type, info, &new_base);
4380 break;
4381 case OB_MBALL:
4382 newob = convert_mball(*base, target_type, info, mball_converted, &new_base, &act_base);
4383 break;
4384 case OB_POINTCLOUD:
4385 newob = convert_pointcloud(*base, target_type, info, &new_base);
4386 break;
4387 default:
4388 incompatible_count++;
4389 continue;
4390 }
4391 }
4392
4393 /* Ensure new object has consistent material data with its new obdata. */
4394 if (newob) {
4395 BKE_object_materials_sync_length(bmain, newob, static_cast<ID *>(newob->data));
4396 }
4397
4398 /* tag obdata if it was been changed */
4399
4400 /* If the original object is active then make this object active */
4401 if (new_base) {
4402 if (info.obact && (info.obact == ob)) {
4403 /* Store new active base to update view layer. */
4404 act_base = new_base;
4405 }
4406 new_base = nullptr;
4407 }
4408
4409 if (!keep_original && (ob->flag & OB_DONE)) {
4410 /* NOTE: Tag transform for update because object parenting to curve with path is handled
4411 * differently from all other cases. Converting curve to mesh and mesh to curve will likely
4412 * affect the way children are evaluated.
4413 * It is not enough to tag only geometry and rely on the curve parenting relations because
4414 * this relation is lost when curve is converted to mesh. */
4416 ((ID *)ob->data)->tag &= ~ID_TAG_DOIT; /* flag not to convert this datablock again */
4417 }
4418 }
4419
4420 if (!keep_original) {
4421 if (mball_converted) {
4422 /* We need to remove non-basis MBalls first, otherwise we won't be able to detect them if
4423 * their basis happens to be removed first. */
4424 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
4425 if (ob_mball->type == OB_MBALL) {
4426 Object *ob_basis = nullptr;
4427 if (!BKE_mball_is_basis(ob_mball) &&
4428 ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
4429 {
4430 base_free_and_unlink(bmain, scene, ob_mball);
4431 }
4432 }
4433 }
4435 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
4436 if (ob_mball->type == OB_MBALL) {
4437 if (ob_mball->flag & OB_DONE) {
4438 if (BKE_mball_is_basis(ob_mball)) {
4439 base_free_and_unlink(bmain, scene, ob_mball);
4440 }
4441 }
4442 }
4443 }
4445 }
4446 }
4447
4448 // XXX: editmode_enter(C, 0);
4449 // XXX: exit_editmode(C, EM_FREEDATA|); /* free data, but no undo. */
4450
4451 if (act_base) {
4452 /* active base was changed */
4453 base_activate(C, act_base);
4454 view_layer->basact = act_base;
4455 }
4456 else {
4457 BKE_view_layer_synced_ensure(scene, view_layer);
4458 if (Object *object = BKE_view_layer_active_object_get(view_layer)) {
4459 if (object->flag & OB_DONE) {
4462 }
4463 }
4464 }
4465
4466 if (incompatible_count != 0) {
4467 const char *target_type_name = "";
4468 PropertyRNA *prop = RNA_struct_find_property(op->ptr, "target");
4469 BLI_assert(prop != nullptr);
4470 RNA_property_enum_name(C, op->ptr, prop, target, &target_type_name);
4471 if (incompatible_count == selected_editable_bases.size()) {
4472 BKE_reportf(op->reports,
4473 RPT_INFO,
4474 "None of the objects are compatible with a conversion to \"%s\"",
4475 RPT_(target_type_name));
4476 }
4477 else {
4479 op->reports,
4480 RPT_INFO,
4481 "The selection included %d object type(s) which do not support conversion to \"%s\"",
4482 incompatible_count,
4483 RPT_(target_type_name));
4484 }
4485 }
4486
4492
4493 return OPERATOR_FINISHED;
4494}
4495
4496static void object_convert_ui(bContext * /*C*/, wmOperator *op)
4497{
4498 uiLayout *layout = op->layout;
4499
4500 layout->use_property_split_set(true);
4501
4502 layout->prop(op->ptr, "target", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4503 layout->prop(op->ptr, "keep_original", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4504
4505 const int target = RNA_enum_get(op->ptr, "target");
4506 if (target == OB_MESH) {
4507 layout->prop(op->ptr, "merge_customdata", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4508 }
4509 else if (target == OB_GREASE_PENCIL) {
4510 layout->prop(op->ptr, "thickness", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4511 layout->prop(op->ptr, "offset", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4512 layout->prop(op->ptr, "faces", UI_ITEM_NONE, std::nullopt, ICON_NONE);
4513 }
4514}
4515
4517{
4518 PropertyRNA *prop;
4519
4520 /* identifiers */
4521 ot->name = "Convert To";
4522 ot->description = "Convert selected objects to another type";
4523 ot->idname = "OBJECT_OT_convert";
4524
4525 /* API callbacks. */
4526 ot->invoke = WM_menu_invoke;
4527 ot->exec = object_convert_exec;
4528 ot->poll = object_convert_poll;
4529 ot->ui = object_convert_ui;
4530
4531 /* flags */
4532 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4533
4534 /* properties */
4535 ot->prop = prop = RNA_def_enum(
4536 ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
4538
4539 prop = RNA_def_boolean(ot->srna,
4540 "keep_original",
4541 false,
4542 "Keep Original",
4543 "Keep original objects instead of replacing them");
4545
4547 ot->srna,
4548 "merge_customdata",
4549 true,
4550 "Merge UVs",
4551 "Merge UV coordinates that share a vertex to account for imprecision in some modifiers");
4552
4553 RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100);
4554 RNA_def_boolean(ot->srna, "faces", true, "Export Faces", "Export faces as filled strokes");
4556 "offset",
4557 0.01f,
4558 0.0,
4560 "Stroke Offset",
4561 "Offset strokes from fill",
4562 0.0,
4563 100.00);
4564}
4565
4567
4568/* -------------------------------------------------------------------- */
4571
4573 Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new)
4574{
4575 if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
4576 BKE_collection_object_add_from(bmain, scene, base_src->object, object_new);
4577 }
4578 else {
4579 LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
4580 BKE_collection_object_add(bmain, layer_collection->collection, object_new);
4581 }
4582}
4583
4584static void object_add_sync_local_view(Base *base_src, Base *base_new)
4585{
4586 base_new->local_view_bits = base_src->local_view_bits;
4587}
4588
4589static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new)
4590{
4591 /* 1) duplis should end up in same collection as the original
4592 * 2) Rigid Body sim participants MUST always be part of a collection...
4593 */
4594 /* XXX: is 2) really a good measure here? */
4595 if (object_src->rigidbody_object || object_src->rigidbody_constraint) {
4596 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
4597 if (BKE_collection_has_object(collection, object_src)) {
4598 BKE_collection_object_add(bmain, collection, object_new);
4599 }
4600 }
4601 }
4602}
4603
4610 Object *ob,
4611 const eDupli_ID_Flags dupflag,
4612 const eLibIDDuplicateFlags duplicate_options,
4613 Object **r_ob_new)
4614{
4615 if (ob->mode & OB_MODE_POSE) {
4616 return;
4617 }
4618
4619 Object *obn = BKE_object_duplicate(bmain, ob, dupflag, duplicate_options);
4620 if (r_ob_new) {
4621 *r_ob_new = obn;
4622 }
4624}
4625
4627 Scene *scene,
4628 ViewLayer *view_layer,
4629 Object *ob,
4630 const eDupli_ID_Flags dupflag,
4631 const eLibIDDuplicateFlags duplicate_options,
4632 Object **r_ob_new)
4633{
4634 Object *object_new = nullptr;
4635 object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new);
4636 if (r_ob_new) {
4637 *r_ob_new = object_new;
4638 }
4639 if (object_new == nullptr) {
4640 return nullptr;
4641 }
4642
4643 BKE_view_layer_synced_ensure(scene, view_layer);
4644 Base *base_src = BKE_view_layer_base_find(view_layer, ob);
4645 object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new);
4646 BKE_view_layer_synced_ensure(scene, view_layer);
4647 Base *base_new = BKE_view_layer_base_find(view_layer, object_new);
4648 if (base_src && base_new) {
4649 object_add_sync_local_view(base_src, base_new);
4650 }
4651 object_add_sync_rigid_body(bmain, ob, object_new);
4652 return base_new;
4653}
4654
4656 Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag)
4657{
4658 Base *basen;
4659 Object *ob;
4660
4661 basen = object_add_duplicate_internal(bmain,
4662 scene,
4663 view_layer,
4664 base->object,
4665 dupflag,
4668 nullptr);
4669 if (basen == nullptr) {
4670 return nullptr;
4671 }
4672
4673 ob = basen->object;
4674
4675 /* Link own references to the newly duplicated data #26816.
4676 * Note that this function can be called from edit-mode code, in which case we may have to
4677 * enforce remapping obdata (by default this is forbidden in edit mode). */
4678 const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0;
4679 BKE_libblock_relink_to_newid(bmain, &ob->id, remap_flag);
4680
4681 /* Correct but the caller must do this. */
4682 // DAG_relations_tag_update(bmain);
4683
4684 if (ob->data != nullptr) {
4686 }
4687
4689
4690 return basen;
4691}
4692
4693/* contextual operator dupli */
4695{
4696 Main *bmain = CTX_data_main(C);
4697 Scene *scene = CTX_data_scene(C);
4698 ViewLayer *view_layer = CTX_data_view_layer(C);
4699 const bool linked = RNA_boolean_get(op->ptr, "linked");
4700 const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag;
4701
4702 /* We need to handle that here ourselves, because we may duplicate several objects, in which case
4703 * we also want to remap pointers between those... */
4705
4706 /* Duplicate the selected objects, remember data needed to process
4707 * after the sync. */
4708 struct DuplicateObjectLink {
4709 Base *base_src = nullptr;
4710 Object *object_new = nullptr;
4711
4712 DuplicateObjectLink(Base *base_src) : base_src(base_src) {}
4713 };
4714
4715 Vector<DuplicateObjectLink> object_base_links;
4716 CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
4717 object_base_links.append(DuplicateObjectLink(base));
4718 }
4720
4721 bool new_objects_created = false;
4722 for (DuplicateObjectLink &link : object_base_links) {
4724 link.base_src->object,
4725 dupflag,
4727 &link.object_new);
4728 if (link.object_new) {
4729 new_objects_created = true;
4730 }
4731 }
4732
4733 if (!new_objects_created) {
4734 return OPERATOR_CANCELLED;
4735 }
4736
4737 /* Sync that could tag the view_layer out of sync. */
4738 for (DuplicateObjectLink &link : object_base_links) {
4739 /* note that this is safe to do with this context iterator,
4740 * the list is made in advance */
4741 base_select(link.base_src, BA_DESELECT);
4742 if (link.object_new) {
4743 object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new);
4744 object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new);
4745 }
4746 }
4747
4748 /* Sync the view layer. Everything else should not tag the view_layer out of sync. */
4749 BKE_view_layer_synced_ensure(scene, view_layer);
4750 const Base *active_base = BKE_view_layer_active_base_get(view_layer);
4751 for (DuplicateObjectLink &link : object_base_links) {
4752 if (!link.object_new) {
4753 continue;
4754 }
4755
4756 Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new);
4757 BLI_assert(base_new);
4758 base_select(base_new, BA_SELECT);
4759 if (active_base == link.base_src) {
4760 base_activate(C, base_new);
4761 }
4762
4763 if (link.object_new->data) {
4764 DEG_id_tag_update(static_cast<ID *>(link.object_new->data), 0);
4765 }
4766
4767 object_add_sync_local_view(link.base_src, base_new);
4768 }
4769
4770 /* Note that this will also clear newid pointers and tags. */
4772
4774
4777
4780
4781 return OPERATOR_FINISHED;
4782}
4783
4785{
4786 PropertyRNA *prop;
4787
4788 /* identifiers */
4789 ot->name = "Duplicate Objects";
4790 ot->description = "Duplicate selected objects";
4791 ot->idname = "OBJECT_OT_duplicate";
4792
4793 /* API callbacks. */
4794 ot->exec = duplicate_exec;
4795 ot->poll = ED_operator_objectmode;
4796
4797 /* flags */
4798 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4799
4800 /* to give to transform */
4801 prop = RNA_def_boolean(ot->srna,
4802 "linked",
4803 false,
4804 "Linked",
4805 "Duplicate object but not object data, linking to the original data");
4807
4808 prop = RNA_def_enum(ot->srna,
4809 "mode",
4812 "Mode",
4813 "");
4815}
4816
4818
4819/* -------------------------------------------------------------------- */
4824
4826{
4827 Main *bmain = CTX_data_main(C);
4828 Scene *scene = CTX_data_scene(C);
4829 ViewLayer *view_layer = CTX_data_view_layer(C);
4830 const bool linked = RNA_boolean_get(op->ptr, "linked");
4831 const eDupli_ID_Flags dupflag = (linked) ? (eDupli_ID_Flags)0 : (eDupli_ID_Flags)U.dupflag;
4832
4833 /* Find object, create fake base. */
4834
4835 Object *ob = reinterpret_cast<Object *>(
4837
4838 if (ob == nullptr) {
4839 BKE_report(op->reports, RPT_ERROR, "Object not found");
4840 return OPERATOR_CANCELLED;
4841 }
4842
4843 /* prepare dupli */
4845 bmain,
4846 scene,
4847 view_layer,
4848 ob,
4849 dupflag,
4850 /* Sub-process flag because the new-ID remapping (#BKE_libblock_relink_to_newid()) in this
4851 * function will only work if the object is already linked in the view layer, which is not
4852 * the case here. So we have to do the new-ID relinking ourselves
4853 * (#copy_object_set_idnew()).
4854 */
4856 nullptr);
4857
4858 if (basen == nullptr) {
4859 BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
4860 return OPERATOR_CANCELLED;
4861 }
4862
4864 /* Do immediately, as #copy_object_set_idnew() below operates on visible objects. */
4865 BKE_base_eval_flags(basen);
4866
4867 /* #object_add_duplicate_internal() doesn't deselect other objects,
4868 * unlike #object_add_common() or #BKE_view_layer_base_deselect_all(). */
4869 base_deselect_all(scene, view_layer, nullptr, SEL_DESELECT);
4870 base_select(basen, BA_SELECT);
4871 base_activate(C, basen);
4872
4874
4875 /* TODO(sergey): Only update relations for the current scene. */
4877
4883
4884 PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
4885 if (RNA_property_is_set(op->ptr, prop_matrix)) {
4886 Object *ob_add = basen->object;
4888 op->ptr, prop_matrix, ob_add->runtime->object_to_world.base_ptr());
4889 BKE_object_apply_mat4(ob_add, ob_add->object_to_world().ptr(), true, true);
4890
4892 }
4893 else if (CTX_wm_region_view3d(C)) {
4894 int mval[2];
4895 if (object_add_drop_xy_get(C, op, &mval)) {
4896 location_from_view(C, basen->object->loc);
4897 ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
4898 }
4899 }
4900
4901 return OPERATOR_FINISHED;
4902}
4903
4905{
4906 /* identifiers */
4907 ot->name = "Add Object";
4908 ot->description = "Add named object";
4909 ot->idname = "OBJECT_OT_add_named";
4910
4911 /* API callbacks. */
4913 ot->exec = object_add_named_exec;
4915
4916 /* flags */
4917 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
4918
4919 PropertyRNA *prop;
4920 RNA_def_boolean(ot->srna,
4921 "linked",
4922 false,
4923 "Linked",
4924 "Duplicate object but not object data, linking to the original data");
4925
4927
4928 prop = RNA_def_float_matrix(
4929 ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
4931
4933}
4934
4936
4937/* -------------------------------------------------------------------- */
4940
4945{
4946 Main *bmain = CTX_data_main(C);
4947 const Scene *scene = CTX_data_scene(C);
4948 ViewLayer *view_layer = CTX_data_view_layer(C);
4949
4950 Object *ob = reinterpret_cast<Object *>(
4952
4953 if (!ob) {
4954 BKE_view_layer_synced_ensure(scene, view_layer);
4955 ob = BKE_view_layer_active_object_get(view_layer);
4956 }
4957
4958 if (ob == nullptr) {
4959 BKE_report(op->reports, RPT_ERROR, "Object not found");
4960 return OPERATOR_CANCELLED;
4961 }
4962
4963 /* Don't transform a linked object. There's just nothing to do here in this case, so return
4964 * #OPERATOR_FINISHED. */
4965 if (!BKE_id_is_editable(bmain, &ob->id)) {
4966 return OPERATOR_FINISHED;
4967 }
4968
4969 /* Ensure the locations are updated so snap reads the evaluated active location. */
4971
4972 PropertyRNA *prop_matrix = RNA_struct_find_property(op->ptr, "matrix");
4973 if (RNA_property_is_set(op->ptr, prop_matrix)) {
4976 view_layer, nullptr, &params);
4977
4978 float matrix[4][4];
4979 RNA_property_float_get_array(op->ptr, prop_matrix, &matrix[0][0]);
4980
4981 float mat_src_unit[4][4];
4982 float mat_dst_unit[4][4];
4983 float final_delta[4][4];
4984
4985 normalize_m4_m4(mat_src_unit, ob->object_to_world().ptr());
4986 normalize_m4_m4(mat_dst_unit, matrix);
4987 invert_m4(mat_src_unit);
4988 mul_m4_m4m4(final_delta, mat_dst_unit, mat_src_unit);
4989
4990 object_xform_array_m4(objects.data(), objects.size(), final_delta);
4991 }
4992 else if (CTX_wm_region_view3d(C)) {
4993 int mval[2];
4994 if (object_add_drop_xy_get(C, op, &mval)) {
4995 float cursor[3];
4996 location_from_view(C, cursor);
4997 ED_view3d_cursor3d_position(C, mval, false, cursor);
4998
4999 /* Use the active objects location since this is the ID which the user selected to drop.
5000 *
5001 * This transforms all selected objects, so that dropping a single object which links in
5002 * other objects will have their relative transformation preserved.
5003 * For example a child/parent relationship or other objects used with a boolean modifier.
5004 *
5005 * The caller is responsible for ensuring the selection state gives useful results.
5006 * Link/append does this using #FILE_AUTOSELECT. */
5008 }
5009 }
5010
5011 return OPERATOR_FINISHED;
5012}
5013
5015{
5016 /* identifiers */
5017 ot->name = "Place Object Under Mouse";
5018 ot->description = "Snap selected item(s) to the mouse location";
5019 ot->idname = "OBJECT_OT_transform_to_mouse";
5020
5021 /* API callbacks. */
5025
5026 /* flags */
5027 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
5028
5029 PropertyRNA *prop;
5030 prop = RNA_def_string(
5031 ot->srna,
5032 "name",
5033 nullptr,
5034 MAX_ID_NAME - 2,
5035 "Name",
5036 "Object name to place (uses the active object when this and 'session_uid' are unset)");
5038 prop = RNA_def_int(ot->srna,
5039 "session_uid",
5040 0,
5041 INT32_MIN,
5042 INT32_MAX,
5043 "Session UUID",
5044 "Session UUID of the object to place (uses the active object when this and "
5045 "'name' are unset)",
5046 INT32_MIN,
5047 INT32_MAX);
5049
5050 prop = RNA_def_float_matrix(
5051 ot->srna, "matrix", 4, 4, nullptr, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
5053
5055}
5056
5058
5059/* -------------------------------------------------------------------- */
5062
5064{
5066
5067 if (ob == nullptr || ob->data == nullptr || !ID_IS_EDITABLE(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
5069 {
5070 return false;
5071 }
5072
5073 if (ELEM(ob->type,
5074 OB_MESH,
5076 OB_SURF,
5078 OB_CURVES,
5081 {
5082 return true;
5083 }
5084 return false;
5085}
5086
5088{
5089 Main *bmain = CTX_data_main(C);
5091
5092 if (ob->mode & OB_MODE_EDIT) {
5093 BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
5094 return OPERATOR_CANCELLED;
5095 }
5097 BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
5098 return OPERATOR_CANCELLED;
5099 }
5101 BKE_reportf(op->reports,
5103 "Cannot edit object '%s' as it is used by override collections",
5104 ob->id.name + 2);
5105 return OPERATOR_CANCELLED;
5106 }
5107
5109 if (ob->type == OB_MESH) {
5111 }
5112 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
5114 }
5115 else if (ob->type == OB_ARMATURE) {
5117 }
5118 else if (ob->type == OB_POINTCLOUD) {
5120 }
5121 else if (ob->type == OB_CURVES) {
5123 }
5124 else if (ob->type == OB_GREASE_PENCIL) {
5126 }
5127
5128 if (ret & OPERATOR_FINISHED) {
5129 /* Even though internally failure to invert is accounted for with a fallback,
5130 * show a warning since the result may not be what the user expects. See #80077.
5131 *
5132 * Failure to invert the matrix is typically caused by zero scaled axes
5133 * (which can be caused by constraints, even if the input scale isn't zero).
5134 *
5135 * Internally the join functions use #invert_m4_m4_safe_ortho which creates
5136 * an inevitable matrix from one that has one or more degenerate axes.
5137 *
5138 * In most cases we don't worry about special handling for non-inevitable matrices however for
5139 * joining objects there may be flat 2D objects where it's not obvious the scale is zero.
5140 * In this case, using #invert_m4_m4_safe_ortho works as well as we can expect,
5141 * joining the contents, flattening on the axis that's zero scaled.
5142 * If the zero scale is removed, the data on this axis remains un-scaled
5143 * (something that wouldn't work for #invert_m4_m4_safe). */
5144 float imat_test[4][4];
5145 if (!invert_m4_m4(imat_test, ob->object_to_world().ptr())) {
5146 BKE_report(op->reports,
5148 "Active object final transform has one or more zero scaled axes");
5149 }
5150 }
5151
5152 return ret;
5153}
5154
5156{
5157 /* identifiers */
5158 ot->name = "Join";
5159 ot->description = "Join selected objects into active object";
5160 ot->idname = "OBJECT_OT_join";
5161
5162 /* API callbacks. */
5163 ot->exec = object_join_exec;
5164 ot->poll = object_join_poll;
5165
5166 /* flags */
5167 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
5168}
5169
5171
5172/* -------------------------------------------------------------------- */
5175
5177{
5179 if (!ob) {
5180 return false;
5181 }
5182 if (ob->type != OB_MESH) {
5183 return false;
5184 }
5185
5186 if (ob->mode & OB_MODE_EDIT) {
5187 CTX_wm_operator_poll_msg_set(C, "This operation is not supported in edit mode");
5188 return false;
5189 }
5191 CTX_wm_operator_poll_msg_set(C, "Cannot edit external library data");
5192 return false;
5193 }
5194 Main &bmain = *CTX_data_main(C);
5196 CTX_wm_operator_poll_msg_set(C, "Cannot edit object used by override collections");
5197 return false;
5198 }
5199 return true;
5200}
5201
5203{
5205 C, true, RNA_boolean_get(op->ptr, "use_mirror"), op->reports);
5206}
5207
5209{
5210 ot->name = "Join as Shapes";
5211 ot->description =
5212 "Add the vertex positions of selected objects as shape keys or update existing shape keys "
5213 "with matching names";
5214 ot->idname = "OBJECT_OT_join_shapes";
5215
5216 ot->exec = join_shapes_exec;
5218
5219 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
5220
5222 ot->srna, "use_mirror", false, "Mirror", "Mirror the new shape key values");
5224}
5225
5227{
5229 C, false, RNA_boolean_get(op->ptr, "use_mirror"), op->reports);
5230}
5231
5233{
5235 return false;
5236 }
5237
5239 const Key *key = BKE_key_from_object(ob);
5240 if (!key || BLI_listbase_is_empty(&key->block)) {
5241 return false;
5242 }
5243 return true;
5244}
5245
5247{
5248 ot->name = "Update from Objects";
5249 ot->description =
5250 "Update existing shape keys with the vertex positions of selected objects with matching "
5251 "names";
5252 ot->idname = "OBJECT_OT_update_shapes";
5253
5256
5257 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
5258
5260 ot->srna, "use_mirror", false, "Mirror", "Mirror the new shape key values");
5262}
5263
5265
5266} // 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:97
void BKE_animdata_free(ID *id, bool do_id_user)
Definition anim_data.cc:188
std::string BKE_attribute_calc_unique_name(const AttributeOwner &owner, blender::StringRef name)
Definition attribute.cc:370
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)
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.
struct Curves * BKE_curves_add(struct Main *bmain, const char *name)
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:96
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
support for deformation groups and hooks.
void BKE_defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
Definition deform.cc:73
display list (or rather multi purpose list) stuff.
blender::VectorList< DupliObject > DupliList
constexpr int MAX_DUPLI_RECUR
void object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob, blender::Set< const Object * > *include_objects, DupliList &r_duplilist)
struct PartDeflect * BKE_partdeflect_new(int type)
Definition effect.cc:71
Low-level operations for grease pencil.
Material * BKE_grease_pencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
GreasePencil * BKE_grease_pencil_add(Main *bmain, const char *name)
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)
Material * BKE_grease_pencil_object_material_ensure_by_name(Main *bmain, Object *ob, const char *name, int *r_index)
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1791
void BKE_lattice_resize(Lattice *lt, int u_new, int v_new, int w_new, Object *lt_ob)
Definition lattice.cc:272
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 BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
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:2523
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:358
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:2001
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:782
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
#define IS_TAGGED(_id)
const char * BKE_id_name(const ID &id)
void id_us_min(ID *id)
Definition lib_id.cc:366
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1201
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:1519
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1224
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:628
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:931
@ ID_REMAP_SKIP_USER_CLEAR
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
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:583
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
General operations, lookup, etc. for materials.
short * BKE_id_material_len_p(ID *id)
Material *** BKE_id_material_array_p(ID *id)
void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, const ID *data_eval)
void BKE_object_materials_sync_length(Main *bmain, Object *ob, ID *id)
void BKE_object_material_resize(Main *bmain, Object *ob, short totcol, bool do_id_user)
Material * BKE_object_material_get(Object *ob, short act)
bool BKE_mball_is_basis(const Object *ob)
Definition mball.cc:255
Object * BKE_mball_basis_find(Scene *scene, Object *ob)
Definition mball.cc:419
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, bool process_shape_keys=true)
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_mat3_to_rot(Object *ob, float r_mat[3][3], bool use_compat)
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_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)
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
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_derived_caches(Object *ob)
General operations for point clouds.
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2621
void BKE_scene_object_base_flag_sync_from_base(Base *base)
Definition scene.cc:2858
General operations for speakers.
@ FO_EDIT
Definition BKE_vfont.hh:78
bool BKE_vfont_to_curve_ex(Object *ob, const Curve &cu, eEditFontMode mode, ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, CharTrans **r_chartransdata, float *r_font_size_eval)
Volume data-block.
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ATTR_FALLTHROUGH
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.cc:686
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:752
#define BLI_ghashutil_inthash(key)
Definition BLI_ghash.h:576
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
MINLINE int max_ii(int a, int b)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
#define DEG2RADF(_deg)
#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 unit_m3(float m[3][3])
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 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 normalize_m3(float R[3][3]) ATTR_NONNULL()
void rescale_m4(float mat[4][4], const float scale[3])
void mul_m4_v3(const float M[4][4], float r[3])
void invert_m3_m3_safe_ortho(float inverse[3][3], const float mat[3][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 unit_m4(float m[4][4])
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)
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 copy_v4_v4(float r[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.cc:41
#define STR_ELEM(...)
Definition BLI_string.h:661
#define STRNCPY_UTF8(dst, src)
unsigned int uint
unsigned short ushort
#define SET_FLAG_FROM_TEST(value, test, flag)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define RPT_(msgid)
#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_relations_tag_update(Main *bmain)
void DEG_graph_tag_relations_update(Depsgraph *graph)
bool DEG_object_transform_is_evaluated(const Object &object)
T * DEG_get_original(T *id)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
#define ID_EXTRA_USERS(id)
Definition DNA_ID.h:662
@ ID_TAG_NEW
Definition DNA_ID.h:919
@ ID_TAG_INDIRECT
Definition DNA_ID.h:848
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_EDITORS
Definition DNA_ID.h:1111
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1077
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1104
#define MAX_ID_NAME
Definition DNA_ID.h:373
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_REAL_USERS(id)
Definition DNA_ID.h:676
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define ID_NEW_SET(_id, _idn)
Definition DNA_ID.h:756
ID_Type
@ ID_IM
@ ID_GR
@ ID_OB
@ ROT_MODE_EUL
Object groups, one object can be in many groups at once.
@ CU_3D
@ CU_FRONT
@ CU_PATH
@ CU_BACK
@ CU_NURBS
@ CU_PRIM_PATH
@ CD_PROP_FLOAT2
@ GP_LAYER_TREE_NODE_USE_LIGHTS
@ 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
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
@ LINEART_SOURCE_SCENE
@ LINEART_SOURCE_OBJECT
@ LINEART_SOURCE_COLLECTION
@ eModifierType_Lattice
@ eModifierType_GreasePencilLineart
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ NUM_PFIELD_TYPES
@ PFIELD_FLUIDFLOW
@ PFIELD_HARMONIC
@ PFIELD_TURBULENCE
@ PFIELD_LENNARDJ
Object is a sort of wrapper for general info.
@ OB_EMPTY_IMAGE_HIDE_BACK
@ OB_EMPTY_IMAGE_HIDE_PERSPECTIVE
@ PAROBJECT
@ GREASE_PENCIL_LINEART_SCENE
@ GP_STROKE
@ GREASE_PENCIL_LINEART_COLLECTION
@ GREASE_PENCIL_LINEART_OBJECT
@ GP_MONKEY
@ GP_EMPTY
@ OB_HIDE_VIEWPORT
@ OB_USE_GPENCIL_LIGHTS
@ OB_DRAW_IN_FRONT
@ OB_MODIFIER_FLAG_ADD_REST_POSITION
@ OB_SINGLE_ARROW
@ OB_EMPTY_IMAGE
@ 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_CURVES
@ OB_LIGHTPROBE
@ OB_DONE
@ OB_DUPLI
@ OB_DUPLICOLLECTION
@ OB_EMPTY_IMAGE_DEPTH_BACK
#define BASE_SELECTED(v3d, base)
#define BASE_SELECTED_EDITABLE(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_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
MetaElem * ED_mball_add_primitive(bContext *C, Object *obedit, bool obedit_is_new, float mat[4][4], float dia, int type)
wmOperatorStatus ED_mesh_shapes_join_objects_exec(bContext *C, bool ensure_keys_exist, bool mirror, ReportList *reports)
Definition meshtools.cc:88
#define OBJECT_ADD_SIZE_MAXF
Definition ED_object.hh:318
void ED_outliner_select_sync_from_object_tag(bContext *C)
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
bool ED_operator_objectmode(bContext *C)
bool ED_operator_scene_editable(bContext *C)
bool ED_operator_objectmode_poll_msg(bContext *C)
@ SEL_DESELECT
bool ED_view3d_snap_selected_to_location(bContext *C, wmOperator *op, const float target_loc_global[3], int pivot_point)
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])
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)
const EnumPropertyItem * RNA_collection_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:432
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_SKIP_PRESET
Definition RNA_types.hh:473
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
@ ALERT_ICON_NONE
#define UI_ITEM_NONE
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1121
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ FILE_OPENFILE
Definition WM_api.hh:1133
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DRAW
Definition WM_types.hh:461
#define ND_OB_ACTIVE
Definition WM_types.hh:440
#define ND_DATA
Definition WM_types.hh:509
#define NC_ANIMATION
Definition WM_types.hh:388
#define ND_OB_SELECT
Definition WM_types.hh:442
#define NC_SCENE
Definition WM_types.hh:378
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_LAYER_CONTENT
Definition WM_types.hh:453
#define ND_MODIFIER
Definition WM_types.hh:462
#define ND_PARENT
Definition WM_types.hh:467
#define ND_NLA
Definition WM_types.hh:497
#define NC_OBJECT
Definition WM_types.hh:379
EditBone * ED_armature_ebone_add_primitive(Object *obedit_arm, const float length, const bool view_aligned)
wmOperatorStatus ED_armature_join_objects_exec(bContext *C, wmOperator *op)
#define U
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static AttributeOwner from_id(ID *id)
Definition attribute.cc:44
AttributeSet attributes
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
int64_t size() const
Definition BLI_array.hh:256
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
constexpr void fill(const T &value) const
Definition BLI_span.hh:517
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr int64_t size() const
Definition BLI_span.hh:252
static VArray from_span(Span< T > values)
bool add(const Key &key)
int64_t index_of_or_add(const Key &key)
IndexRange index_range() const
int64_t size() const
void append(const T &value)
bool is_empty() const
IndexRange index_range() const
MutableSpan< float3 > positions_for_write()
MutableAttributeAccessor attributes_for_write()
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
MutableSpan< bool > cyclic_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
MutableSpan< float > radii_for_write()
bke::CurvesGeometry & strokes_for_write()
float4x4 to_object_space(const Object &object) const
bool operator==(const FillColorRecord &other) const
nullptr float
#define SELECT
static wmOperatorStatus duplicate_exec(bContext *C, wmOperator *op)
wmOperatorStatus ED_curve_join_objects_exec(bContext *C, wmOperator *op)
Nurb * ED_curve_add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob)
#define rot(x, k)
#define GS(x)
static float normals[][3]
#define INT32_MAX
#define INT32_MIN
#define printf(...)
VecBase< float, 4 > float4
wmOperatorStatus ED_grease_pencil_join_objects_exec(bContext *C, wmOperator *op)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
static char faces[256]
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
constexpr float LEGACY_RADIUS_CONVERSION_FACTOR
void curves_copy_parameters(const Curves &src, Curves &dst)
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
Mesh * curve_to_wire_mesh(const CurvesGeometry &curve, const bke::AttributeFilter &attribute_filter={})
bool object_has_geometry_set_instances(const Object &object)
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
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:64
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op)
void create_suzanne(Main &bmain, Object &object, const float4x4 &matrix, const int frame_number)
Vector< DrawingInfo > retrieve_visible_drawings(const Scene &scene, const GreasePencil &grease_pencil, const bool do_onion_skinning)
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)
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op)
Definition mesh_join.cc:486
static uint dupliobject_instancer_hash(const void *ptr)
void OBJECT_OT_metaball_add(wmOperatorType *ot)
static wmOperatorStatus collection_drop_exec(bContext *C, wmOperator *op)
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
static wmOperatorStatus duplicate_exec(bContext *C, wmOperator *op)
static void mesh_data_to_grease_pencil(const Mesh &mesh_eval, GreasePencil &grease_pencil, const int current_frame, const bool generate_faces, const float stroke_radius, const float offset, const Array< int > &material_remap)
static wmOperatorStatus object_convert_exec(bContext *C, wmOperator *op)
void add_unit_props_radius(wmOperatorType *ot)
static Object * convert_grease_pencil(Base &base, const ObjectType target, ObjectConversionInfo &info, Base **r_new_base)
static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
static int mesh_to_grease_pencil_add_material(Main &bmain, Object &ob_grease_pencil, const StringRefNull name, const std::optional< float4 > &stroke_color, const std::optional< float4 > &fill_color)
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 Object * convert_mesh_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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 Object * convert_curves_legacy_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static Object * convert_curves_legacy(Base &base, const ObjectType target, ObjectConversionInfo &info, Base **r_new_base)
static Object * convert_mesh_to_curves(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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 wmOperatorStatus effector_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_add_text_exec(bContext *C, wmOperator *op)
static Object * convert_font(Base &base, const short target, ObjectConversionInfo &info, Base **r_new_base)
static Object * convert_mesh(Base &base, const ObjectType target, ObjectConversionInfo &info, Base **r_new_base)
void OBJECT_OT_update_shapes(wmOperatorType *ot)
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 wmOperatorStatus object_pointcloud_add_exec(bContext *C, wmOperator *op)
static Object * convert_curves_legacy_to_grease_pencil(Base &base, ObjectConversionInfo &info, Base **r_new_base)
void OBJECT_OT_delete(wmOperatorType *ot)
static bool object_convert_poll(bContext *C)
void OBJECT_OT_transform_to_mouse(wmOperatorType *ot)
static Object * convert_font_to_curves(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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 Object * convert_curves_to_grease_pencil(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static VectorSet< FillColorRecord > mesh_to_grease_pencil_get_material_list(Object &ob_mesh, const Mesh &mesh, Array< int > &material_remap)
void rotation_from_view(bContext *C, float rot[3], char align_axis)
static wmOperatorStatus object_armature_add_exec(bContext *C, wmOperator *op)
void base_activate(bContext *C, Base *base)
static bool object_update_shapes_poll(bContext *C)
static const EnumPropertyItem field_type_items[]
void OBJECT_OT_collection_external_asset_drop(wmOperatorType *ot)
static bool object_can_have_lattice_modifier(const Object *ob)
void OBJECT_OT_data_instance_add(wmOperatorType *ot)
void OBJECT_OT_armature_add(wmOperatorType *ot)
void OBJECT_OT_lattice_add_to_selected(wmOperatorType *ot)
static Object * convert_mball(Base &base, const ObjectType target, ObjectConversionInfo &info, bool &r_mball_converted, Base **r_new_base, Base **r_act_base)
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 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 Object * convert_font_to_curves_legacy(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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)
static Object * convert_mesh_to_grease_pencil(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static Object * convert_grease_pencil_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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 active_shape_key_editable_poll(bContext *C)
static bool object_curves_empty_hair_add_poll(bContext *C)
static void object_convert_ui(bContext *, wmOperator *op)
static void add_grease_pencil_materials_for_conversion(Main &bmain, ID &from_id, Object &gp_object, const bool use_fill)
static void view_align_update(Main *, Scene *, PointerRNA *ptr)
static wmOperatorStatus object_delete_exec(bContext *C, wmOperator *op)
static Object * convert_grease_pencil_component_to_curves(Base &base, ObjectConversionInfo &info, Base **r_new_base)
void OBJECT_OT_pointcloud_random_add(wmOperatorType *ot)
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 wmOperatorStatus object_curves_empty_hair_add_exec(bContext *C, wmOperator *op)
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])
bool editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag)
static wmOperatorStatus object_empty_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_curves_random_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_transform_to_mouse_exec(bContext *C, wmOperator *op)
static void copy_object_set_idnew(bContext *C)
static wmOperatorStatus object_light_add_exec(bContext *C, wmOperator *op)
static Object * convert_mesh_to_curves_legacy(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static wmOperatorStatus object_join_exec(bContext *C, wmOperator *op)
void OBJECT_OT_effector_add(wmOperatorType *ot)
void OBJECT_OT_add_named(wmOperatorType *ot)
static wmOperatorStatus object_instance_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static Object * convert_mesh_to_pointcloud(Base &base, ObjectConversionInfo &info, Base **r_new_base)
Base * add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, eDupli_ID_Flags dupflag)
void OBJECT_OT_light_add(wmOperatorType *ot)
static wmOperatorStatus object_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus join_shapes_exec(bContext *C, wmOperator *op)
static EnumPropertyItem lightprobe_type_items[]
static Object * convert_pointcloud_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static wmOperatorStatus collection_instance_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_metaball_add_exec(bContext *C, wmOperator *op)
static bool object_add_to_selected_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
static wmOperatorStatus lattice_add_to_selected_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_grease_pencil_add_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_empty_image_add(wmOperatorType *ot)
static wmOperatorStatus object_speaker_add_exec(bContext *C, wmOperator *op)
static bool object_image_add_poll(bContext *C)
static wmOperatorStatus object_camera_add_exec(bContext *C, wmOperator *op)
static Object * convert_pointcloud(Base &base, const ObjectType target, ObjectConversionInfo &info, Base **r_new_base)
static wmOperatorStatus object_duplicates_make_real_exec(bContext *C, wmOperator *op)
static Object * convert_curves_legacy_to_curves(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int(*r_mval)[2])
void OBJECT_OT_empty_add(wmOperatorType *ot)
static wmOperatorStatus object_add_named_exec(bContext *C, wmOperator *op)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
static const EnumPropertyItem convert_target_items[]
static Object * convert_font_to_grease_pencil(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static Object * get_object_for_conversion(Base &base, ObjectConversionInfo &info, Base **r_new_base)
void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
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])
static wmOperatorStatus object_delete_invoke(bContext *C, wmOperator *op, const wmEvent *)
void OBJECT_OT_add(wmOperatorType *ot)
void add_generic_props(wmOperatorType *ot, bool do_editmode)
static uint dupliobject_hash(const void *ptr)
static Object * convert_mball_to_mesh(Base &base, ObjectConversionInfo &info, bool &r_mball_converted, Base **r_new_base, Base **r_act_base)
void OBJECT_OT_curves_random_add(wmOperatorType *ot)
void location_from_view(bContext *C, float loc[3])
static std::optional< Bounds< float3 > > lattice_add_to_selected_collect_targets_and_calc_bounds(bContext *C, const float orientation_matrix[3][3], Vector< Object * > &r_targets)
static wmOperatorStatus object_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus object_data_instance_add_exec(bContext *C, wmOperator *op)
static Object * convert_curves_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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)
static Object * convert_curves_component_to_curves(Base &base, ObjectConversionInfo &info, Base **r_new_base)
static Object * convert_curves(Base &base, const ObjectType target, ObjectConversionInfo &info, Base **r_new_base)
static wmOperatorStatus object_image_add_exec(bContext *C, wmOperator *op)
static Object * convert_font_to_mesh(Base &base, ObjectConversionInfo &info, Base **r_new_base)
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 wmOperatorStatus object_grease_pencil_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus lightprobe_add_exec(bContext *C, wmOperator *op)
static std::optional< CollectionAddInfo > collection_add_info_get_from_op(bContext *C, wmOperator *op)
static Object * convert_font_to_curve_legacy_generic(Object *ob, Object *newob, ObjectConversionInfo &info)
static wmOperatorStatus update_all_shape_keys_exec(bContext *C, wmOperator *op)
static wmOperatorStatus object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op)
bke::GeometrySet join_geometries(Span< bke::GeometrySet > geometries, const bke::AttributeFilter &attribute_filter, const std::optional< Span< bke::GeometryComponent::Type > > &component_types_to_join=std::nullopt, bool allow_merging_instance_references=true)
bke::CurvesGeometry mesh_edges_to_curves_convert(const Mesh &mesh, const IndexMask &selection, const bke::AttributeFilter &attribute_filter)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
void transform_points(const float4x4 &transform, MutableSpan< float3 > points, bool use_threading=true)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
uint64_t hash_string(StringRef str)
Definition BLI_hash.hh:166
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
#define hash
Definition noise_c.cc:154
#define CURVE_VFONT_CLEAR(vfont_member)
const EnumPropertyItem rna_enum_light_type_items[]
const char * name
return ret
const EnumPropertyItem rna_enum_id_type_items[]
Definition rna_ID.cc:29
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
bool RNA_struct_system_idprops_unset(PointerRNA *ptr, const char *identifier)
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)
bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_property_is_set(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)
const char * RNA_property_identifier(const PropertyRNA *prop)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
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:26
#define FLT_MAX
Definition stdcycles.h:14
ListBase nla_tracks
short flag
struct Object * object
unsigned short local_view_bits
float drawsize
EditNurb * editnurb
ListBase nurb
short ob_type
CurvesGeometry geometry
struct Object * surface
char * surface_uv_map
int persistent_id[MAX_DUPLI_RECUR]
ListBase nurbs
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
char name[258]
Definition DNA_ID.h:432
void * next
Definition DNA_ID.h:417
ListBase block
struct Collection * collection
float energy
short type
void * first
ListBase scenes
Definition BKE_main.hh:278
ListBase collections
Definition BKE_main.hh:298
ListBase objects
Definition BKE_main.hh:280
struct MaterialGPencilStyle * gp_style
int edges_num
CustomData corner_data
CustomData vert_data
struct Key * key
char name[64]
const NodeType * type
Definition graph/node.h:178
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 rot[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
struct CustomData_MeshMasks customdata_mask
struct RenderData r
View3DCursor cursor
struct Object * camera
struct Object * camera
struct View3D * localvd
short scenelock
unsigned short local_view_uid
struct Base * basact
ListBase object_bases
const c_style_mat & ptr() const
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Curves * get_curves() const
int ymin
int xmin
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
int xy[2]
Definition WM_types.hh:761
int mval[2]
Definition WM_types.hh:763
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1049
struct ReportList * reports
struct uiLayout * layout
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
void WM_operator_view3d_unit_defaults(bContext *C, wmOperator *op)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)
wmOperatorStatus 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)