Blender V4.5
object_relations.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 <cstdio>
10#include <cstdlib>
11#include <cstring>
12
13#include <fmt/format.h>
14
15#include "MEM_guardedalloc.h"
16
17#include "DNA_anim_types.h"
18#include "DNA_armature_types.h"
19#include "DNA_camera_types.h"
22#include "DNA_lattice_types.h"
23#include "DNA_material_types.h"
24#include "DNA_mesh_types.h"
25#include "DNA_object_types.h"
26#include "DNA_particle_types.h"
27#include "DNA_scene_types.h"
28#include "DNA_vfont_types.h"
29
30#include "BLI_kdtree.h"
31#include "BLI_linklist.h"
32#include "BLI_listbase.h"
33#include "BLI_math_matrix.h"
34#include "BLI_math_vector.h"
35#include "BLI_string.h"
36#include "BLI_utildefines.h"
37#include "BLI_vector_set.hh"
38
39#include "BLT_translation.hh"
40
41#include "BKE_action.hh"
42#include "BKE_anim_data.hh"
43#include "BKE_armature.hh"
44#include "BKE_collection.hh"
45#include "BKE_constraint.h"
46#include "BKE_context.hh"
47#include "BKE_curve.hh"
48#include "BKE_displist.h"
49#include "BKE_editmesh.hh"
50#include "BKE_fcurve.hh"
51#include "BKE_idtype.hh"
52#include "BKE_layer.hh"
53#include "BKE_lib_id.hh"
54#include "BKE_lib_override.hh"
55#include "BKE_lib_query.hh"
56#include "BKE_lib_remap.hh"
57#include "BKE_main.hh"
58#include "BKE_material.hh"
59#include "BKE_mesh_types.hh"
60#include "BKE_modifier.hh"
61#include "BKE_node.hh"
62#include "BKE_node_runtime.hh"
64#include "BKE_object.hh"
65#include "BKE_object_types.hh"
66#include "BKE_report.hh"
67#include "BKE_scene.hh"
68
69#include "DEG_depsgraph.hh"
72
73#include "WM_api.hh"
74#include "WM_types.hh"
75
76#include "UI_interface.hh"
77#include "UI_resources.hh"
78
79#include "RNA_access.hh"
80#include "RNA_define.hh"
81#include "RNA_enum_types.hh"
82
83#include "ED_armature.hh"
84#include "ED_curve.hh"
85#include "ED_gpencil_legacy.hh"
86#include "ED_grease_pencil.hh"
87#include "ED_mesh.hh"
88#include "ED_object.hh"
89#include "ED_screen.hh"
90#include "ED_view3d.hh"
91
92#include "ANIM_action.hh"
93#include "ANIM_animdata.hh"
94
95#include "MOD_nodes.hh"
96
97#include "object_intern.hh"
98
99namespace blender::ed::object {
100
101/* ------------------------------------------------------------------- */
104
109
111{
112 Main *bmain = CTX_data_main(C);
113 Scene *scene = CTX_data_scene(C);
114 View3D *v3d = CTX_wm_view3d(C);
116 ViewLayer *view_layer = CTX_data_view_layer(C);
117 Object *obedit = CTX_data_edit_object(C);
118 Object *par;
119
120#define INDEX_UNSET -1
121 int par1, par2, par3, par4;
122 par1 = par2 = par3 = par4 = INDEX_UNSET;
123
124 /* we need 1 to 3 selected vertices */
125
126 if (obedit->type == OB_MESH) {
127 Mesh *mesh = static_cast<Mesh *>(obedit->data);
128
129 EDBM_mesh_load(bmain, obedit);
130 EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
131
132 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
133
134 BMEditMesh *em = mesh->runtime->edit_mesh.get();
135
137
138 /* Make sure the evaluated mesh is updated.
139 *
140 * Most reliable way is to update the tagged objects, which will ensure
141 * proper copy-on-evaluation update, but also will make sure all dependent
142 * objects are also up to date. */
144
145 BMVert *eve;
146 BMIter iter;
147 int curr_index;
148 BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, curr_index) {
150 if (par1 == INDEX_UNSET) {
151 par1 = curr_index;
152 }
153 else if (par2 == INDEX_UNSET) {
154 par2 = curr_index;
155 }
156 else if (par3 == INDEX_UNSET) {
157 par3 = curr_index;
158 }
159 else if (par4 == INDEX_UNSET) {
160 par4 = curr_index;
161 }
162 else {
163 break;
164 }
165 }
166 }
167 }
168 else if (ELEM(obedit->type, OB_SURF, OB_CURVES_LEGACY)) {
169 ListBase *editnurb = object_editcurve_get(obedit);
170 int curr_index = 0;
171 for (Nurb *nu = static_cast<Nurb *>(editnurb->first); nu != nullptr; nu = nu->next) {
172 if (nu->type == CU_BEZIER) {
173 BezTriple *bezt = nu->bezt;
174 for (int nurb_index = 0; nurb_index < nu->pntsu; nurb_index++, bezt++, curr_index++) {
175 if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
176 if (par1 == INDEX_UNSET) {
177 par1 = curr_index;
178 }
179 else if (par2 == INDEX_UNSET) {
180 par2 = curr_index;
181 }
182 else if (par3 == INDEX_UNSET) {
183 par3 = curr_index;
184 }
185 else if (par4 == INDEX_UNSET) {
186 par4 = curr_index;
187 }
188 else {
189 break;
190 }
191 }
192 }
193 }
194 else {
195 BPoint *bp = nu->bp;
196 const int points_num = nu->pntsu * nu->pntsv;
197 for (int nurb_index = 0; nurb_index < points_num; nurb_index++, bp++, curr_index++) {
198 if (bp->f1 & SELECT) {
199 if (par1 == INDEX_UNSET) {
200 par1 = curr_index;
201 }
202 else if (par2 == INDEX_UNSET) {
203 par2 = curr_index;
204 }
205 else if (par3 == INDEX_UNSET) {
206 par3 = curr_index;
207 }
208 else if (par4 == INDEX_UNSET) {
209 par4 = curr_index;
210 }
211 else {
212 break;
213 }
214 }
215 }
216 }
217 }
218 }
219 else if (obedit->type == OB_LATTICE) {
220 Lattice *lt = static_cast<Lattice *>(obedit->data);
221
222 const int points_num = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv *
223 lt->editlatt->latt->pntsw;
224 BPoint *bp = lt->editlatt->latt->def;
225 for (int curr_index = 0; curr_index < points_num; curr_index++, bp++) {
226 if (bp->f1 & SELECT) {
227 if (par1 == INDEX_UNSET) {
228 par1 = curr_index;
229 }
230 else if (par2 == INDEX_UNSET) {
231 par2 = curr_index;
232 }
233 else if (par3 == INDEX_UNSET) {
234 par3 = curr_index;
235 }
236 else if (par4 == INDEX_UNSET) {
237 par4 = curr_index;
238 }
239 else {
240 break;
241 }
242 }
243 }
244 }
245
246 if (par4 != INDEX_UNSET || par1 == INDEX_UNSET || (par2 != INDEX_UNSET && par3 == INDEX_UNSET)) {
247 BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
248 return OPERATOR_CANCELLED;
249 }
250
251 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
252 if (ob != obedit) {
254 par = obedit->parent;
255
256 if (BKE_object_parent_loop_check(par, ob)) {
257 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
258 }
259 else {
260 BKE_view_layer_synced_ensure(scene, view_layer);
261 ob->parent = BKE_view_layer_active_object_get(view_layer);
262 if (par3 != INDEX_UNSET) {
263 ob->partype = PARVERT3;
264 ob->par1 = par1;
265 ob->par2 = par2;
266 ob->par3 = par3;
267
268 /* inverse parent matrix */
269 invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
270 }
271 else {
272 ob->partype = PARVERT1;
273 ob->par1 = par1;
274
275 /* inverse parent matrix */
276 invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
277 }
278 }
279 }
280 }
282
284
286
287 return OPERATOR_FINISHED;
288
289#undef INDEX_UNSET
290}
291
293{
294 /* identifiers */
295 ot->name = "Make Vertex Parent";
296 ot->description = "Parent selected objects to the selected vertices";
297 ot->idname = "OBJECT_OT_vertex_parent_set";
298
299 /* API callbacks. */
302
303 /* flags */
305}
306
308
309/* ------------------------------------------------------------------- */
312
315 "CLEAR",
316 0,
317 "Clear Parent",
318 "Completely clear the parenting relationship, including involved modifiers if any"},
320 "CLEAR_KEEP_TRANSFORM",
321 0,
322 "Clear and Keep Transformation",
323 "As 'Clear Parent', but keep the current visual transformations of the object"},
325 "CLEAR_INVERSE",
326 0,
327 "Clear Parent Inverse",
328 "Reset the transform corrections applied to the parenting relationship, does not remove "
329 "parenting itself"},
330 {0, nullptr, 0, nullptr, nullptr},
331};
332
333/* Helper for parent_clear() - Remove deform-modifiers associated with parent */
335{
337 ModifierData *md, *mdn;
338
339 /* assume that we only need to remove the first instance of matching deform modifier here */
340 for (md = static_cast<ModifierData *>(ob->modifiers.first); md; md = mdn) {
341 bool free = false;
342
343 mdn = md->next;
344
345 /* need to match types (modifier + parent) and references */
346 if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
348 if (amd->object == par) {
349 free = true;
350 }
351 }
352 else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
354 if (lmd->object == par) {
355 free = true;
356 }
357 }
358 else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVES_LEGACY)) {
360 if (cmd->object == par) {
361 free = true;
362 }
363 }
364
365 /* free modifier if match */
366 if (free) {
369 }
370 }
371 }
372}
373
374static void parent_clear_data(Object *ob)
375{
376 ob->parent = nullptr;
377 /* Set parent type to default PAROBJECT and reset enum explicitly, to prevent rna enum errors
378 * later. */
379 ob->partype = PAROBJECT;
380 ob->parsubstr[0] = '\0';
381}
382
383void parent_clear(Object *ob, const int type)
384{
385 if (ob->parent == nullptr) {
386 return;
387 }
389 switch (type) {
390 case CLEAR_PARENT_ALL: {
391 /* for deformers, remove corresponding modifiers to prevent
392 * a large number of modifiers building up */
394
395 /* clear parenting relationship completely */
397 break;
398 }
400 /* remove parent, and apply the parented transform
401 * result as object's local transforms */
403 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, false);
404 /* Don't recalculate the animation because it would change the transform
405 * instead of keeping it. */
406 flags &= ~ID_RECALC_ANIMATION;
407 break;
408 }
410 /* object stays parented, but the parent inverse
411 * (i.e. offset from parent to retain binding state)
412 * is cleared. In other words: nothing to do here! */
413 break;
414 }
415 }
416
417 /* Always clear parentinv matrix for sake of consistency, see #41950. */
418 unit_m4(ob->parentinv);
419
420 DEG_id_tag_update(&ob->id, flags);
421}
422
423/* NOTE: poll should check for editable scene. */
425{
426 Main *bmain = CTX_data_main(C);
427 /* Dependency graph must be evaluated for access to object's evaluated transform matrices. */
429 const int type = RNA_enum_get(op->ptr, "type");
430
431 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
432 parent_clear(ob, type);
433 }
435
439 return OPERATOR_FINISHED;
440}
441
443{
444 /* identifiers */
445 ot->name = "Clear Parent";
446 ot->description = "Clear the object's parenting";
447 ot->idname = "OBJECT_OT_parent_clear";
448
449 /* API callbacks. */
450 ot->invoke = WM_menu_invoke;
451 ot->exec = parent_clear_exec;
452
453 /* flags */
455
456 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
457}
458
460
461/* ------------------------------------------------------------------- */
464
465void parent_set(Object *ob, Object *par, const int type, const char *substr)
466{
467 /* Always clear parentinv matrix for sake of consistency, see #41950. */
468 unit_m4(ob->parentinv);
469
470 if (!par || BKE_object_parent_loop_check(par, ob)) {
472 return;
473 }
474
475 /* Other partypes are deprecated, do not use here! */
477
478 /* this could use some more checks */
479
480 ob->parent = par;
481 ob->partype &= ~PARTYPE;
482 ob->partype |= type;
483 STRNCPY(ob->parsubstr, substr);
484}
485
487 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
488 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
489 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
490 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
491 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
492 {PAR_BONE, "BONE", 0, "Bone", ""},
493 {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
494 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
495 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
496 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
497 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
498 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
499 {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
500 {0, nullptr, 0, nullptr, nullptr},
501};
502
504 const bContext *C,
505 Scene *scene,
506 Depsgraph *depsgraph,
507 Object *const ob,
508 Object *const par,
509 Object *const parent_eval,
510 int partype,
511 const bool xmirror,
512 const bool keep_transform,
513 const int vert_par[3])
514{
515 Main *bmain = CTX_data_main(C);
516 bPoseChannel *pchan = nullptr;
517 bPoseChannel *pchan_eval = nullptr;
518
519 /* Preconditions. */
520 if (ob == par) {
521 /* Parenting an object to itself is impossible. */
522 return false;
523 }
524
525 if (BKE_object_parent_loop_check(par, ob)) {
526 BKE_report(reports, RPT_ERROR, "Loop in parents");
527 return false;
528 }
529
530 switch (partype) {
531 case PAR_FOLLOW:
532 case PAR_PATH_CONST: {
533 if (par->type != OB_CURVES_LEGACY) {
534 return false;
535 }
536 Curve *cu = static_cast<Curve *>(par->data);
537 Curve *cu_eval = static_cast<Curve *>(parent_eval->data);
538 if ((cu->flag & CU_PATH) == 0) {
539 cu->flag |= CU_PATH | CU_FOLLOW;
540 cu_eval->flag |= CU_PATH | CU_FOLLOW;
541 /* force creation of path data */
542 BKE_displist_make_curveTypes(depsgraph, scene, par, false);
543 }
544 else {
545 cu->flag |= CU_FOLLOW;
546 cu_eval->flag |= CU_FOLLOW;
547 }
548
549 /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
550 if (partype == PAR_FOLLOW) {
551 /* get or create F-Curve */
552 bAction *act = animrig::id_action_ensure(bmain, &cu->id);
553 PointerRNA id_ptr = RNA_id_pointer_create(&cu->id);
555 bmain, act, nullptr, &id_ptr, {"eval_time", 0});
556
557 /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
558 if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
560 }
561 }
562
563 /* fall back on regular parenting now (for follow only) */
564 if (partype == PAR_FOLLOW) {
565 partype = PAR_OBJECT;
566 }
567 break;
568 }
569 case PAR_BONE:
572 pchan_eval = BKE_pose_channel_active_if_bonecoll_visible(parent_eval);
573
574 if (pchan == nullptr || pchan_eval == nullptr) {
575 /* If pchan_eval is nullptr, pchan should also be nullptr. */
576 BLI_assert_msg(pchan == nullptr, "Missing evaluated bone data");
577 BKE_report(reports, RPT_ERROR, "No active bone");
578 return false;
579 }
580 }
581
582 /* Apply transformation of previous parenting. */
583 if (keep_transform) {
584 /* Was removed because of bug #23577, * but this can be handy in some cases too #32616, so
585 * make optional. */
586 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), false, false);
587 }
588
589 /* Set the parent (except for follow-path constraint option). */
590 if (partype != PAR_PATH_CONST) {
591 ob->parent = par;
592 /* Always clear parentinv matrix for sake of consistency, see #41950. */
593 unit_m4(ob->parentinv);
594 }
595
596 /* Handle types. */
597 if (pchan) {
598 STRNCPY(ob->parsubstr, pchan->name);
599 }
600 else {
601 ob->parsubstr[0] = 0;
602 }
603
604 switch (partype) {
605 case PAR_PATH_CONST:
606 /* Don't do anything here, since this is not technically "parenting". */
607 break;
608 case PAR_CURVE:
609 case PAR_LATTICE:
610 case PAR_ARMATURE:
614 /* partype is now set to PAROBJECT so that invisible 'virtual'
615 * modifiers don't need to be created.
616 * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, * creating the
617 * virtual modifiers.
618 */
619 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
620 // ob->partype = PARSKEL; /* NOTE: DNA define, not operator property. */
621
622 /* BUT, to keep the deforms, we need a modifier, * and then we need to set the object
623 * that it uses
624 * - We need to ensure that the modifier we're adding doesn't already exist, * so we
625 * check this by assuming that the parent is selected too.
626 */
627 /* XXX currently this should only happen for meshes, curves, surfaces, * and lattices
628 * - this stuff isn't available for meta-balls yet. */
629 if (ELEM(
631 {
632 ModifierData *md;
633
634 switch (partype) {
635 case PAR_CURVE: /* curve deform */
636 if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
637 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Curve);
638 if (md) {
639 ((CurveModifierData *)md)->object = par;
640 }
641 if (par->runtime->curve_cache &&
642 par->runtime->curve_cache->anim_path_accum_length == nullptr)
643 {
645 }
646 }
647 break;
648 case PAR_LATTICE: /* lattice deform */
650 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Lattice);
651 if (md) {
652 ((LatticeModifierData *)md)->object = par;
653 }
654 }
655 break;
656 default: /* armature deform */
658 if (ob->type == OB_GREASE_PENCIL) {
659 md = modifier_add(
660 reports, bmain, scene, ob, nullptr, eModifierType_GreasePencilArmature);
661 if (md) {
662 ((GreasePencilArmatureModifierData *)md)->object = par;
663 }
664 }
665 else {
666 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Armature);
667 if (md) {
668 ((ArmatureModifierData *)md)->object = par;
669 }
670 }
671 }
672 break;
673 }
674 }
675 break;
676 case PAR_BONE:
677 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
678 if (pchan->bone) {
680 pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
681 }
682 break;
684 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
685 if (pchan->bone) {
687 pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
688 }
689 break;
690 case PAR_VERTEX:
691 ob->partype = PARVERT1;
692 ob->par1 = vert_par[0];
693 break;
694 case PAR_VERTEX_TRI:
695 ob->partype = PARVERT3;
696 copy_v3_v3_int(&ob->par1, vert_par);
697 break;
698 case PAR_OBJECT:
699 case PAR_FOLLOW:
700 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
701 break;
702 }
703
704 /* Constraint and set parent inverse. */
705 const bool is_armature_parent = ELEM(
707 if (partype == PAR_PATH_CONST) {
708 bConstraint *con;
710 float cmat[4][4], vec[3];
711
713
714 data = static_cast<bFollowPathConstraint *>(con->data);
715 data->tar = par;
716
718 depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, nullptr, cmat, scene->r.cfra);
719 sub_v3_v3v3(vec, ob->object_to_world().location(), cmat[3]);
720
721 copy_v3_v3(ob->loc, vec);
722 }
723 else if (is_armature_parent && (ob->type == OB_LATTICE) && (par->type == OB_ARMATURE) &&
724 (partype == PAR_ARMATURE_NAME))
725 {
727 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
728 }
729 else if (is_armature_parent && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
730 if (partype == PAR_ARMATURE_NAME) {
732 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
733 }
734 else if (partype == PAR_ARMATURE_ENVELOPE) {
736 reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
737 }
738 else if (partype == PAR_ARMATURE_AUTO) {
739 WM_cursor_wait(true);
741 reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
742 WM_cursor_wait(false);
743 }
744 /* Get corrected inverse. */
745 ob->partype = PAROBJECT;
746
748 }
749 else if (is_armature_parent && (ob->type == OB_GREASE_PENCIL) && (par->type == OB_ARMATURE)) {
750 if (partype == PAR_ARMATURE_NAME) {
752 }
753 else if (partype == PAR_ARMATURE_ENVELOPE) {
755 }
756 else if (partype == PAR_ARMATURE_AUTO) {
758 }
759 /* get corrected inverse */
760 ob->partype = PAROBJECT;
761
763 }
764 else {
765 /* calculate inverse parent matrix */
767 }
768
771 return true;
772}
773
775 const bContext *C,
776 Scene *scene,
777 Object *const ob,
778 Object *const par,
779 int partype,
780 const bool xmirror,
781 const bool keep_transform,
782 const int vert_par[3])
783{
785 Object *parent_eval = DEG_get_evaluated(depsgraph, par);
786
788 C,
789 scene,
790 depsgraph,
791 ob,
792 par,
793 parent_eval,
794 partype,
795 xmirror,
796 keep_transform,
797 vert_par);
798}
799
800static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
801{
802 const float *co_find = child->object_to_world().location();
803 if (is_tri) {
804 KDTreeNearest_3d nearest[3];
805 int tot;
806
807 tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
808 BLI_assert(tot == 3);
809 UNUSED_VARS(tot);
810
811 vert_par[0] = nearest[0].index;
812 vert_par[1] = nearest[1].index;
813 vert_par[2] = nearest[2].index;
814
815 BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
816 }
817 else {
818 vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, nullptr);
819 BLI_assert(vert_par[0] >= 0);
820 vert_par[1] = 0;
821 vert_par[2] = 0;
822 }
823}
824
834
836{
838 Object *parent_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
839
840 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
841 if (ob == parenting_context->par) {
842 /* parent_set() will fail (and thus return false), but this case
843 * shouldn't break this loop. It's expected that the active object is also selected. */
844 continue;
845 }
846
847 if (!parent_set_with_depsgraph(parenting_context->reports,
848 C,
849 parenting_context->scene,
850 depsgraph,
851 ob,
852 parenting_context->par,
853 parent_eval,
854 parenting_context->partype,
855 parenting_context->xmirror,
856 parenting_context->keep_transform,
857 nullptr))
858 {
859 return false;
860 }
861 }
863
864 return true;
865}
866
868 ParentingContext *parenting_context,
869 KDTree_3d *tree)
870{
871 int vert_par[3] = {0, 0, 0};
872
873 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
874 if (ob == parenting_context->par) {
875 /* parent_set() will fail (and thus return false), but this case
876 * shouldn't break this loop. It's expected that the active object is also selected. */
877 continue;
878 }
879
880 parent_set_vert_find(tree, ob, vert_par, parenting_context->is_vertex_tri);
881 if (!parent_set(parenting_context->reports,
882 C,
883 parenting_context->scene,
884 ob,
885 parenting_context->par,
886 parenting_context->partype,
887 parenting_context->xmirror,
888 parenting_context->keep_transform,
889 vert_par))
890 {
891 return false;
892 }
893 }
895 return true;
896}
897
898static bool parent_set_vertex_parent(bContext *C, ParentingContext *parenting_context)
899{
900 KDTree_3d *tree = nullptr;
901 int tree_tot;
902
904 Object *par_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
905
906 tree = BKE_object_as_kdtree(par_eval, &tree_tot);
907 BLI_assert(tree != nullptr);
908
909 if (tree_tot < (parenting_context->is_vertex_tri ? 3 : 1)) {
910 BKE_report(parenting_context->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
911 BLI_kdtree_3d_free(tree);
912 return false;
913 }
914
915 const bool ok = parent_set_vertex_parent_with_kdtree(C, parenting_context, tree);
916 BLI_kdtree_3d_free(tree);
917 return ok;
918}
919
921{
922 const int partype = RNA_enum_get(op->ptr, "type");
923 ParentingContext parenting_context{};
924 parenting_context.reports = op->reports;
925 parenting_context.scene = CTX_data_scene(C);
926 parenting_context.par = context_active_object(C);
927 parenting_context.partype = partype;
928 parenting_context.is_vertex_tri = partype == PAR_VERTEX_TRI;
929 parenting_context.xmirror = RNA_boolean_get(op->ptr, "xmirror");
930 parenting_context.keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
931
932 bool ok;
933 if (ELEM(parenting_context.partype, PAR_VERTEX, PAR_VERTEX_TRI)) {
934 ok = parent_set_vertex_parent(C, &parenting_context);
935 }
936 else {
937 ok = parent_set_nonvertex_parent(C, &parenting_context);
938 }
939 if (!ok) {
940 return OPERATOR_CANCELLED;
941 }
942
943 Main *bmain = CTX_data_main(C);
947
948 return OPERATOR_FINISHED;
949}
950
952{
953 Object *parent = context_active_object(C);
954 uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
955 uiLayout *layout = UI_popup_menu_layout(pup);
956
957 PointerRNA opptr;
958#if 0
959 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_OBJECT);
960#else
961 opptr = layout->op(ot, IFACE_("Object"), ICON_NONE, WM_OP_EXEC_DEFAULT, UI_ITEM_NONE);
962 RNA_enum_set(&opptr, "type", PAR_OBJECT);
963 RNA_boolean_set(&opptr, "keep_transform", false);
964
965 opptr = layout->op(
966 ot, IFACE_("Object (Keep Transform)"), ICON_NONE, WM_OP_EXEC_DEFAULT, UI_ITEM_NONE);
967 RNA_enum_set(&opptr, "type", PAR_OBJECT);
968 RNA_boolean_set(&opptr, "keep_transform", true);
969#endif
970
971 PointerRNA op_ptr = layout->op(
972 "OBJECT_OT_parent_no_inverse_set", IFACE_("Object (Without Inverse)"), ICON_NONE);
973 RNA_boolean_set(&op_ptr, "keep_transform", false);
974
975 op_ptr = layout->op("OBJECT_OT_parent_no_inverse_set",
976 IFACE_("Object (Keep Transform Without Inverse)"),
977 ICON_NONE);
978 RNA_boolean_set(&op_ptr, "keep_transform", true);
979
980 struct {
981 bool armature_deform, empty_groups, envelope_weights, automatic_weights, attach_surface;
982 } can_support = {false};
983
984 CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) {
985 if (child == parent) {
986 continue;
987 }
988 if (ELEM(child->type,
989 OB_MESH,
991 OB_SURF,
992 OB_FONT,
994 OB_LATTICE))
995 {
996 can_support.armature_deform = true;
997 can_support.envelope_weights = true;
998 }
999 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL, OB_LATTICE)) {
1000 can_support.empty_groups = true;
1001 }
1002 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL)) {
1003 can_support.automatic_weights = true;
1004 }
1005 if (child->type == OB_CURVES) {
1006 can_support.attach_surface = true;
1007 }
1008 }
1010
1011 if (parent->type == OB_ARMATURE) {
1012
1013 if (can_support.armature_deform) {
1014 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE);
1015 }
1016 if (can_support.empty_groups) {
1017 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_NAME);
1018 }
1019 if (can_support.envelope_weights) {
1020 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_ENVELOPE);
1021 }
1022 if (can_support.automatic_weights) {
1023 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_AUTO);
1024 }
1025 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_BONE);
1026 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_BONE_RELATIVE);
1027 }
1028 else if (parent->type == OB_CURVES_LEGACY) {
1029 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_CURVE);
1030 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_FOLLOW);
1031 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_PATH_CONST);
1032 }
1033 else if (parent->type == OB_LATTICE) {
1034 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_LATTICE);
1035 }
1036 else if (parent->type == OB_MESH) {
1037 if (can_support.attach_surface) {
1038 layout->op("CURVES_OT_surface_set", IFACE_("Object (Attach Curves to Surface)"), ICON_NONE);
1039 }
1040 }
1041
1042 /* vertex parenting */
1043 if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
1044 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_VERTEX);
1045 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_VERTEX_TRI);
1046 }
1047
1048 UI_popup_menu_end(C, pup);
1049
1050 return OPERATOR_INTERFACE;
1051}
1052
1054{
1055 if (RNA_property_is_set(op->ptr, op->type->prop)) {
1056 return parent_set_exec(C, op);
1057 }
1058 return parent_set_invoke_menu(C, op->type);
1059}
1060
1061static bool parent_set_poll_property(const bContext * /*C*/,
1062 wmOperator *op,
1063 const PropertyRNA *prop)
1064{
1065 const char *prop_id = RNA_property_identifier(prop);
1066
1067 /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
1068 if (STREQ(prop_id, "xmirror")) {
1069 const int type = RNA_enum_get(op->ptr, "type");
1071 return true;
1072 }
1073 return false;
1074 }
1075
1076 return true;
1077}
1078
1080{
1081 /* identifiers */
1082 ot->name = "Make Parent";
1083 ot->description = "Set the object's parenting";
1084 ot->idname = "OBJECT_OT_parent_set";
1085
1086 /* API callbacks. */
1087 ot->invoke = parent_set_invoke;
1088 ot->exec = parent_set_exec;
1090 ot->poll_property = parent_set_poll_property;
1091
1092 /* flags */
1093 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1094
1095 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
1097 ot->srna,
1098 "xmirror",
1099 false,
1100 "X Mirror",
1101 "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
1102 RNA_def_boolean(ot->srna,
1103 "keep_transform",
1104 false,
1105 "Keep Transform",
1106 "Apply transformation before parenting");
1107}
1108
1110
1111/* ------------------------------------------------------------------- */
1114
1116{
1117 Main *bmain = CTX_data_main(C);
1119
1120 const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
1121
1123
1124 /* context iterator */
1125 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1126 if (ob != par) {
1127 if (BKE_object_parent_loop_check(par, ob)) {
1128 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
1129 }
1130 else {
1131 /* set recalc flags */
1133
1134 /* set parenting type for object - object only... */
1135 ob->parent = par;
1136 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
1137
1138 if (keep_transform) {
1140 continue;
1141 }
1142
1143 /* clear inverse matrix and also the object location */
1144 unit_m4(ob->parentinv);
1145 memset(ob->loc, 0, sizeof(float[3]));
1146 }
1147 }
1148 }
1150
1154
1155 return OPERATOR_FINISHED;
1156}
1157
1159{
1160 /* identifiers */
1161 ot->name = "Make Parent without Inverse";
1162 ot->description = "Set the object's parenting without setting the inverse parent correction";
1163 ot->idname = "OBJECT_OT_parent_no_inverse_set";
1164
1165 /* API callbacks. */
1166 ot->exec = parent_noinv_set_exec;
1168
1169 /* flags */
1170 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1171
1172 RNA_def_boolean(ot->srna,
1173 "keep_transform",
1174 false,
1175 "Keep Transform",
1176 "Preserve the world transform throughout parenting");
1177}
1178
1180
1181/* ------------------------------------------------------------------- */
1184
1185enum {
1188};
1189
1191 {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
1193 "CLEAR_KEEP_TRANSFORM",
1194 0,
1195 "Clear and Keep Transformation (Clear Track)",
1196 ""},
1197 {0, nullptr, 0, nullptr, nullptr},
1198};
1199
1200/* NOTE: poll should check for editable scene. */
1202{
1203 Main *bmain = CTX_data_main(C);
1204 const int type = RNA_enum_get(op->ptr, "type");
1205
1206 if (CTX_data_edit_object(C)) {
1207 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
1208 return OPERATOR_CANCELLED;
1209 }
1210 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1211 bConstraint *con, *pcon;
1212
1213 /* remove track-object for old track */
1214 ob->track = nullptr;
1216
1217 /* also remove all tracking constraints */
1218 for (con = static_cast<bConstraint *>(ob->constraints.last); con; con = pcon) {
1219 pcon = con->prev;
1220 if (ELEM(con->type,
1224 {
1225 BKE_constraint_remove_ex(&ob->constraints, ob, con);
1226 }
1227 }
1228
1229 if (type == CLEAR_TRACK_KEEP_TRANSFORM) {
1230 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, true);
1231 }
1232 }
1234
1237
1238 return OPERATOR_FINISHED;
1239}
1240
1242{
1243 /* identifiers */
1244 ot->name = "Clear Track";
1245 ot->description = "Clear tracking constraint or flag from object";
1246 ot->idname = "OBJECT_OT_track_clear";
1247
1248 /* API callbacks. */
1249 ot->invoke = WM_menu_invoke;
1251
1252 ot->poll = ED_operator_objectmode;
1253
1254 /* flags */
1255 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1256
1257 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1258}
1259
1261
1262/* ------------------------------------------------------------------- */
1265
1266enum {
1270};
1271
1273 {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
1274 {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""},
1275 {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
1276 {0, nullptr, 0, nullptr, nullptr},
1277};
1278
1280{
1281 Main *bmain = CTX_data_main(C);
1282 Object *obact = context_active_object(C);
1283
1284 const int type = RNA_enum_get(op->ptr, "type");
1285
1286 switch (type) {
1288 bConstraint *con;
1290
1291 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1292 if (ob != obact) {
1294
1295 data = static_cast<bDampTrackConstraint *>(con->data);
1296 data->tar = obact;
1297 DEG_id_tag_update(&ob->id,
1299
1300 /* Light, Camera and Speaker track differently by default */
1301 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1302 data->trackflag = TRACK_nZ;
1303 }
1304 }
1305 }
1307 break;
1308 }
1309 case CREATE_TRACK_TRACKTO: {
1310 bConstraint *con;
1312
1313 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1314 if (ob != obact) {
1316
1317 data = static_cast<bTrackToConstraint *>(con->data);
1318 data->tar = obact;
1319 DEG_id_tag_update(&ob->id,
1321
1322 /* Light, Camera and Speaker track differently by default */
1323 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1324 data->reserved1 = TRACK_nZ;
1325 data->reserved2 = UP_Y;
1326 }
1327 }
1328 }
1330 break;
1331 }
1333 bConstraint *con;
1335
1336 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1337 if (ob != obact) {
1339
1340 data = static_cast<bLockTrackConstraint *>(con->data);
1341 data->tar = obact;
1342 DEG_id_tag_update(&ob->id,
1344
1345 /* Light, Camera and Speaker track differently by default */
1346 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1347 data->trackflag = TRACK_nZ;
1348 data->lockflag = LOCK_Y;
1349 }
1350 }
1351 }
1353 break;
1354 }
1355 }
1356
1359
1360 return OPERATOR_FINISHED;
1361}
1362
1364{
1365 /* identifiers */
1366 ot->name = "Make Track";
1367 ot->description = "Make the object track another object, using various methods/constraints";
1368 ot->idname = "OBJECT_OT_track_set";
1369
1370 /* API callbacks. */
1371 ot->invoke = WM_menu_invoke;
1372 ot->exec = track_set_exec;
1373
1374 ot->poll = ED_operator_objectmode;
1375
1376 /* flags */
1377 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1378
1379 /* properties */
1380 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
1381}
1382
1384
1385/* ------------------------------------------------------------------- */
1388
1389#if 0
1390static void link_to_scene(Main * /*bmain*/, ushort /*nr*/)
1391{
1392 Scene *sce = (Scene *)BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
1393 Base *base, *nbase;
1394
1395 if (sce == nullptr) {
1396 return;
1397 }
1398 if (sce->id.lib) {
1399 return;
1400 }
1401
1402 for (base = FIRSTBASE; base; base = base->next) {
1403 if (BASE_SELECTED(v3d, base)) {
1404 nbase = MEM_mallocN(sizeof(Base), "newbase");
1405 *nbase = *base;
1406 BLI_addhead(&(sce->base), nbase);
1407 id_us_plus((ID *)base->object);
1408 }
1409 }
1410}
1411#endif
1412
1414{
1415 Main *bmain = CTX_data_main(C);
1416 Scene *scene_to = static_cast<Scene *>(
1417 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
1418
1419 if (scene_to == nullptr) {
1420 BKE_report(op->reports, RPT_ERROR, "Could not find scene");
1421 return OPERATOR_CANCELLED;
1422 }
1423
1424 if (scene_to == CTX_data_scene(C)) {
1425 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
1426 return OPERATOR_CANCELLED;
1427 }
1428
1429 if (!BKE_id_is_editable(bmain, &scene_to->id)) {
1430 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
1431 return OPERATOR_CANCELLED;
1432 }
1433
1434 Collection *collection_to = scene_to->master_collection;
1435 CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
1436 BKE_collection_object_add(bmain, collection_to, base->object);
1437 }
1439
1440 DEG_id_tag_update(&collection_to->id, ID_RECALC_HIERARCHY);
1441
1443
1444 /* redraw the 3D view because the object center points are colored differently */
1446
1447 /* one day multiple scenes will be visible, then we should have some update function for them
1448 */
1449 return OPERATOR_FINISHED;
1450}
1451
1452enum {
1461};
1462
1463/* Return true if make link data is allowed, false otherwise */
1464static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
1465{
1466 switch (type) {
1467 case MAKE_LINKS_OBDATA:
1468 if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
1469 return true;
1470 }
1471 break;
1474 /* Linking non-grease-pencil materials to a grease-pencil object causes issues.
1475 * We make sure that if one of the objects is a grease-pencil object, the other must be
1476 * as well. */
1477 ((ob_src->type == OB_GREASE_PENCIL) == (ob_dst->type == OB_GREASE_PENCIL)))
1478 {
1479 return true;
1480 }
1481 break;
1483 if (ob_dst->type == OB_EMPTY) {
1484 return true;
1485 }
1486 break;
1488 case MAKE_LINKS_GROUP:
1489 return true;
1491 if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
1492 return true;
1493 }
1494 break;
1495 case MAKE_LINKS_FONTS:
1496 if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT))
1497 {
1498 return true;
1499 }
1500 break;
1502 if ((ob_src->type == OB_GREASE_PENCIL) && (ob_dst->type == OB_GREASE_PENCIL)) {
1503 return true;
1504 }
1505 break;
1506 }
1507 return false;
1508}
1509
1511{
1512 Scene *scene = CTX_data_scene(C);
1513 Main *bmain = CTX_data_main(C);
1514 const int type = RNA_enum_get(op->ptr, "type");
1515 Object *ob_src;
1516 ID *obdata_id;
1517 int a;
1518
1519 /* collection */
1520 LinkNode *ob_collections = nullptr;
1521 bool is_cycle = false;
1522 bool is_lib = false;
1523
1524 ob_src = context_active_object(C);
1525
1526 /* avoid searching all collections in source object each time */
1527 if (type == MAKE_LINKS_GROUP) {
1528 ob_collections = BKE_object_groups(bmain, scene, ob_src);
1529 }
1530
1531 CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) {
1532 Object *ob_dst = base_dst->object;
1533
1534 if (ob_src != ob_dst) {
1535 if (allow_make_links_data(type, ob_src, ob_dst)) {
1536 obdata_id = static_cast<ID *>(ob_dst->data);
1537
1538 switch (type) {
1539 case MAKE_LINKS_OBDATA: /* obdata */
1540 id_us_min(obdata_id);
1541
1542 obdata_id = static_cast<ID *>(ob_src->data);
1543 id_us_plus(obdata_id);
1544 ob_dst->data = obdata_id;
1545
1546 /* if amount of material indices changed: */
1547 BKE_object_materials_sync_length(bmain, ob_dst, static_cast<ID *>(ob_dst->data));
1548
1549 if (ob_dst->type == OB_ARMATURE) {
1550 BKE_pose_rebuild(bmain, ob_dst, static_cast<bArmature *>(ob_dst->data), true);
1551 }
1553 break;
1555 /* new approach, using functions from kernel */
1556 for (a = 0; a < ob_src->totcol; a++) {
1557 Material *ma = BKE_object_material_get(ob_src, a + 1);
1558 /* also works with `ma == nullptr` */
1559 BKE_object_material_assign(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
1560 }
1562 break;
1564 BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
1565 if (ob_dst->data && ob_src->data) {
1566 if (BKE_id_is_editable(bmain, obdata_id)) {
1567 BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
1568 }
1569 else {
1570 is_lib = true;
1571 }
1572 }
1573 DEG_id_tag_update(&ob_dst->id,
1575 break;
1576 case MAKE_LINKS_GROUP: {
1577 LinkNode *collection_node;
1578
1579 /* first clear collections */
1580 BKE_object_groups_clear(bmain, scene, ob_dst);
1581
1582 /* now add in the collections from the link nodes */
1583 for (collection_node = ob_collections; collection_node;
1584 collection_node = collection_node->next)
1585 {
1586 if (ob_dst->instance_collection != collection_node->link) {
1588 bmain, static_cast<Collection *>(collection_node->link), ob_dst);
1589 }
1590 else {
1591 is_cycle = true;
1592 }
1593 }
1594 break;
1595 }
1597 ob_dst->instance_collection = ob_src->instance_collection;
1598 if (ob_dst->instance_collection) {
1599 id_us_plus(&ob_dst->instance_collection->id);
1600 ob_dst->transflag |= OB_DUPLICOLLECTION;
1601 }
1603 break;
1605 BKE_object_link_modifiers(ob_dst, ob_src);
1606 DEG_id_tag_update(&ob_dst->id,
1608 break;
1609 case MAKE_LINKS_FONTS: {
1610 Curve *cu_src = static_cast<Curve *>(ob_src->data);
1611 Curve *cu_dst = static_cast<Curve *>(ob_dst->data);
1612
1613 if (!BKE_id_is_editable(bmain, obdata_id)) {
1614 is_lib = true;
1615 break;
1616 }
1617
1618#define CURVE_VFONT_SET(vfont_member) \
1619 { \
1620 if (cu_dst->vfont_member) { \
1621 id_us_min(&cu_dst->vfont_member->id); \
1622 } \
1623 cu_dst->vfont_member = cu_src->vfont_member; \
1624 id_us_plus((ID *)cu_dst->vfont_member); \
1625 } \
1626 ((void)0)
1627
1628 CURVE_VFONT_SET(vfont);
1629 CURVE_VFONT_SET(vfontb);
1630 CURVE_VFONT_SET(vfonti);
1631 CURVE_VFONT_SET(vfontbi);
1632
1633#undef CURVE_VFONT_SET
1634
1635 DEG_id_tag_update(&ob_dst->id,
1637 break;
1638 }
1640 shaderfx_link(ob_dst, ob_src);
1641 DEG_id_tag_update(&ob_dst->id,
1643 break;
1644 }
1645 }
1646 }
1647 }
1649
1650 if (type == MAKE_LINKS_GROUP) {
1651 if (ob_collections) {
1652 BLI_linklist_free(ob_collections, nullptr);
1653 }
1654
1655 if (is_cycle) {
1656 BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
1657 }
1658 }
1659
1660 if (is_lib) {
1661 BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
1662 }
1663
1668
1669 return OPERATOR_FINISHED;
1670}
1671
1673{
1674 PropertyRNA *prop;
1675
1676 /* identifiers */
1677 ot->name = "Link Objects to Scene";
1678 ot->description = "Link selection to another scene";
1679 ot->idname = "OBJECT_OT_make_links_scene";
1680
1681 /* API callbacks. */
1682 ot->invoke = WM_enum_search_invoke;
1683 ot->exec = make_links_scene_exec;
1684 /* better not run the poll check */
1685
1686 /* flags */
1687 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1688
1689 /* properties */
1690 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
1693 ot->prop = prop;
1694}
1695
1697{
1698 static const EnumPropertyItem make_links_items[] = {
1699 {MAKE_LINKS_OBDATA, "OBDATA", 0, "Link Object Data", "Replace assigned Object Data"},
1700 {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Link Materials", "Replace assigned Materials"},
1702 "ANIMATION",
1703 0,
1704 "Link Animation Data",
1705 "Replace assigned Animation Data"},
1706 {MAKE_LINKS_GROUP, "GROUPS", 0, "Link Collections", "Replace assigned Collections"},
1708 "DUPLICOLLECTION",
1709 0,
1710 "Link Instance Collection",
1711 "Replace assigned Collection Instance"},
1712 {MAKE_LINKS_FONTS, "FONTS", 0, "Link Fonts to Text", "Replace Text object Fonts"},
1714 {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Copy Modifiers", "Replace Modifiers"},
1716 "EFFECTS",
1717 0,
1718 "Copy Grease Pencil Effects",
1719 "Replace Grease Pencil Effects"},
1720 {0, nullptr, 0, nullptr, nullptr},
1721 };
1722
1723 /* identifiers */
1724 ot->name = "Link/Transfer Data";
1725 ot->description = "Transfer data from active object to selected objects";
1726 ot->idname = "OBJECT_OT_make_links_data";
1727
1728 /* API callbacks. */
1729 ot->exec = make_links_data_exec;
1731
1732 /* flags */
1733 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1734
1735 /* properties */
1736 ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
1737}
1738
1740
1741/* ------------------------------------------------------------------- */
1744
1746{
1747 /* NOTE: When dealing with linked data, we always make a local copy of it.
1748 * While in theory we could rather make it local when it only has one user, this is difficult
1749 * in practice with current code of this function. */
1750 return (id != nullptr && (id->us > 1 || ID_IS_LINKED(id)));
1751}
1752
1754 Collection *collection,
1755 const bool do_collection)
1756{
1757 if (do_collection) {
1758 BKE_libblock_relink_to_newid(bmain, &collection->id, 0);
1759 }
1760
1761 for (CollectionObject *cob = static_cast<CollectionObject *>(collection->gobject.first);
1762 cob != nullptr;
1763 cob = cob->next)
1764 {
1765 BKE_libblock_relink_to_newid(bmain, &cob->ob->id, 0);
1766 }
1767
1768 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
1769 libblock_relink_collection(bmain, child->collection, true);
1770 }
1771}
1772
1774 Scene *scene,
1775 Collection *collection,
1776 const int flag,
1777 const bool copy_collections,
1778 const bool is_master_collection)
1779{
1780 /* Generate new copies for objects in given collection and all its children, * and
1781 * optionally also copy collections themselves. */
1782 if (copy_collections && !is_master_collection) {
1783 Collection *collection_new = (Collection *)BKE_id_copy_ex(
1784 bmain, &collection->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
1785 id_us_min(&collection_new->id);
1786 collection = static_cast<Collection *>(ID_NEW_SET(collection, collection_new));
1787 }
1788
1789 /* We do not remap to new objects here, this is done in separate step. */
1790 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
1791 Object *ob = cob->ob;
1792 /* an object may be in more than one collection */
1793 if ((ob->id.newid == nullptr) && ((ob->flag & flag) == flag)) {
1794 if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
1795 ID_NEW_SET(
1796 ob,
1797 BKE_id_copy_ex(bmain, &ob->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS));
1798 id_us_min(ob->id.newid);
1799 }
1800 }
1801 }
1802
1803 /* Since master collection has already be duplicated as part of scene copy, * we do not
1804 * duplicate it here. However, this means its children need to be re-added manually here, *
1805 * otherwise their parent lists are empty (which will lead to crashes, see #63101). */
1806 CollectionChild *child_next, *child = static_cast<CollectionChild *>(collection->children.first);
1807 CollectionChild *orig_child_last = static_cast<CollectionChild *>(collection->children.last);
1808 for (; child != nullptr; child = child_next) {
1809 child_next = child->next;
1810 Collection *collection_child_new = single_object_users_collection(
1811 bmain, scene, child->collection, flag, copy_collections, false);
1812
1813 if (is_master_collection && copy_collections && child->collection != collection_child_new) {
1814 /* We do not want a collection sync here, our collections are in a complete uninitialized
1815 * state currently. With current code, that would lead to a memory leak - because of
1816 * reasons. It would be a useless loss of computing anyway, since caller has to fully
1817 * refresh view-layers/collections caching at the end. */
1818 BKE_collection_child_add_no_sync(bmain, collection, collection_child_new);
1819 BLI_remlink(&collection->children, child);
1820 MEM_freeN(child);
1821 if (child == orig_child_last) {
1822 break;
1823 }
1824 }
1825 }
1826
1827 return collection;
1828}
1829
1830/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
1832 Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
1833{
1834 /* duplicate all the objects of the scene (and matching collections, if required). */
1835 Collection *master_collection = scene->master_collection;
1836 single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
1837
1838 /* Will also handle the master collection. */
1839 BKE_libblock_relink_to_newid(bmain, &scene->id, 0);
1840
1841 /* Collection and object pointers in collections */
1842 libblock_relink_collection(bmain, scene->master_collection, false);
1843
1844 /* We also have to handle runtime things in UI. */
1845 if (v3d) {
1846 ID_NEW_REMAP(v3d->camera);
1847 }
1848
1849 /* Making single user may affect other scenes if they share
1850 * with current one some collections in their ViewLayer. */
1852}
1853
1854void object_single_user_make(Main *bmain, Scene *scene, Object *ob)
1855{
1856 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
1857 ob_iter->flag &= ~OB_DONE;
1858 }
1860
1861 /* tag only the one object */
1862 ob->flag |= OB_DONE;
1863
1864 single_object_users(bmain, scene, nullptr, OB_DONE, false);
1866}
1867
1869 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
1870{
1871 Light *la;
1872 Curve *cu;
1873 Camera *cam;
1874 Mesh *mesh;
1875 Lattice *lat;
1876 ID *id;
1877
1878 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
1879 if (BKE_id_is_editable(bmain, &ob->id)) {
1880 id = static_cast<ID *>(ob->data);
1883
1884 switch (ob->type) {
1885 case OB_EMPTY:
1886 ob->data = ID_NEW_SET(ob->data,
1887 BKE_id_copy_ex(bmain,
1888 static_cast<const ID *>(ob->data),
1889 nullptr,
1891 break;
1892 case OB_LAMP:
1893 ob->data = la = static_cast<Light *>(
1894 ID_NEW_SET(ob->data,
1895 BKE_id_copy_ex(bmain,
1896 static_cast<const ID *>(ob->data),
1897 nullptr,
1899 break;
1900 case OB_CAMERA:
1901 ob->data = cam = static_cast<Camera *>(
1902 ID_NEW_SET(ob->data,
1903 BKE_id_copy_ex(bmain,
1904 static_cast<const ID *>(ob->data),
1905 nullptr,
1908 break;
1909 case OB_MESH:
1910 /* Needed to remap texcomesh below. */
1911 ob->data = mesh = static_cast<Mesh *>(
1912 ID_NEW_SET(ob->data,
1913 BKE_id_copy_ex(bmain,
1914 static_cast<const ID *>(ob->data),
1915 nullptr,
1917 break;
1918 case OB_MBALL:
1919 ob->data = ID_NEW_SET(ob->data,
1920 BKE_id_copy_ex(bmain,
1921 static_cast<const ID *>(ob->data),
1922 nullptr,
1924 break;
1925 case OB_CURVES_LEGACY:
1926 case OB_SURF:
1927 case OB_FONT:
1928 ob->data = cu = static_cast<Curve *>(
1929 ID_NEW_SET(ob->data,
1930 BKE_id_copy_ex(bmain,
1931 static_cast<const ID *>(ob->data),
1932 nullptr,
1934 ID_NEW_REMAP(cu->bevobj);
1936 break;
1937 case OB_LATTICE:
1938 ob->data = lat = static_cast<Lattice *>(
1939 ID_NEW_SET(ob->data,
1940 BKE_id_copy_ex(bmain,
1941 static_cast<const ID *>(ob->data),
1942 nullptr,
1944 break;
1945 case OB_ARMATURE:
1947 ob->data = ID_NEW_SET(ob->data,
1948 BKE_id_copy_ex(bmain,
1949 static_cast<const ID *>(ob->data),
1950 nullptr,
1952 BKE_pose_rebuild(bmain, ob, static_cast<bArmature *>(ob->data), true);
1953 break;
1954 case OB_SPEAKER:
1955 ob->data = ID_NEW_SET(ob->data,
1956 BKE_id_copy_ex(bmain,
1957 static_cast<const ID *>(ob->data),
1958 nullptr,
1960 break;
1961 case OB_LIGHTPROBE:
1962 ob->data = ID_NEW_SET(ob->data,
1963 BKE_id_copy_ex(bmain,
1964 static_cast<const ID *>(ob->data),
1965 nullptr,
1967 break;
1968 case OB_CURVES:
1969 ob->data = ID_NEW_SET(ob->data,
1970 BKE_id_copy_ex(bmain,
1971 static_cast<const ID *>(ob->data),
1972 nullptr,
1974 break;
1975 case OB_POINTCLOUD:
1976 ob->data = ID_NEW_SET(ob->data,
1977 BKE_id_copy_ex(bmain,
1978 static_cast<const ID *>(ob->data),
1979 nullptr,
1981 break;
1982 case OB_VOLUME:
1983 ob->data = ID_NEW_SET(ob->data,
1984 BKE_id_copy_ex(bmain,
1985 static_cast<const ID *>(ob->data),
1986 nullptr,
1988 break;
1989 case OB_GREASE_PENCIL:
1990 ob->data = ID_NEW_SET(ob->data,
1991 BKE_id_copy_ex(bmain,
1992 static_cast<const ID *>(ob->data),
1993 nullptr,
1995 break;
1996 default:
1997 printf("ERROR %s: can't copy %s\n", __func__, id->name);
1998 BLI_assert_msg(0, "This should never happen.");
1999
2000 /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
2001 BKE_scene_objects_iterator_end(&iter_macro);
2002 return;
2003 }
2004
2005 id_us_min(id);
2006 }
2007 }
2008 }
2010
2011 mesh = static_cast<Mesh *>(bmain->meshes.first);
2012 while (mesh) {
2013 ID_NEW_REMAP(mesh->texcomesh);
2014 mesh = static_cast<Mesh *>(mesh->id.next);
2015 }
2016}
2017
2018void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
2019{
2020 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
2021 ob_iter->flag &= ~OB_DONE;
2022 }
2024
2025 /* Tag only the one object. */
2026 ob->flag |= OB_DONE;
2027
2028 single_obdata_users(bmain, scene, nullptr, nullptr, OB_DONE);
2029}
2030
2032 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2033{
2034 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2035 if (BKE_id_is_editable(bmain, &ob->id)) {
2036 AnimData *adt = BKE_animdata_from_id(&ob->id);
2037 if (adt == nullptr) {
2038 continue;
2039 }
2040
2041 ID *id_act = (ID *)adt->action;
2042 if (single_data_needs_duplication(id_act)) {
2045 }
2046 }
2047 }
2049}
2050
2052 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2053{
2054 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2055 if (BKE_id_is_editable(bmain, &ob->id) && ob->data != nullptr) {
2056 ID *id_obdata = (ID *)ob->data;
2057 AnimData *adt = BKE_animdata_from_id(id_obdata);
2058 if (adt == nullptr) {
2059 continue;
2060 }
2061
2062 ID *id_act = (ID *)adt->action;
2063 if (single_data_needs_duplication(id_act)) {
2066 }
2067 }
2068 }
2070}
2071
2073 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2074{
2075 Material *ma, *man;
2076 int a;
2077
2078 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2079 if (BKE_id_is_editable(bmain, &ob->id)) {
2080 for (a = 1; a <= ob->totcol; a++) {
2081 ma = BKE_object_material_get(ob, short(a));
2083 man = (Material *)BKE_id_copy_ex(
2084 bmain, &ma->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
2085 man->id.us = 0;
2086 BKE_object_material_assign(bmain, ob, man, short(a), BKE_MAT_ASSIGN_USERPREF);
2087 }
2088 }
2089 }
2090 }
2092}
2093
2095
2096/* ------------------------------------------------------------------- */
2099
2100enum {
2105};
2106
2108{
2109 ID **id_pointer = cb_data->id_pointer;
2110 if (*id_pointer) {
2111 (*id_pointer)->tag &= ~ID_TAG_DOIT;
2112 }
2113
2114 return IDWALK_RET_NOP;
2115}
2116
2117static void tag_localizable_objects(bContext *C, const int mode)
2118{
2119 Main *bmain = CTX_data_main(C);
2120
2121 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2122
2123 /* Set ID_TAG_DOIT flag for all selected objects, so next we can check whether
2124 * object is gonna to become local or not.
2125 */
2126 CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
2127 object->id.tag |= ID_TAG_DOIT;
2128
2129 /* If obdata is also going to become local, mark it as such too. */
2130 if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
2131 ID *data_id = (ID *)object->data;
2132 data_id->tag |= ID_TAG_DOIT;
2133 }
2134 }
2136
2137 /* Also forbid making objects local if other library objects are using
2138 * them for modifiers or constraints.
2139 *
2140 * FIXME This is ignoring all other linked ID types potentially using the selected tagged
2141 * objects! Probably works fine in most 'usual' cases though.
2142 */
2143 for (Object *object = static_cast<Object *>(bmain->objects.first); object;
2144 object = static_cast<Object *>(object->id.next))
2145 {
2146 if ((object->id.tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(object)) {
2148 nullptr, &object->id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2149 }
2150 if (object->data) {
2151 ID *data_id = (ID *)object->data;
2152 if ((data_id->tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(data_id)) {
2154 nullptr, data_id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2155 }
2156 }
2157 }
2158
2159 /* TODO(sergey): Drivers targets? */
2160}
2161
2167 const Scene *scene,
2168 ViewLayer *view_layer,
2169 Collection *collection)
2170{
2171 Object *ob;
2172 bool changed = false;
2173
2174 for (ob = static_cast<Object *>(bmain->objects.first); ob;
2175 ob = static_cast<Object *>(ob->id.next))
2176 {
2177 if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
2178 Base *base;
2179
2180 id_us_plus(&ob->id);
2181
2182 BKE_collection_object_add(bmain, collection, ob);
2183 BKE_view_layer_synced_ensure(scene, view_layer);
2184 base = BKE_view_layer_base_find(view_layer, ob);
2185 base_select(base, BA_SELECT);
2187
2188 changed = true;
2189 }
2190 }
2191
2192 return changed;
2193}
2194
2196{
2197 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
2198 if (strip->act) {
2199 strip->act->id.tag &= ~ID_TAG_PRE_EXISTING;
2200 }
2201
2202 make_local_animdata_tag_strips(&strip->strips);
2203 }
2204}
2205
2206/* Tag all actions used by given animdata to be made local. */
2208{
2209 if (adt) {
2210 /* Actions - Active and Temp */
2211 if (adt->action) {
2213 }
2214 if (adt->tmpact) {
2216 }
2217
2218 /* Drivers */
2219 /* TODO: need to handle the ID-targets too? */
2220
2221 /* NLA Data */
2222 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
2223 make_local_animdata_tag_strips(&nlt->strips);
2224 }
2225 }
2226}
2227
2229{
2230 if (ma) {
2233
2234 /* About node-trees: root one is made local together with material,
2235 * others we keep linked (for now). */
2236 }
2237}
2238
2240{
2241 Main *bmain = CTX_data_main(C);
2242 Material *ma, ***matarar;
2243 const int mode = RNA_enum_get(op->ptr, "type");
2244 int a;
2245
2246 /* NOTE: we (ab)use ID_TAG_PRE_EXISTING to cherry pick which ID to make local... */
2247 if (mode == MAKE_LOCAL_ALL) {
2248 const Scene *scene = CTX_data_scene(C);
2249 ViewLayer *view_layer = CTX_data_view_layer(C);
2250 Collection *collection = CTX_data_collection(C);
2251
2253
2254 /* De-select so the user can differentiate newly instanced from existing objects. */
2255 BKE_view_layer_base_deselect_all(scene, view_layer);
2256
2257 if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, collection)) {
2258 BKE_report(op->reports,
2259 RPT_INFO,
2260 "Orphan library objects added to the current scene to avoid loss");
2261 }
2262 }
2263 else {
2266
2267 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2268 if ((ob->id.tag & ID_TAG_DOIT) == 0) {
2269 continue;
2270 }
2271
2272 ob->id.tag &= ~ID_TAG_PRE_EXISTING;
2274 LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
2275 psys->part->id.tag &= ~ID_TAG_PRE_EXISTING;
2276 }
2277
2279 for (a = 0; a < ob->totcol; a++) {
2280 ma = ob->mat[a];
2281 if (ma) {
2283 }
2284 }
2285
2286 matarar = BKE_object_material_array_p(ob);
2287 if (matarar) {
2288 for (a = 0; a < ob->totcol; a++) {
2289 ma = (*matarar)[a];
2290 if (ma) {
2292 }
2293 }
2294 }
2295 }
2296
2298 ob->data != nullptr)
2299 {
2300 ID *ob_data = static_cast<ID *>(ob->data);
2301 ob_data->tag &= ~ID_TAG_PRE_EXISTING;
2303 }
2304 }
2306 }
2307
2309 bmain, nullptr, nullptr, true, false, true); /* nullptr is all libraries. */
2310
2312 return OPERATOR_FINISHED;
2313}
2314
2316{
2317 static const EnumPropertyItem type_items[] = {
2318 {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
2319 {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
2321 "SELECT_OBDATA_MATERIAL",
2322 0,
2323 "Selected Objects, Data and Materials",
2324 ""},
2325 {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
2326 {0, nullptr, 0, nullptr, nullptr},
2327 };
2328
2329 /* identifiers */
2330 ot->name = "Make Local";
2331 ot->description = "Make library linked data-blocks local to this file";
2332 ot->idname = "OBJECT_OT_make_local";
2333
2334 /* API callbacks. */
2335 ot->invoke = WM_menu_invoke;
2336 ot->exec = make_local_exec;
2337 ot->poll = ED_operator_objectmode;
2338
2339 /* flags */
2340 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2341
2342 /* properties */
2343 ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
2344}
2345
2347
2348/* ------------------------------------------------------------------- */
2351
2353{
2354 /* An object is actually overridable only if it is in at least one local collection.
2355 * Unfortunately 'direct link' flag is not enough here. */
2356 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2357 if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) {
2358 return true;
2359 }
2360 }
2361 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
2362 if (!ID_IS_LINKED(scene) && BKE_collection_has_object(scene->master_collection, object)) {
2363 return true;
2364 }
2365 }
2366 return false;
2367}
2368
2370{
2371 Main *bmain = CTX_data_main(C);
2372 Scene *scene = CTX_data_scene(C);
2373 ViewLayer *view_layer = CTX_data_view_layer(C);
2375 ID *id_root = nullptr;
2376 bool is_override_instancing_object = false;
2377
2378 bool user_overrides_from_selected_objects = false;
2379
2380 if (!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2382 {
2384 BKE_reportf(op->reports,
2386 "Collection '%s' (instantiated by the active object) is not overridable",
2387 obact->instance_collection->id.name + 2);
2388 return OPERATOR_CANCELLED;
2389 }
2390
2391 id_root = &obact->instance_collection->id;
2392 is_override_instancing_object = true;
2393 user_overrides_from_selected_objects = false;
2394 }
2395 else if (!make_override_library_object_overridable_check(bmain, obact)) {
2396 const int i = RNA_property_int_get(op->ptr, op->type->prop);
2397 const uint collection_session_uid = *((const uint *)&i);
2398 if (collection_session_uid == MAIN_ID_SESSION_UID_UNSET) {
2399 BKE_reportf(op->reports,
2401 "Could not find an overridable root hierarchy for object '%s'",
2402 obact->id.name + 2);
2403 return OPERATOR_CANCELLED;
2404 }
2405 Collection *collection = static_cast<Collection *>(
2407 &collection_session_uid,
2408 sizeof(collection_session_uid),
2409 offsetof(ID, session_uid)));
2410 id_root = &collection->id;
2411 user_overrides_from_selected_objects = true;
2412 }
2413 /* Else, poll func ensures us that ID_IS_LINKED(obact) is true, or that it is already an
2414 * existing liboverride. */
2415 else {
2417 id_root = &obact->id;
2418 user_overrides_from_selected_objects = true;
2419 }
2420
2421 /* Make already existing selected liboverrides editable. */
2422 bool is_active_override = false;
2423 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2424 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2425 ob_iter->id.override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
2426 is_active_override = is_active_override || (&ob_iter->id == id_root);
2428 }
2429 }
2431 /* If the active object is a liboverride, there is no point going further, since in the weird
2432 * case where some other selected objects would be linked ones, there is no way to properly
2433 * create overrides for them currently.
2434 *
2435 * Could be added later if really needed, but would rather avoid that extra complexity here. */
2436 if (is_active_override) {
2437 return OPERATOR_FINISHED;
2438 }
2439
2441 const bool do_fully_editable = false;
2442
2443 GSet *user_overrides_objects_uids = do_fully_editable ? nullptr :
2446 __func__);
2447
2448 if (do_fully_editable) {
2449 /* Pass. */
2450 }
2451 else if (user_overrides_from_selected_objects) {
2452 /* Only selected objects can be 'user overrides'. */
2453 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2454 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2455 }
2457 }
2458 else {
2459 /* Only armatures inside the root collection (and their children) can be 'user overrides'. */
2461 if (ob_iter->type == OB_ARMATURE) {
2462 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2463 }
2464 }
2466 }
2467
2468 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2469
2470 /* For the time being, replace selected linked objects by their overrides in all collections.
2471 * While this may not be the absolute best behavior in all cases, in most common one this
2472 * should match the expected result. */
2473 if (user_overrides_objects_uids != nullptr) {
2474 LISTBASE_FOREACH (Collection *, coll_iter, &bmain->collections) {
2475 if (ID_IS_LINKED(coll_iter)) {
2476 continue;
2477 }
2478 LISTBASE_FOREACH (CollectionObject *, coll_ob_iter, &coll_iter->gobject) {
2479 if (BLI_gset_haskey(user_overrides_objects_uids,
2480 POINTER_FROM_UINT(coll_ob_iter->ob->id.session_uid)))
2481 {
2482 /* Tag for remapping when creating overrides. */
2483 coll_iter->id.tag |= ID_TAG_DOIT;
2484 break;
2485 }
2486 }
2487 }
2488 /* Also tag the Scene itself for remapping when creating overrides (includes the scene's master
2489 * collection too). */
2490 scene->id.tag |= ID_TAG_DOIT;
2491 }
2492
2493 ID *id_root_override;
2494 const bool success = BKE_lib_override_library_create(bmain,
2495 scene,
2496 view_layer,
2497 nullptr,
2498 id_root,
2499 id_root,
2500 &obact->id,
2501 &id_root_override,
2502 do_fully_editable);
2503
2504 if (!do_fully_editable) {
2505 /* Define liboverrides from selected/validated objects as user defined. */
2506 ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
2507 ID *id_iter;
2508 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2509 if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
2510 id_iter->override_library->hierarchy_root != id_hierarchy_root_override)
2511 {
2512 continue;
2513 }
2514 if (BLI_gset_haskey(user_overrides_objects_uids,
2516 {
2518 }
2519 }
2521
2522 BLI_gset_free(user_overrides_objects_uids, nullptr);
2523 }
2524
2525 if (success) {
2526 if (is_override_instancing_object) {
2527 /* Remove the instance empty from this scene, the items now have an overridden collection
2528 * instead. */
2529 base_free_and_unlink(bmain, scene, obact);
2530 }
2531 else {
2532 /* Remove the found root ID from the view layer. */
2533 switch (GS(id_root->name)) {
2534 case ID_GR: {
2535 Collection *collection_root = (Collection *)id_root;
2537 CollectionParent *, collection_parent, &collection_root->runtime.parents)
2538 {
2539 if (ID_IS_LINKED(collection_parent->collection) ||
2540 !BKE_view_layer_has_collection(view_layer, collection_parent->collection))
2541 {
2542 continue;
2543 }
2544 BKE_collection_child_remove(bmain, collection_parent->collection, collection_root);
2545 }
2546 break;
2547 }
2548 case ID_OB: {
2549 /* TODO: Not sure how well we can handle this case, when we don't have the collections
2550 * as reference containers... */
2551 break;
2552 }
2553 default:
2554 break;
2555 }
2556 }
2557 }
2558
2563
2564 return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2565}
2566
2567/* Set the object to override. */
2569 wmOperator *op,
2570 const wmEvent * /*event*/)
2571{
2572 Main *bmain = CTX_data_main(C);
2573 Scene *scene = CTX_data_scene(C);
2574 ViewLayer *view_layer = CTX_data_view_layer(C);
2575 Object *obact = context_active_object(C);
2576
2577 /* Sanity checks. */
2578 if (!scene || ID_IS_LINKED(scene) || !obact) {
2579 return OPERATOR_CANCELLED;
2580 }
2581
2582 if ((!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2585 {
2586 return make_override_library_exec(C, op);
2587 }
2588
2589 if (!ID_IS_LINKED(obact)) {
2590 if (ID_IS_OVERRIDE_LIBRARY_REAL(obact)) {
2591 return make_override_library_exec(C, op);
2592 }
2593 BKE_report(op->reports, RPT_ERROR, "Cannot make library override from a local object");
2594 return OPERATOR_CANCELLED;
2595 }
2596
2597 VectorSet<Collection *> potential_root_collections;
2598 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2599 /* Only check for linked collections from the same library, in the current view-layer. */
2600 if (!ID_IS_LINKED(&collection->id) || collection->id.lib != obact->id.lib ||
2601 !BKE_view_layer_has_collection(view_layer, collection))
2602 {
2603 continue;
2604 }
2605 if (!BKE_collection_has_object_recursive(collection, obact)) {
2606 continue;
2607 }
2608 if (potential_root_collections.is_empty()) {
2609 potential_root_collections.add_new(collection);
2610 }
2611 else {
2612 bool has_parents_in_potential_roots = false;
2613 bool is_potential_root = false;
2614 for (auto *collection_root_iter : potential_root_collections) {
2615 if (BKE_collection_has_collection(collection_root_iter, collection)) {
2616 BLI_assert_msg(!BKE_collection_has_collection(collection, collection_root_iter),
2617 "Invalid loop in collection hierarchy");
2618 /* Current potential root is already 'better' (higher up in the collection hierarchy)
2619 * than current collection, nothing else to do. */
2620 has_parents_in_potential_roots = true;
2621 }
2622 else if (BKE_collection_has_collection(collection, collection_root_iter)) {
2623 BLI_assert_msg(!BKE_collection_has_collection(collection_root_iter, collection),
2624 "Invalid loop in collection hierarchy");
2625 /* Current potential root is in the current collection's hierarchy, so the later is a
2626 * better candidate as root collection. */
2627 is_potential_root = true;
2628 potential_root_collections.remove(collection_root_iter);
2629 }
2630 else {
2631 /* Current potential root is not found in current collection's hierarchy, so the later
2632 * is a potential candidate as root collection. */
2633 is_potential_root = true;
2634 }
2635 }
2636 /* Only add the current collection as potential root if it is not a descendant of any
2637 * already known potential root collections. */
2638 if (is_potential_root && !has_parents_in_potential_roots) {
2639 potential_root_collections.add_new(collection);
2640 }
2641 }
2642 }
2643
2644 if (potential_root_collections.is_empty()) {
2646 return make_override_library_exec(C, op);
2647 }
2648 if (potential_root_collections.size() == 1) {
2649 Collection *collection_root = potential_root_collections.pop();
2650 RNA_property_int_set(op->ptr, op->type->prop, *((int *)&collection_root->id.session_uid));
2651 return make_override_library_exec(C, op);
2652 }
2653
2654 BKE_reportf(op->reports,
2655 RPT_ERROR,
2656 "Too many potential root collections (%d) for the override hierarchy, "
2657 "please use the Outliner instead",
2658 int(potential_root_collections.size()));
2659 return OPERATOR_CANCELLED;
2660}
2661
2663{
2664 Base *base_act = CTX_data_active_base(C);
2665 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2666 * misbehave if the active object is not also selected, see e.g. #120701. */
2667 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2668 return false;
2669 }
2670
2671 /* Object must be directly linked to be overridable. */
2672 Object *obact = base_act->object;
2673 return (
2674 ED_operator_objectmode(C) && obact != nullptr &&
2675 (ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) ||
2676 (obact->instance_collection != nullptr &&
2678}
2679
2681{
2682 /* identifiers */
2683 ot->name = "Make Library Override";
2684 ot->description =
2685 "Create a local override of the selected linked objects, and their hierarchy of "
2686 "dependencies";
2687 ot->idname = "OBJECT_OT_make_override_library";
2688
2689 /* API callbacks. */
2693
2694 /* flags */
2695 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2696
2697 /* properties */
2698 PropertyRNA *prop;
2699 prop = RNA_def_int(ot->srna,
2700 "collection",
2702 INT_MIN,
2703 INT_MAX,
2704 "Override Collection",
2705 "Session UID of the directly linked collection containing the selected "
2706 "object, to make an override from",
2707 INT_MIN,
2708 INT_MAX);
2710 ot->prop = prop;
2711}
2712
2714
2715/* ------------------------------------------------------------------- */
2718
2720{
2721 Base *base_act = CTX_data_active_base(C);
2722 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2723 * misbehave if the active object is not also selected, see e.g. #120701. */
2724 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2725 return false;
2726 }
2727
2728 /* Object must be local and an override. */
2729 Object *obact = base_act->object;
2730 return (ED_operator_objectmode(C) && obact != nullptr && !ID_IS_LINKED(obact) &&
2731 ID_IS_OVERRIDE_LIBRARY(obact));
2732}
2733
2735{
2736 Main *bmain = CTX_data_main(C);
2737
2738 /* Reset all selected liboverrides. */
2740 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2741 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, false);
2742 }
2743 }
2745
2749
2750 return OPERATOR_FINISHED;
2751}
2752
2754{
2755 /* identifiers */
2756 ot->name = "Reset Library Override";
2757 ot->description = "Reset the selected local overrides to their linked references values";
2758 ot->idname = "OBJECT_OT_reset_override_library";
2759
2760 /* API callbacks. */
2763
2764 /* flags */
2765 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2766}
2767
2769
2770/* ------------------------------------------------------------------- */
2773
2775{
2776 Main *bmain = CTX_data_main(C);
2777 ViewLayer *view_layer = CTX_data_view_layer(C);
2778 Scene *scene = CTX_data_scene(C);
2779 LinkNode *todo_objects = nullptr, *todo_object_iter;
2780
2781 /* Make already existing selected liboverrides editable. */
2782 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2783 if (ID_IS_LINKED(ob_iter)) {
2784 continue;
2785 }
2786 BLI_linklist_prepend_alloca(&todo_objects, ob_iter);
2787 }
2789
2790 for (todo_object_iter = todo_objects; todo_object_iter != nullptr;
2791 todo_object_iter = todo_object_iter->next)
2792 {
2793 Object *ob_iter = static_cast<Object *>(todo_object_iter->link);
2794 if (BKE_lib_override_library_is_hierarchy_leaf(bmain, &ob_iter->id)) {
2795 bool do_remap_active = false;
2796 BKE_view_layer_synced_ensure(scene, view_layer);
2797 if (BKE_view_layer_active_object_get(view_layer) == ob_iter) {
2798 do_remap_active = true;
2799 }
2800 BKE_libblock_remap(bmain,
2801 &ob_iter->id,
2802 ob_iter->id.override_library->reference,
2804 if (do_remap_active) {
2805 BKE_view_layer_synced_ensure(scene, view_layer);
2806 Object *ref_object = (Object *)ob_iter->id.override_library->reference;
2807 Base *basact = BKE_view_layer_base_find(view_layer, ref_object);
2808 if (basact != nullptr) {
2809 view_layer->basact = basact;
2810 }
2812 }
2813 BKE_id_delete(bmain, &ob_iter->id);
2814 }
2815 else {
2816 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, true);
2817 }
2818 }
2819
2824
2825 return OPERATOR_FINISHED;
2826}
2827
2829{
2830 /* identifiers */
2831 ot->name = "Clear Library Override";
2832 ot->description =
2833 "Delete the selected local overrides and relink their usages to the linked data-blocks if "
2834 "possible, else reset them and mark them as non editable";
2835 ot->idname = "OBJECT_OT_clear_override_library";
2836
2837 /* API callbacks. */
2840
2841 /* flags */
2842 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2843}
2844
2846
2847/* ------------------------------------------------------------------- */
2850
2851enum {
2854};
2855
2857{
2858 Main *bmain = CTX_data_main(C);
2859 Scene *scene = CTX_data_scene(C);
2860 ViewLayer *view_layer = CTX_data_view_layer(C);
2861 View3D *v3d = CTX_wm_view3d(C); /* ok if this is nullptr */
2862 const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
2863 const bool copy_collections = false;
2864 bool update_deps = false;
2865
2866 if (RNA_boolean_get(op->ptr, "object")) {
2867 if (flag == SELECT) {
2868 BKE_view_layer_selected_objects_tag(scene, view_layer, OB_DONE);
2869 single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
2870 }
2871 else {
2872 single_object_users(bmain, scene, v3d, 0, copy_collections);
2873 }
2874
2875 /* needed since object relationships may have changed */
2876 update_deps = true;
2877 }
2878
2879 if (RNA_boolean_get(op->ptr, "obdata")) {
2880 single_obdata_users(bmain, scene, view_layer, v3d, flag);
2881
2882 /* Needed since some IDs were remapped? (incl. mesh->texcomesh, see #73797). */
2883 update_deps = true;
2884 }
2885
2886 if (RNA_boolean_get(op->ptr, "material")) {
2887 single_mat_users(bmain, scene, view_layer, v3d, flag);
2888 }
2889
2890 if (RNA_boolean_get(op->ptr, "animation")) {
2891 single_object_action_users(bmain, scene, view_layer, v3d, flag);
2892 }
2893
2894 if (RNA_boolean_get(op->ptr, "obdata_animation")) {
2895 single_objectdata_action_users(bmain, scene, view_layer, v3d, flag);
2896 }
2897
2899
2901
2902 if (update_deps) {
2904 }
2905
2906 return OPERATOR_FINISHED;
2907}
2908
2910{
2912 C, op, event, IFACE_("Make Selected Objects Single-User"), IFACE_("Make Single"));
2913}
2914
2916{
2917 static const EnumPropertyItem type_items[] = {
2918 {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
2919 {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
2920 {0, nullptr, 0, nullptr, nullptr},
2921 };
2922
2923 /* identifiers */
2924 ot->name = "Make Single User";
2925 ot->description = "Make linked data local to each object";
2926 ot->idname = "OBJECT_OT_make_single_user";
2927
2928 /* Note that the invoke callback is only used from operator search, * otherwise this does
2929 * nothing by default. */
2930
2931 /* API callbacks. */
2932 ot->invoke = make_single_user_invoke;
2933 ot->exec = make_single_user_exec;
2934 ot->poll = ED_operator_objectmode;
2935
2936 /* flags */
2937 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2938
2939 /* properties */
2940 ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
2941
2942 RNA_def_boolean(ot->srna, "object", false, "Object", "Make single user objects");
2943 RNA_def_boolean(ot->srna, "obdata", false, "Object Data", "Make single user object data");
2945 ot->srna, "material", false, "Materials", "Make materials local to each data-block");
2946 RNA_def_boolean(ot->srna,
2947 "animation",
2948 false,
2949 "Object Animation",
2950 "Make object animation data local to each object");
2951 RNA_def_boolean(ot->srna,
2952 "obdata_animation",
2953 false,
2954 "Object Data Animation",
2955 "Make object data (mesh, curve etc.) animation data local to each object");
2956}
2957
2959
2960/* ------------------------------------------------------------------- */
2963
2964std::string drop_named_material_tooltip(bContext *C, const char *name, const int mval[2])
2965{
2966 int mat_slot = 0;
2967 Object *ob = ED_view3d_give_material_slot_under_cursor(C, mval, &mat_slot);
2968 if (ob == nullptr) {
2969 return {};
2970 }
2971 mat_slot = max_ii(mat_slot, 1);
2972
2973 Material *prev_mat = BKE_object_material_get(ob, mat_slot);
2974
2975 if (prev_mat) {
2976 return fmt::format(fmt::runtime(TIP_("Drop {} on {} (slot {}, replacing {})")),
2977 name,
2978 ob->id.name + 2,
2979 mat_slot,
2980 prev_mat->id.name + 2);
2981 }
2982 return fmt::format(
2983 fmt::runtime(TIP_("Drop {} on {} (slot {})")), name, ob->id.name + 2, mat_slot);
2984}
2985
2987 wmOperator *op,
2988 const wmEvent *event)
2989{
2990 Main *bmain = CTX_data_main(C);
2991 int mat_slot = 0;
2992 Object *ob = ED_view3d_give_material_slot_under_cursor(C, event->mval, &mat_slot);
2993 mat_slot = max_ii(mat_slot, 1);
2994
2996 bmain, op->ptr, ID_MA);
2997
2998 if (ob == nullptr || ma == nullptr) {
2999 return OPERATOR_CANCELLED;
3000 }
3001
3003
3005
3009
3010 return OPERATOR_FINISHED;
3011}
3012
3014{
3015 /* identifiers */
3016 ot->name = "Drop Named Material on Object";
3017 ot->idname = "OBJECT_OT_drop_named_material";
3018
3019 /* API callbacks. */
3022
3023 /* flags */
3024 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
3025
3026 /* properties */
3028}
3029
3031
3032/* ------------------------------------------------------------------- */
3035
3036std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2])
3037{
3038 const Object *ob = ED_view3d_give_object_under_cursor(C, mval);
3039 if (ob == nullptr) {
3040 return {};
3041 }
3042
3043 const uint32_t session_uid = RNA_int_get(properties, "session_uid");
3044 const ID *id = BKE_libblock_find_session_uid(CTX_data_main(C), ID_NT, session_uid);
3045 if (!id) {
3046 return {};
3047 }
3048
3049 return fmt::format(fmt::runtime(TIP_("Add modifier with node group \"{}\" on object \"{}\"")),
3050 id->name,
3051 ob->id.name);
3052}
3053
3055{
3056 tree->ensure_interface_cache();
3057 if (!tree->interface_outputs().is_empty()) {
3058 const bNodeTreeInterfaceSocket *first_output = tree->interface_outputs()[0];
3059 if (!first_output) {
3060 BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry output socket");
3061 return false;
3062 }
3063 const bke::bNodeSocketType *typeinfo = first_output->socket_typeinfo();
3064 const eNodeSocketDatatype type = typeinfo ? typeinfo->type : SOCK_CUSTOM;
3065 if (type != SOCK_GEOMETRY) {
3066 BKE_report(op->reports, RPT_ERROR, "The first output must be a geometry socket");
3067 return false;
3068 }
3069 }
3070 return true;
3071}
3072
3074 wmOperator *op,
3075 const wmEvent *event)
3076{
3078 if (!ob) {
3079 return OPERATOR_CANCELLED;
3080 }
3081
3082 Main *bmain = CTX_data_main(C);
3083 Scene *scene = CTX_data_scene(C);
3084
3085 const uint32_t uid = RNA_int_get(op->ptr, "session_uid");
3086 bNodeTree *node_tree = (bNodeTree *)BKE_libblock_find_session_uid(bmain, ID_NT, uid);
3087 if (!node_tree) {
3088 return OPERATOR_CANCELLED;
3089 }
3090 if (node_tree->type != NTREE_GEOMETRY) {
3091 BKE_report(op->reports, RPT_ERROR, "Node group must be a geometry node tree");
3092 return OPERATOR_CANCELLED;
3093 }
3094
3095 if (!check_geometry_node_group_sockets(op, node_tree)) {
3096 return OPERATOR_CANCELLED;
3097 }
3098
3100 op->reports, bmain, scene, ob, node_tree->id.name + 2, eModifierType_Nodes);
3101 if (!nmd) {
3102 BKE_report(op->reports, RPT_ERROR, "Could not add geometry nodes modifier");
3103 return OPERATOR_CANCELLED;
3104 }
3105
3106 if (!RNA_boolean_get(op->ptr, "show_datablock_in_modifier")) {
3108 }
3109
3110 nmd->node_group = node_tree;
3111 id_us_plus(&node_tree->id);
3113
3116
3117 return OPERATOR_FINISHED;
3118}
3119
3121{
3122 ot->name = "Drop Geometry Node Group on Object";
3123 ot->idname = "OBJECT_OT_drop_geometry_nodes";
3124
3127
3129
3130 PropertyRNA *prop = RNA_def_int(ot->srna,
3131 "session_uid",
3132 0,
3133 INT32_MIN,
3134 INT32_MAX,
3135 "Session UID",
3136 "Session UID of the geometry node group being dropped",
3137 INT32_MIN,
3138 INT32_MAX);
3140 RNA_def_boolean(ot->srna,
3141 "show_datablock_in_modifier",
3142 true,
3143 "Show the datablock selector in the modifier",
3144 "");
3145}
3146
3148
3149/* ------------------------------------------------------------------- */
3152
3154{
3155 ID *id;
3156 PropertyPointerRNA pprop;
3157
3159
3160 if (pprop.prop == nullptr) {
3161 BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
3162 return OPERATOR_CANCELLED;
3163 }
3164
3165 id = pprop.ptr.owner_id;
3166
3167 if (GS(id->name) == ID_OB) {
3168 Object *ob = (Object *)id;
3169 if (ob->data) {
3170 ID *id_data = static_cast<ID *>(ob->data);
3171
3172 if (GS(id_data->name) == ID_IM) {
3173 id_us_min(id_data);
3174 ob->data = nullptr;
3175 }
3176 else {
3177 BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
3178 return OPERATOR_CANCELLED;
3179 }
3180 }
3181 }
3182
3183 RNA_property_update(C, &pprop.ptr, pprop.prop);
3184
3185 return OPERATOR_FINISHED;
3186}
3187
3189{
3190 /* identifiers */
3191 ot->name = "Unlink";
3192 ot->idname = "OBJECT_OT_unlink_data";
3193
3194 /* API callbacks. */
3196
3197 /* flags */
3198 ot->flag = OPTYPE_INTERNAL;
3199}
3200
3202
3203} // namespace blender::ed::object
Functions and classes to work with Actions.
Functions to work with AnimData.
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_active_if_bonecoll_visible(Object *ob) ATTR_WARN_UNUSED_RESULT
bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, int flag)
Definition anim_data.cc:368
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:82
void BKE_animdata_duplicate_id_action(Main *bmain, ID *id, uint duplicate_flags)
Definition anim_data.cc:437
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Definition armature.cc:2877
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_SCENE_OBJECT_END
bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
void BKE_scene_objects_iterator_end(BLI_Iterator *iter)
bool BKE_collection_child_add_no_sync(Main *bmain, Collection *parent, Collection *child)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
bool BKE_collection_has_collection(const Collection *parent, const Collection *collection)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
bool BKE_constraint_remove_ex(ListBase *list, struct Object *ob, struct bConstraint *con)
struct bConstraint * BKE_constraint_add_for_object(struct Object *ob, const char *name, short type)
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, struct Scene *scene, struct bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
#define CTX_DATA_BEGIN(C, Type, instance, member)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
Collection * CTX_data_collection(const bContext *C)
#define CTX_DATA_END
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
display list (or rather multi purpose list) stuff.
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, bool for_render)
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:95
FModifier * add_fmodifier(ListBase *modifiers, int type, FCurve *owner_fcu)
bool BKE_view_layer_has_collection(const ViewLayer *view_layer, const Collection *collection)
void BKE_view_layer_selected_objects_tag(const Scene *scene, ViewLayer *view_layer, int tag)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
#define FOREACH_OBJECT_FLAG_END
Definition BKE_layer.hh:477
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:298
void BKE_view_layer_base_deselect_all(const Scene *scene, ViewLayer *view_layer)
void BKE_main_collection_sync_remap(const Main *bmain)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
#define FOREACH_OBJECT_FLAG_BEGIN(_scene, _view_layer, _v3d, _flag, _instance)
Definition BKE_layer.hh:437
#define FOREACH_SELECTED_OBJECT_END
Definition BKE_layer.hh:310
ID * BKE_libblock_find_session_uid(Main *bmain, short type, uint32_t session_uid)
Definition lib_id.cc:1697
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2503
void id_us_plus(ID *id)
Definition lib_id.cc:353
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_COPY_DEFAULT
#define MAIN_ID_SESSION_UID_UNSET
void BKE_library_make_local(Main *bmain, const Library *lib, GHash *old_to_new_ids, bool untagged_only, bool set_fake, bool clear_asset_data)
Definition lib_id.cc:2109
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1981
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:767
void id_us_min(ID *id)
Definition lib_id.cc:361
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1214
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root, bool do_reset_system_override)
bool BKE_lib_override_library_create(Main *bmain, Scene *scene, ViewLayer *view_layer, Library *owner_library, ID *id_root_reference, ID *id_hierarchy_root_reference, ID *id_instance_hint, ID **r_id_root_override, const bool do_fully_editable)
bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id)
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_RET_NOP
@ IDWALK_READONLY
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:919
@ ID_REMAP_SKIP_INDIRECT_USAGE
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:563
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:557
General operations, lookup, etc. for materials.
void BKE_object_materials_sync_length(Main *bmain, Object *ob, ID *id)
@ BKE_MAT_ASSIGN_USERPREF
Material * BKE_object_material_get(Object *ob, short act)
void BKE_object_material_assign(Main *bmain, Object *ob, Material *ma, short act, int assign_type)
Material *** BKE_object_material_array_p(Object *ob)
Object * BKE_modifiers_is_deformed_by_curve(Object *ob)
Object * BKE_modifiers_is_deformed_by_lattice(Object *ob)
void BKE_modifier_free(ModifierData *md)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
General operations, lookup, etc. for blender objects.
blender::float4x4 BKE_object_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *ob)
KDTree_3d * BKE_object_as_kdtree(Object *ob, int *r_tot)
void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *object)
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
int BKE_object_scenes_users_get(Main *bmain, Object *ob)
bool BKE_object_parent_loop_check(const Object *parent, const Object *ob)
void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src)
void BKE_object_apply_parent_inverse(Object *ob)
LinkNode * BKE_object_groups(Main *bmain, Scene *scene, Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2618
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
struct GSet GSet
Definition BLI_ghash.h:337
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:944
bool BLI_ghashutil_intcmp(const void *a, const void *b)
unsigned int BLI_ghashutil_inthash_p(const void *ptr)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
A KD-tree for nearest neighbor search.
void BLI_kdtree_nd_ free(KDTree *tree)
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)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
void * BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, size_t bytes_size, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
MINLINE int max_ii(int a, int b)
MINLINE int min_iii(int a, int b, int c)
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][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 copy_v3_v3_int(int r[3], const int a[3])
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
unsigned short ushort
#define UNUSED_VARS(...)
#define UNPACK3(a)
#define ELEM(...)
#define POINTER_FROM_UINT(i)
#define STREQ(a, b)
#define TIP_(msgid)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:962
@ ID_RECALC_SELECT
Definition DNA_ID.h:1009
@ ID_RECALC_HIERARCHY
Definition DNA_ID.h:1066
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:985
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1012
@ LIBOVERRIDE_FLAG_SYSTEM_DEFINED
Definition DNA_ID.h:353
@ ID_TAG_PRE_EXISTING
Definition DNA_ID.h:834
@ ID_TAG_DOIT
Definition DNA_ID.h:944
@ ID_IM
@ ID_NT
@ ID_MA
@ ID_GR
@ ID_OB
@ FMODIFIER_TYPE_GENERATOR
@ BONE_RELATIVE_PARENTING
Object groups, one object can be in many groups at once.
@ CONSTRAINT_TYPE_TRACKTO
@ CONSTRAINT_TYPE_LOCKTRACK
@ CONSTRAINT_TYPE_FOLLOWPATH
@ CONSTRAINT_TYPE_DAMPTRACK
@ CONSTRAINT_OBTYPE_OBJECT
@ CU_BEZIER
@ CU_FOLLOW
@ CU_PATH
#define BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)
@ NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR
@ eModifierType_Curve
@ eModifierType_Lattice
@ eModifierType_GreasePencilArmature
@ eModifierType_Armature
@ eModifierType_Nodes
@ NTREE_GEOMETRY
eNodeSocketDatatype
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
Object is a sort of wrapper for general info.
@ OB_DUPLICOLLECTION
#define OB_TYPE_SUPPORT_PARVERT(_type)
@ 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_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
#define OB_TYPE_SUPPORT_MATERIAL(_type)
@ PARVERT1
@ PARSKEL
@ PAROBJECT
@ PARTYPE
@ PARVERT3
@ PARBONE
@ OB_DONE
#define BASE_SELECTED(v3d, base)
@ USER_DUP_LINKED_ID
@ USER_DUP_ACT
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ RPT_ERROR_INVALID_INPUT
#define ARM_GROUPS_ENVELOPE
#define ARM_GROUPS_NAME
#define ARM_GROUPS_AUTO
void EDBM_mesh_make(Object *ob, int select_mode, bool add_key_index)
void EDBM_mesh_load(Main *bmain, Object *ob)
bool ED_operator_object_active(bContext *C)
bool ED_operator_editsurfcurve(bContext *C)
bool ED_operator_objectmode(bContext *C)
bool ED_operator_objectmode_with_view3d_poll_msg(bContext *C)
bool ED_operator_view3d_active(bContext *C)
bool ED_operator_object_active_editable(bContext *C)
bool ED_operator_editlattice(bContext *C)
bool ED_operator_editmesh(bContext *C)
Object * ED_view3d_give_material_slot_under_cursor(bContext *C, const int mval[2], int *r_material_slot)
Object * ED_view3d_give_object_under_cursor(bContext *C, const int mval[2])
Read Guarded memory(de)allocation.
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
Definition MOD_nodes.cc:448
const EnumPropertyItem * RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
#define RNA_ENUM_ITEM_SEPR
Definition RNA_types.hh:645
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:406
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
#define C
Definition RandGen.cpp:29
void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(bContext *C, const char *title, int icon) ATTR_NONNULL()
uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
#define UI_ITEM_NONE
void uiItemEnumO_ptr(uiLayout *layout, wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::StringRefNull propname, int value)
#define NC_WINDOW
Definition WM_types.hh:372
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:495
#define ND_DRAW
Definition WM_types.hh:458
#define NC_WM
Definition WM_types.hh:371
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_ANIMATION
Definition WM_types.hh:385
#define ND_LIB_OVERRIDE_CHANGED
Definition WM_types.hh:416
#define ND_MODIFIER
Definition WM_types.hh:459
#define ND_PARENT
Definition WM_types.hh:464
ReportList * reports
Definition WM_types.hh:1025
#define NC_MATERIAL
Definition WM_types.hh:377
#define ND_TRANSFORM
Definition WM_types.hh:453
@ WM_OP_EXEC_DEFAULT
Definition WM_types.hh:245
#define ND_OB_SHADING
Definition WM_types.hh:454
#define ND_SPACE_VIEW3D
Definition WM_types.hh:525
#define NC_OBJECT
Definition WM_types.hh:376
#define ND_SHADING_LINKS
Definition WM_types.hh:476
#define NC_SPACE
Definition WM_types.hh:389
void ED_object_vgroup_calc_from_armature(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par, const int mode, const bool mirror)
@ BM_ELEM_SELECT
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
BMesh const char void * data
BPy_StructRNA * depsgraph
int64_t size() const
void add_new(const Key &key)
#define SELECT
#define offsetof(t, d)
ListBase * object_editcurve_get(Object *ob)
Definition editcurve.cc:90
KDTree_3d * tree
#define INT32_MAX
#define INT32_MIN
#define printf(...)
#define ID_NEW_REMAP(a)
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
#define ID_IS_OVERRIDABLE_LIBRARY(_id)
#define ID_IS_LINKED(_id)
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define ID_NEW_SET(_id, _idn)
#define GS(a)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
#define INDEX_UNSET
bAction * id_action_ensure(Main *bmain, ID *id)
Definition animdata.cc:195
FCurve * action_fcurve_ensure_ex(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, const FCurveDescriptor &fcurve_descriptor)
void add_armature_automatic_weights(Scene &scene, Object &object, const Object &ob_armature)
void add_armature_envelope_weights(Scene &scene, Object &object, const Object &ob_armature)
bool add_armature_vertex_groups(Object &object, const Object &ob_armature)
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
static wmOperatorStatus object_unlink_data_exec(bContext *C, wmOperator *op)
void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
static bool make_override_library_object_overridable_check(Main *bmain, Object *object)
static wmOperatorStatus drop_geometry_nodes_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_make_local(wmOperatorType *ot)
static wmOperatorStatus clear_override_library_exec(bContext *C, wmOperator *)
void OBJECT_OT_clear_override_library(wmOperatorType *ot)
const EnumPropertyItem prop_clear_parent_types[]
static const EnumPropertyItem prop_clear_track_types[]
static bool parent_set_vertex_parent_with_kdtree(bContext *C, ParentingContext *parenting_context, KDTree_3d *tree)
void OBJECT_OT_unlink_data(wmOperatorType *ot)
static bool check_geometry_node_group_sockets(wmOperator *op, const bNodeTree *tree)
static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static bool parent_set_vertex_parent(bContext *C, ParentingContext *parenting_context)
static void parent_clear_data(Object *ob)
static void make_local_animdata_tag_strips(ListBase *strips)
static wmOperatorStatus object_track_clear_exec(bContext *C, wmOperator *op)
static wmOperatorStatus parent_set_invoke(bContext *C, wmOperator *op, const wmEvent *)
std::string drop_named_material_tooltip(bContext *C, const char *name, const int mval[2])
void OBJECT_OT_make_links_scene(wmOperatorType *ot)
std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2])
void OBJECT_OT_track_clear(wmOperatorType *ot)
static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static wmOperatorStatus make_links_scene_exec(bContext *C, wmOperator *op)
void OBJECT_OT_drop_named_material(wmOperatorType *ot)
const EnumPropertyItem prop_make_parent_types[]
void base_select(Base *base, eObjectSelect_Mode mode)
void parent_clear(Object *ob, int type)
void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static wmOperatorStatus make_single_user_exec(bContext *C, wmOperator *op)
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
static bool single_data_needs_duplication(ID *id)
static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
void OBJECT_OT_track_set(wmOperatorType *ot)
static const EnumPropertyItem prop_make_track_types[]
static wmOperatorStatus track_set_exec(bContext *C, wmOperator *op)
static wmOperatorStatus vertex_parent_set_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
static void single_objectdata_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static wmOperatorStatus parent_clear_exec(bContext *C, wmOperator *op)
bool parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *const ob, Object *const par, int partype, bool xmirror, bool keep_transform, const int vert_par[3])
static wmOperatorStatus make_local_exec(bContext *C, wmOperator *op)
static wmOperatorStatus make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *)
Object * context_active_object(const bContext *C)
void OBJECT_OT_make_links_data(wmOperatorType *ot)
static wmOperatorStatus parent_noinv_set_exec(bContext *C, wmOperator *op)
static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
static wmOperatorStatus reset_override_library_exec(bContext *C, wmOperator *)
static wmOperatorStatus make_links_data_exec(bContext *C, wmOperator *op)
static bool reset_clear_override_library_poll(bContext *C)
static bool make_override_library_poll(bContext *C)
void OBJECT_OT_reset_override_library(wmOperatorType *ot)
void OBJECT_OT_parent_clear(wmOperatorType *ot)
static void make_local_animdata_tag(AnimData *adt)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
void OBJECT_OT_make_override_library(wmOperatorType *ot)
static bool parent_set_nonvertex_parent(bContext *C, ParentingContext *parenting_context)
void OBJECT_OT_drop_geometry_nodes(wmOperatorType *ot)
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
void OBJECT_OT_make_single_user(wmOperatorType *ot)
static wmOperatorStatus parent_set_invoke_menu(bContext *C, wmOperatorType *ot)
static bool vertex_parent_set_poll(bContext *C)
static void make_local_material_tag(Material *ma)
static void libblock_relink_collection(Main *bmain, Collection *collection, const bool do_collection)
static void tag_localizable_objects(bContext *C, const int mode)
static bool parent_set_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
static wmOperatorStatus drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_parent_set(wmOperatorType *ot)
static bool parent_set_with_depsgraph(ReportList *reports, const bContext *C, Scene *scene, Depsgraph *depsgraph, Object *const ob, Object *const par, Object *const parent_eval, int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
static wmOperatorStatus parent_set_exec(bContext *C, wmOperator *op)
static int tag_localizable_looper(LibraryIDLinkCallbackData *cb_data)
static bool make_local_all__instance_indirect_unused(Main *bmain, const Scene *scene, ViewLayer *view_layer, Collection *collection)
void object_single_user_make(Main *bmain, Scene *scene, Object *ob)
static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static Collection * single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections, const bool is_master_collection)
static wmOperatorStatus make_override_library_exec(bContext *C, wmOperator *op)
static wmOperatorStatus make_single_user_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void shaderfx_link(Object *dst, Object *src)
#define CURVE_VFONT_SET(vfont_member)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
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_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
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_dummy_NULL_items[]
Definition rna_rna.cc:26
bAction * action
bAction * tmpact
ListBase nla_tracks
uint8_t f1
struct Base * next
short flag
struct Object * object
struct Object * focus_object
struct CameraDOFSettings dof
struct Collection * collection
struct CollectionChild * next
struct CollectionObject * next
Collection_Runtime runtime
struct Object * object
struct Object * bevobj
struct Object * taperobj
struct Lattice * latt
FPoint * fpt
BezTriple * bezt
ListBase modifiers
unsigned int flag
Definition DNA_ID.h:338
struct ID * hierarchy_root
Definition DNA_ID.h:334
struct ID * reference
Definition DNA_ID.h:324
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
struct Library * lib
Definition DNA_ID.h:410
int us
Definition DNA_ID.h:425
struct ID * newid
Definition DNA_ID.h:408
IDOverrideLibrary * override_library
Definition DNA_ID.h:459
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
unsigned int session_uid
Definition DNA_ID.h:444
struct EditLatt * editlatt
struct BPoint * def
void * link
struct LinkNode * next
void * last
void * first
ListBase scenes
Definition BKE_main.hh:245
ListBase meshes
Definition BKE_main.hh:248
ListBase collections
Definition BKE_main.hh:267
ListBase objects
Definition BKE_main.hh:247
uint16_t flag
struct ModifierData * next
struct bNodeTree * node_group
struct Nurb * next
struct Collection * instance_collection
ObjectRuntimeHandle * runtime
ListBase modifiers
float loc[3]
float parentinv[4][4]
struct Object * parent
char parsubstr[64]
ID * owner_id
Definition RNA_types.hh:51
PropertyRNA * prop
Definition RNA_types.hh:134
struct Collection * master_collection
struct ToolSettings * toolsettings
struct RenderData r
struct Object * camera
struct Base * basact
struct bConstraint * prev
struct Bone * bone
Defines a socket type.
Definition BKE_node.hh:152
eNodeSocketDatatype type
Definition BKE_node.hh:187
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
int mval[2]
Definition WM_types.hh:760
PropertyRNA * prop
Definition WM_types.hh:1136
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_cursor_wait(bool val)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4226
wmOperatorType * ot
Definition wm_files.cc:4225
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
void WM_operator_properties_id_lookup(wmOperatorType *ot, const bool add_name_prop)
wmOperatorStatus WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
wmOperatorStatus WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
uint8_t flag
Definition wm_window.cc:139