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
374void parent_clear(Object *ob, const int type)
375{
376 if (ob->parent == nullptr) {
377 return;
378 }
380 switch (type) {
381 case CLEAR_PARENT_ALL: {
382 /* for deformers, remove corresponding modifiers to prevent
383 * a large number of modifiers building up */
385
386 /* clear parenting relationship completely */
387 ob->parent = nullptr;
388 ob->partype = PAROBJECT;
389 ob->parsubstr[0] = 0;
390 break;
391 }
393 /* remove parent, and apply the parented transform
394 * result as object's local transforms */
395 ob->parent = nullptr;
396 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, false);
397 /* Don't recalculate the animation because it would change the transform
398 * instead of keeping it. */
399 flags &= ~ID_RECALC_ANIMATION;
400 break;
401 }
403 /* object stays parented, but the parent inverse
404 * (i.e. offset from parent to retain binding state)
405 * is cleared. In other words: nothing to do here! */
406 break;
407 }
408 }
409
410 /* Always clear parentinv matrix for sake of consistency, see #41950. */
411 unit_m4(ob->parentinv);
412
413 DEG_id_tag_update(&ob->id, flags);
414}
415
416/* NOTE: poll should check for editable scene. */
418{
419 Main *bmain = CTX_data_main(C);
420 /* Dependency graph must be evaluated for access to object's evaluated transform matrices. */
422 const int type = RNA_enum_get(op->ptr, "type");
423
424 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
425 parent_clear(ob, type);
426 }
428
432 return OPERATOR_FINISHED;
433}
434
436{
437 /* identifiers */
438 ot->name = "Clear Parent";
439 ot->description = "Clear the object's parenting";
440 ot->idname = "OBJECT_OT_parent_clear";
441
442 /* API callbacks. */
443 ot->invoke = WM_menu_invoke;
444 ot->exec = parent_clear_exec;
445
446 /* flags */
448
449 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
450}
451
453
454/* ------------------------------------------------------------------- */
457
458void parent_set(Object *ob, Object *par, const int type, const char *substr)
459{
460 /* Always clear parentinv matrix for sake of consistency, see #41950. */
461 unit_m4(ob->parentinv);
462
463 if (!par || BKE_object_parent_loop_check(par, ob)) {
464 ob->parent = nullptr;
465 ob->partype = PAROBJECT;
466 ob->parsubstr[0] = 0;
467 return;
468 }
469
470 /* Other partypes are deprecated, do not use here! */
472
473 /* this could use some more checks */
474
475 ob->parent = par;
476 ob->partype &= ~PARTYPE;
477 ob->partype |= type;
478 STRNCPY(ob->parsubstr, substr);
479}
480
482 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
483 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
484 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
485 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
486 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
487 {PAR_BONE, "BONE", 0, "Bone", ""},
488 {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
489 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
490 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
491 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
492 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
493 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
494 {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
495 {0, nullptr, 0, nullptr, nullptr},
496};
497
499 const bContext *C,
500 Scene *scene,
501 Depsgraph *depsgraph,
502 Object *const ob,
503 Object *const par,
504 Object *const parent_eval,
505 int partype,
506 const bool xmirror,
507 const bool keep_transform,
508 const int vert_par[3])
509{
510 Main *bmain = CTX_data_main(C);
511 bPoseChannel *pchan = nullptr;
512 bPoseChannel *pchan_eval = nullptr;
513
514 /* Preconditions. */
515 if (ob == par) {
516 /* Parenting an object to itself is impossible. */
517 return false;
518 }
519
520 if (BKE_object_parent_loop_check(par, ob)) {
521 BKE_report(reports, RPT_ERROR, "Loop in parents");
522 return false;
523 }
524
525 switch (partype) {
526 case PAR_FOLLOW:
527 case PAR_PATH_CONST: {
528 if (par->type != OB_CURVES_LEGACY) {
529 return false;
530 }
531 Curve *cu = static_cast<Curve *>(par->data);
532 Curve *cu_eval = static_cast<Curve *>(parent_eval->data);
533 if ((cu->flag & CU_PATH) == 0) {
534 cu->flag |= CU_PATH | CU_FOLLOW;
535 cu_eval->flag |= CU_PATH | CU_FOLLOW;
536 /* force creation of path data */
537 BKE_displist_make_curveTypes(depsgraph, scene, par, false);
538 }
539 else {
540 cu->flag |= CU_FOLLOW;
541 cu_eval->flag |= CU_FOLLOW;
542 }
543
544 /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
545 if (partype == PAR_FOLLOW) {
546 /* get or create F-Curve */
547 bAction *act = animrig::id_action_ensure(bmain, &cu->id);
548 PointerRNA id_ptr = RNA_id_pointer_create(&cu->id);
550 bmain, act, nullptr, &id_ptr, {"eval_time", 0});
551
552 /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
553 if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
555 }
556 }
557
558 /* fall back on regular parenting now (for follow only) */
559 if (partype == PAR_FOLLOW) {
560 partype = PAR_OBJECT;
561 }
562 break;
563 }
564 case PAR_BONE:
567 pchan_eval = BKE_pose_channel_active_if_bonecoll_visible(parent_eval);
568
569 if (pchan == nullptr || pchan_eval == nullptr) {
570 /* If pchan_eval is nullptr, pchan should also be nullptr. */
571 BLI_assert_msg(pchan == nullptr, "Missing evaluated bone data");
572 BKE_report(reports, RPT_ERROR, "No active bone");
573 return false;
574 }
575 }
576
577 /* Apply transformation of previous parenting. */
578 if (keep_transform) {
579 /* Was removed because of bug #23577, * but this can be handy in some cases too #32616, so
580 * make optional. */
581 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), false, false);
582 }
583
584 /* Set the parent (except for follow-path constraint option). */
585 if (partype != PAR_PATH_CONST) {
586 ob->parent = par;
587 /* Always clear parentinv matrix for sake of consistency, see #41950. */
588 unit_m4(ob->parentinv);
589 }
590
591 /* Handle types. */
592 if (pchan) {
593 STRNCPY(ob->parsubstr, pchan->name);
594 }
595 else {
596 ob->parsubstr[0] = 0;
597 }
598
599 switch (partype) {
600 case PAR_PATH_CONST:
601 /* Don't do anything here, since this is not technically "parenting". */
602 break;
603 case PAR_CURVE:
604 case PAR_LATTICE:
605 case PAR_ARMATURE:
609 /* partype is now set to PAROBJECT so that invisible 'virtual'
610 * modifiers don't need to be created.
611 * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, * creating the
612 * virtual modifiers.
613 */
614 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
615 // ob->partype = PARSKEL; /* NOTE: DNA define, not operator property. */
616
617 /* BUT, to keep the deforms, we need a modifier, * and then we need to set the object
618 * that it uses
619 * - We need to ensure that the modifier we're adding doesn't already exist, * so we
620 * check this by assuming that the parent is selected too.
621 */
622 /* XXX currently this should only happen for meshes, curves, surfaces, * and lattices
623 * - this stuff isn't available for meta-balls yet. */
624 if (ELEM(
626 {
627 ModifierData *md;
628
629 switch (partype) {
630 case PAR_CURVE: /* curve deform */
631 if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
632 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Curve);
633 if (md) {
634 ((CurveModifierData *)md)->object = par;
635 }
636 if (par->runtime->curve_cache &&
637 par->runtime->curve_cache->anim_path_accum_length == nullptr)
638 {
640 }
641 }
642 break;
643 case PAR_LATTICE: /* lattice deform */
645 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Lattice);
646 if (md) {
647 ((LatticeModifierData *)md)->object = par;
648 }
649 }
650 break;
651 default: /* armature deform */
653 if (ob->type == OB_GREASE_PENCIL) {
654 md = modifier_add(
655 reports, bmain, scene, ob, nullptr, eModifierType_GreasePencilArmature);
656 if (md) {
657 ((GreasePencilArmatureModifierData *)md)->object = par;
658 }
659 }
660 else {
661 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Armature);
662 if (md) {
663 ((ArmatureModifierData *)md)->object = par;
664 }
665 }
666 }
667 break;
668 }
669 }
670 break;
671 case PAR_BONE:
672 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
673 if (pchan->bone) {
675 pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
676 }
677 break;
679 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
680 if (pchan->bone) {
682 pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
683 }
684 break;
685 case PAR_VERTEX:
686 ob->partype = PARVERT1;
687 ob->par1 = vert_par[0];
688 break;
689 case PAR_VERTEX_TRI:
690 ob->partype = PARVERT3;
691 copy_v3_v3_int(&ob->par1, vert_par);
692 break;
693 case PAR_OBJECT:
694 case PAR_FOLLOW:
695 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
696 break;
697 }
698
699 /* Constraint and set parent inverse. */
700 const bool is_armature_parent = ELEM(
702 if (partype == PAR_PATH_CONST) {
703 bConstraint *con;
705 float cmat[4][4], vec[3];
706
708
709 data = static_cast<bFollowPathConstraint *>(con->data);
710 data->tar = par;
711
713 depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, nullptr, cmat, scene->r.cfra);
714 sub_v3_v3v3(vec, ob->object_to_world().location(), cmat[3]);
715
716 copy_v3_v3(ob->loc, vec);
717 }
718 else if (is_armature_parent && (ob->type == OB_LATTICE) && (par->type == OB_ARMATURE) &&
719 (partype == PAR_ARMATURE_NAME))
720 {
722 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
723 }
724 else if (is_armature_parent && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
725 if (partype == PAR_ARMATURE_NAME) {
727 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
728 }
729 else if (partype == PAR_ARMATURE_ENVELOPE) {
731 reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
732 }
733 else if (partype == PAR_ARMATURE_AUTO) {
734 WM_cursor_wait(true);
736 reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
737 WM_cursor_wait(false);
738 }
739 /* Get corrected inverse. */
740 ob->partype = PAROBJECT;
741
743 }
744 else if (is_armature_parent && (ob->type == OB_GREASE_PENCIL) && (par->type == OB_ARMATURE)) {
745 if (partype == PAR_ARMATURE_NAME) {
747 }
748 else if (partype == PAR_ARMATURE_ENVELOPE) {
750 }
751 else if (partype == PAR_ARMATURE_AUTO) {
753 }
754 /* get corrected inverse */
755 ob->partype = PAROBJECT;
756
758 }
759 else {
760 /* calculate inverse parent matrix */
762 }
763
766 return true;
767}
768
770 const bContext *C,
771 Scene *scene,
772 Object *const ob,
773 Object *const par,
774 int partype,
775 const bool xmirror,
776 const bool keep_transform,
777 const int vert_par[3])
778{
780 Object *parent_eval = DEG_get_evaluated(depsgraph, par);
781
783 C,
784 scene,
785 depsgraph,
786 ob,
787 par,
788 parent_eval,
789 partype,
790 xmirror,
791 keep_transform,
792 vert_par);
793}
794
795static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
796{
797 const float *co_find = child->object_to_world().location();
798 if (is_tri) {
799 KDTreeNearest_3d nearest[3];
800 int tot;
801
802 tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
803 BLI_assert(tot == 3);
804 UNUSED_VARS(tot);
805
806 vert_par[0] = nearest[0].index;
807 vert_par[1] = nearest[1].index;
808 vert_par[2] = nearest[2].index;
809
810 BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
811 }
812 else {
813 vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, nullptr);
814 BLI_assert(vert_par[0] >= 0);
815 vert_par[1] = 0;
816 vert_par[2] = 0;
817 }
818}
819
829
831{
833 Object *parent_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
834
835 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
836 if (ob == parenting_context->par) {
837 /* parent_set() will fail (and thus return false), but this case
838 * shouldn't break this loop. It's expected that the active object is also selected. */
839 continue;
840 }
841
842 if (!parent_set_with_depsgraph(parenting_context->reports,
843 C,
844 parenting_context->scene,
845 depsgraph,
846 ob,
847 parenting_context->par,
848 parent_eval,
849 parenting_context->partype,
850 parenting_context->xmirror,
851 parenting_context->keep_transform,
852 nullptr))
853 {
854 return false;
855 }
856 }
858
859 return true;
860}
861
863 ParentingContext *parenting_context,
864 KDTree_3d *tree)
865{
866 int vert_par[3] = {0, 0, 0};
867
868 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
869 if (ob == parenting_context->par) {
870 /* parent_set() will fail (and thus return false), but this case
871 * shouldn't break this loop. It's expected that the active object is also selected. */
872 continue;
873 }
874
875 parent_set_vert_find(tree, ob, vert_par, parenting_context->is_vertex_tri);
876 if (!parent_set(parenting_context->reports,
877 C,
878 parenting_context->scene,
879 ob,
880 parenting_context->par,
881 parenting_context->partype,
882 parenting_context->xmirror,
883 parenting_context->keep_transform,
884 vert_par))
885 {
886 return false;
887 }
888 }
890 return true;
891}
892
893static bool parent_set_vertex_parent(bContext *C, ParentingContext *parenting_context)
894{
895 KDTree_3d *tree = nullptr;
896 int tree_tot;
897
899 Object *par_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
900
901 tree = BKE_object_as_kdtree(par_eval, &tree_tot);
902 BLI_assert(tree != nullptr);
903
904 if (tree_tot < (parenting_context->is_vertex_tri ? 3 : 1)) {
905 BKE_report(parenting_context->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
906 BLI_kdtree_3d_free(tree);
907 return false;
908 }
909
910 const bool ok = parent_set_vertex_parent_with_kdtree(C, parenting_context, tree);
911 BLI_kdtree_3d_free(tree);
912 return ok;
913}
914
916{
917 const int partype = RNA_enum_get(op->ptr, "type");
918 ParentingContext parenting_context{};
919 parenting_context.reports = op->reports;
920 parenting_context.scene = CTX_data_scene(C);
921 parenting_context.par = context_active_object(C);
922 parenting_context.partype = partype;
923 parenting_context.is_vertex_tri = partype == PAR_VERTEX_TRI;
924 parenting_context.xmirror = RNA_boolean_get(op->ptr, "xmirror");
925 parenting_context.keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
926
927 bool ok;
928 if (ELEM(parenting_context.partype, PAR_VERTEX, PAR_VERTEX_TRI)) {
929 ok = parent_set_vertex_parent(C, &parenting_context);
930 }
931 else {
932 ok = parent_set_nonvertex_parent(C, &parenting_context);
933 }
934 if (!ok) {
935 return OPERATOR_CANCELLED;
936 }
937
938 Main *bmain = CTX_data_main(C);
942
943 return OPERATOR_FINISHED;
944}
945
947{
948 Object *parent = context_active_object(C);
949 uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
950 uiLayout *layout = UI_popup_menu_layout(pup);
951
952 PointerRNA opptr;
953#if 0
954 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_OBJECT);
955#else
956 opptr = layout->op(ot, IFACE_("Object"), ICON_NONE, WM_OP_EXEC_DEFAULT, UI_ITEM_NONE);
957 RNA_enum_set(&opptr, "type", PAR_OBJECT);
958 RNA_boolean_set(&opptr, "keep_transform", false);
959
960 opptr = layout->op(
961 ot, IFACE_("Object (Keep Transform)"), ICON_NONE, WM_OP_EXEC_DEFAULT, UI_ITEM_NONE);
962 RNA_enum_set(&opptr, "type", PAR_OBJECT);
963 RNA_boolean_set(&opptr, "keep_transform", true);
964#endif
965
966 PointerRNA op_ptr = layout->op(
967 "OBJECT_OT_parent_no_inverse_set", IFACE_("Object (Without Inverse)"), ICON_NONE);
968 RNA_boolean_set(&op_ptr, "keep_transform", false);
969
970 op_ptr = layout->op("OBJECT_OT_parent_no_inverse_set",
971 IFACE_("Object (Keep Transform Without Inverse)"),
972 ICON_NONE);
973 RNA_boolean_set(&op_ptr, "keep_transform", true);
974
975 struct {
976 bool armature_deform, empty_groups, envelope_weights, automatic_weights, attach_surface;
977 } can_support = {false};
978
979 CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) {
980 if (child == parent) {
981 continue;
982 }
983 if (ELEM(child->type,
984 OB_MESH,
986 OB_SURF,
987 OB_FONT,
989 OB_LATTICE))
990 {
991 can_support.armature_deform = true;
992 can_support.envelope_weights = true;
993 }
994 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL, OB_LATTICE)) {
995 can_support.empty_groups = true;
996 }
997 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL)) {
998 can_support.automatic_weights = true;
999 }
1000 if (child->type == OB_CURVES) {
1001 can_support.attach_surface = true;
1002 }
1003 }
1005
1006 if (parent->type == OB_ARMATURE) {
1007
1008 if (can_support.armature_deform) {
1009 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE);
1010 }
1011 if (can_support.empty_groups) {
1012 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_NAME);
1013 }
1014 if (can_support.envelope_weights) {
1015 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_ENVELOPE);
1016 }
1017 if (can_support.automatic_weights) {
1018 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_ARMATURE_AUTO);
1019 }
1020 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_BONE);
1021 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_BONE_RELATIVE);
1022 }
1023 else if (parent->type == OB_CURVES_LEGACY) {
1024 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_CURVE);
1025 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_FOLLOW);
1026 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_PATH_CONST);
1027 }
1028 else if (parent->type == OB_LATTICE) {
1029 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_LATTICE);
1030 }
1031 else if (parent->type == OB_MESH) {
1032 if (can_support.attach_surface) {
1033 layout->op("CURVES_OT_surface_set", IFACE_("Object (Attach Curves to Surface)"), ICON_NONE);
1034 }
1035 }
1036
1037 /* vertex parenting */
1038 if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
1039 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_VERTEX);
1040 uiItemEnumO_ptr(layout, ot, std::nullopt, ICON_NONE, "type", PAR_VERTEX_TRI);
1041 }
1042
1043 UI_popup_menu_end(C, pup);
1044
1045 return OPERATOR_INTERFACE;
1046}
1047
1049{
1050 if (RNA_property_is_set(op->ptr, op->type->prop)) {
1051 return parent_set_exec(C, op);
1052 }
1053 return parent_set_invoke_menu(C, op->type);
1054}
1055
1056static bool parent_set_poll_property(const bContext * /*C*/,
1057 wmOperator *op,
1058 const PropertyRNA *prop)
1059{
1060 const char *prop_id = RNA_property_identifier(prop);
1061
1062 /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
1063 if (STREQ(prop_id, "xmirror")) {
1064 const int type = RNA_enum_get(op->ptr, "type");
1066 return true;
1067 }
1068 return false;
1069 }
1070
1071 return true;
1072}
1073
1075{
1076 /* identifiers */
1077 ot->name = "Make Parent";
1078 ot->description = "Set the object's parenting";
1079 ot->idname = "OBJECT_OT_parent_set";
1080
1081 /* API callbacks. */
1082 ot->invoke = parent_set_invoke;
1083 ot->exec = parent_set_exec;
1085 ot->poll_property = parent_set_poll_property;
1086
1087 /* flags */
1088 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1089
1090 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
1092 ot->srna,
1093 "xmirror",
1094 false,
1095 "X Mirror",
1096 "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
1097 RNA_def_boolean(ot->srna,
1098 "keep_transform",
1099 false,
1100 "Keep Transform",
1101 "Apply transformation before parenting");
1102}
1103
1105
1106/* ------------------------------------------------------------------- */
1109
1111{
1112 Main *bmain = CTX_data_main(C);
1114
1115 const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
1116
1118
1119 /* context iterator */
1120 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1121 if (ob != par) {
1122 if (BKE_object_parent_loop_check(par, ob)) {
1123 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
1124 }
1125 else {
1126 /* set recalc flags */
1128
1129 /* set parenting type for object - object only... */
1130 ob->parent = par;
1131 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
1132
1133 if (keep_transform) {
1135 continue;
1136 }
1137
1138 /* clear inverse matrix and also the object location */
1139 unit_m4(ob->parentinv);
1140 memset(ob->loc, 0, sizeof(float[3]));
1141 }
1142 }
1143 }
1145
1149
1150 return OPERATOR_FINISHED;
1151}
1152
1154{
1155 /* identifiers */
1156 ot->name = "Make Parent without Inverse";
1157 ot->description = "Set the object's parenting without setting the inverse parent correction";
1158 ot->idname = "OBJECT_OT_parent_no_inverse_set";
1159
1160 /* API callbacks. */
1161 ot->exec = parent_noinv_set_exec;
1163
1164 /* flags */
1165 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1166
1167 RNA_def_boolean(ot->srna,
1168 "keep_transform",
1169 false,
1170 "Keep Transform",
1171 "Preserve the world transform throughout parenting");
1172}
1173
1175
1176/* ------------------------------------------------------------------- */
1179
1180enum {
1183};
1184
1186 {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
1188 "CLEAR_KEEP_TRANSFORM",
1189 0,
1190 "Clear and Keep Transformation (Clear Track)",
1191 ""},
1192 {0, nullptr, 0, nullptr, nullptr},
1193};
1194
1195/* NOTE: poll should check for editable scene. */
1197{
1198 Main *bmain = CTX_data_main(C);
1199 const int type = RNA_enum_get(op->ptr, "type");
1200
1201 if (CTX_data_edit_object(C)) {
1202 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
1203 return OPERATOR_CANCELLED;
1204 }
1205 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1206 bConstraint *con, *pcon;
1207
1208 /* remove track-object for old track */
1209 ob->track = nullptr;
1211
1212 /* also remove all tracking constraints */
1213 for (con = static_cast<bConstraint *>(ob->constraints.last); con; con = pcon) {
1214 pcon = con->prev;
1215 if (ELEM(con->type,
1219 {
1220 BKE_constraint_remove_ex(&ob->constraints, ob, con);
1221 }
1222 }
1223
1224 if (type == CLEAR_TRACK_KEEP_TRANSFORM) {
1225 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, true);
1226 }
1227 }
1229
1232
1233 return OPERATOR_FINISHED;
1234}
1235
1237{
1238 /* identifiers */
1239 ot->name = "Clear Track";
1240 ot->description = "Clear tracking constraint or flag from object";
1241 ot->idname = "OBJECT_OT_track_clear";
1242
1243 /* API callbacks. */
1244 ot->invoke = WM_menu_invoke;
1246
1247 ot->poll = ED_operator_objectmode;
1248
1249 /* flags */
1250 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1251
1252 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1253}
1254
1256
1257/* ------------------------------------------------------------------- */
1260
1261enum {
1265};
1266
1268 {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
1269 {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""},
1270 {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
1271 {0, nullptr, 0, nullptr, nullptr},
1272};
1273
1275{
1276 Main *bmain = CTX_data_main(C);
1277 Object *obact = context_active_object(C);
1278
1279 const int type = RNA_enum_get(op->ptr, "type");
1280
1281 switch (type) {
1283 bConstraint *con;
1285
1286 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1287 if (ob != obact) {
1289
1290 data = static_cast<bDampTrackConstraint *>(con->data);
1291 data->tar = obact;
1292 DEG_id_tag_update(&ob->id,
1294
1295 /* Light, Camera and Speaker track differently by default */
1296 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1297 data->trackflag = TRACK_nZ;
1298 }
1299 }
1300 }
1302 break;
1303 }
1304 case CREATE_TRACK_TRACKTO: {
1305 bConstraint *con;
1307
1308 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1309 if (ob != obact) {
1311
1312 data = static_cast<bTrackToConstraint *>(con->data);
1313 data->tar = obact;
1314 DEG_id_tag_update(&ob->id,
1316
1317 /* Light, Camera and Speaker track differently by default */
1318 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1319 data->reserved1 = TRACK_nZ;
1320 data->reserved2 = UP_Y;
1321 }
1322 }
1323 }
1325 break;
1326 }
1328 bConstraint *con;
1330
1331 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1332 if (ob != obact) {
1334
1335 data = static_cast<bLockTrackConstraint *>(con->data);
1336 data->tar = obact;
1337 DEG_id_tag_update(&ob->id,
1339
1340 /* Light, Camera and Speaker track differently by default */
1341 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1342 data->trackflag = TRACK_nZ;
1343 data->lockflag = LOCK_Y;
1344 }
1345 }
1346 }
1348 break;
1349 }
1350 }
1351
1354
1355 return OPERATOR_FINISHED;
1356}
1357
1359{
1360 /* identifiers */
1361 ot->name = "Make Track";
1362 ot->description = "Make the object track another object, using various methods/constraints";
1363 ot->idname = "OBJECT_OT_track_set";
1364
1365 /* API callbacks. */
1366 ot->invoke = WM_menu_invoke;
1367 ot->exec = track_set_exec;
1368
1369 ot->poll = ED_operator_objectmode;
1370
1371 /* flags */
1372 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1373
1374 /* properties */
1375 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
1376}
1377
1379
1380/* ------------------------------------------------------------------- */
1383
1384#if 0
1385static void link_to_scene(Main * /*bmain*/, ushort /*nr*/)
1386{
1387 Scene *sce = (Scene *)BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
1388 Base *base, *nbase;
1389
1390 if (sce == nullptr) {
1391 return;
1392 }
1393 if (sce->id.lib) {
1394 return;
1395 }
1396
1397 for (base = FIRSTBASE; base; base = base->next) {
1398 if (BASE_SELECTED(v3d, base)) {
1399 nbase = MEM_mallocN(sizeof(Base), "newbase");
1400 *nbase = *base;
1401 BLI_addhead(&(sce->base), nbase);
1402 id_us_plus((ID *)base->object);
1403 }
1404 }
1405}
1406#endif
1407
1409{
1410 Main *bmain = CTX_data_main(C);
1411 Scene *scene_to = static_cast<Scene *>(
1412 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
1413
1414 if (scene_to == nullptr) {
1415 BKE_report(op->reports, RPT_ERROR, "Could not find scene");
1416 return OPERATOR_CANCELLED;
1417 }
1418
1419 if (scene_to == CTX_data_scene(C)) {
1420 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
1421 return OPERATOR_CANCELLED;
1422 }
1423
1424 if (!BKE_id_is_editable(bmain, &scene_to->id)) {
1425 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
1426 return OPERATOR_CANCELLED;
1427 }
1428
1429 Collection *collection_to = scene_to->master_collection;
1430 CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
1431 BKE_collection_object_add(bmain, collection_to, base->object);
1432 }
1434
1435 DEG_id_tag_update(&collection_to->id, ID_RECALC_HIERARCHY);
1436
1438
1439 /* redraw the 3D view because the object center points are colored differently */
1441
1442 /* one day multiple scenes will be visible, then we should have some update function for them
1443 */
1444 return OPERATOR_FINISHED;
1445}
1446
1447enum {
1456};
1457
1458/* Return true if make link data is allowed, false otherwise */
1459static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
1460{
1461 switch (type) {
1462 case MAKE_LINKS_OBDATA:
1463 if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
1464 return true;
1465 }
1466 break;
1469 /* Linking non-grease-pencil materials to a grease-pencil object causes issues.
1470 * We make sure that if one of the objects is a grease-pencil object, the other must be
1471 * as well. */
1472 ((ob_src->type == OB_GREASE_PENCIL) == (ob_dst->type == OB_GREASE_PENCIL)))
1473 {
1474 return true;
1475 }
1476 break;
1478 if (ob_dst->type == OB_EMPTY) {
1479 return true;
1480 }
1481 break;
1483 case MAKE_LINKS_GROUP:
1484 return true;
1486 if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
1487 return true;
1488 }
1489 break;
1490 case MAKE_LINKS_FONTS:
1491 if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT))
1492 {
1493 return true;
1494 }
1495 break;
1497 if ((ob_src->type == OB_GREASE_PENCIL) && (ob_dst->type == OB_GREASE_PENCIL)) {
1498 return true;
1499 }
1500 break;
1501 }
1502 return false;
1503}
1504
1506{
1507 Scene *scene = CTX_data_scene(C);
1508 Main *bmain = CTX_data_main(C);
1509 const int type = RNA_enum_get(op->ptr, "type");
1510 Object *ob_src;
1511 ID *obdata_id;
1512 int a;
1513
1514 /* collection */
1515 LinkNode *ob_collections = nullptr;
1516 bool is_cycle = false;
1517 bool is_lib = false;
1518
1519 ob_src = context_active_object(C);
1520
1521 /* avoid searching all collections in source object each time */
1522 if (type == MAKE_LINKS_GROUP) {
1523 ob_collections = BKE_object_groups(bmain, scene, ob_src);
1524 }
1525
1526 CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) {
1527 Object *ob_dst = base_dst->object;
1528
1529 if (ob_src != ob_dst) {
1530 if (allow_make_links_data(type, ob_src, ob_dst)) {
1531 obdata_id = static_cast<ID *>(ob_dst->data);
1532
1533 switch (type) {
1534 case MAKE_LINKS_OBDATA: /* obdata */
1535 id_us_min(obdata_id);
1536
1537 obdata_id = static_cast<ID *>(ob_src->data);
1538 id_us_plus(obdata_id);
1539 ob_dst->data = obdata_id;
1540
1541 /* if amount of material indices changed: */
1542 BKE_object_materials_sync_length(bmain, ob_dst, static_cast<ID *>(ob_dst->data));
1543
1544 if (ob_dst->type == OB_ARMATURE) {
1545 BKE_pose_rebuild(bmain, ob_dst, static_cast<bArmature *>(ob_dst->data), true);
1546 }
1548 break;
1550 /* new approach, using functions from kernel */
1551 for (a = 0; a < ob_src->totcol; a++) {
1552 Material *ma = BKE_object_material_get(ob_src, a + 1);
1553 /* also works with `ma == nullptr` */
1554 BKE_object_material_assign(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
1555 }
1557 break;
1559 BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
1560 if (ob_dst->data && ob_src->data) {
1561 if (BKE_id_is_editable(bmain, obdata_id)) {
1562 BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
1563 }
1564 else {
1565 is_lib = true;
1566 }
1567 }
1568 DEG_id_tag_update(&ob_dst->id,
1570 break;
1571 case MAKE_LINKS_GROUP: {
1572 LinkNode *collection_node;
1573
1574 /* first clear collections */
1575 BKE_object_groups_clear(bmain, scene, ob_dst);
1576
1577 /* now add in the collections from the link nodes */
1578 for (collection_node = ob_collections; collection_node;
1579 collection_node = collection_node->next)
1580 {
1581 if (ob_dst->instance_collection != collection_node->link) {
1583 bmain, static_cast<Collection *>(collection_node->link), ob_dst);
1584 }
1585 else {
1586 is_cycle = true;
1587 }
1588 }
1589 break;
1590 }
1592 ob_dst->instance_collection = ob_src->instance_collection;
1593 if (ob_dst->instance_collection) {
1594 id_us_plus(&ob_dst->instance_collection->id);
1595 ob_dst->transflag |= OB_DUPLICOLLECTION;
1596 }
1598 break;
1600 BKE_object_link_modifiers(ob_dst, ob_src);
1601 DEG_id_tag_update(&ob_dst->id,
1603 break;
1604 case MAKE_LINKS_FONTS: {
1605 Curve *cu_src = static_cast<Curve *>(ob_src->data);
1606 Curve *cu_dst = static_cast<Curve *>(ob_dst->data);
1607
1608 if (!BKE_id_is_editable(bmain, obdata_id)) {
1609 is_lib = true;
1610 break;
1611 }
1612
1613#define CURVE_VFONT_SET(vfont_member) \
1614 { \
1615 if (cu_dst->vfont_member) { \
1616 id_us_min(&cu_dst->vfont_member->id); \
1617 } \
1618 cu_dst->vfont_member = cu_src->vfont_member; \
1619 id_us_plus((ID *)cu_dst->vfont_member); \
1620 } \
1621 ((void)0)
1622
1623 CURVE_VFONT_SET(vfont);
1624 CURVE_VFONT_SET(vfontb);
1625 CURVE_VFONT_SET(vfonti);
1626 CURVE_VFONT_SET(vfontbi);
1627
1628#undef CURVE_VFONT_SET
1629
1630 DEG_id_tag_update(&ob_dst->id,
1632 break;
1633 }
1635 shaderfx_link(ob_dst, ob_src);
1636 DEG_id_tag_update(&ob_dst->id,
1638 break;
1639 }
1640 }
1641 }
1642 }
1644
1645 if (type == MAKE_LINKS_GROUP) {
1646 if (ob_collections) {
1647 BLI_linklist_free(ob_collections, nullptr);
1648 }
1649
1650 if (is_cycle) {
1651 BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
1652 }
1653 }
1654
1655 if (is_lib) {
1656 BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
1657 }
1658
1663
1664 return OPERATOR_FINISHED;
1665}
1666
1668{
1669 PropertyRNA *prop;
1670
1671 /* identifiers */
1672 ot->name = "Link Objects to Scene";
1673 ot->description = "Link selection to another scene";
1674 ot->idname = "OBJECT_OT_make_links_scene";
1675
1676 /* API callbacks. */
1677 ot->invoke = WM_enum_search_invoke;
1678 ot->exec = make_links_scene_exec;
1679 /* better not run the poll check */
1680
1681 /* flags */
1682 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1683
1684 /* properties */
1685 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
1688 ot->prop = prop;
1689}
1690
1692{
1693 static const EnumPropertyItem make_links_items[] = {
1694 {MAKE_LINKS_OBDATA, "OBDATA", 0, "Link Object Data", "Replace assigned Object Data"},
1695 {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Link Materials", "Replace assigned Materials"},
1697 "ANIMATION",
1698 0,
1699 "Link Animation Data",
1700 "Replace assigned Animation Data"},
1701 {MAKE_LINKS_GROUP, "GROUPS", 0, "Link Collections", "Replace assigned Collections"},
1703 "DUPLICOLLECTION",
1704 0,
1705 "Link Instance Collection",
1706 "Replace assigned Collection Instance"},
1707 {MAKE_LINKS_FONTS, "FONTS", 0, "Link Fonts to Text", "Replace Text object Fonts"},
1709 {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Copy Modifiers", "Replace Modifiers"},
1711 "EFFECTS",
1712 0,
1713 "Copy Grease Pencil Effects",
1714 "Replace Grease Pencil Effects"},
1715 {0, nullptr, 0, nullptr, nullptr},
1716 };
1717
1718 /* identifiers */
1719 ot->name = "Link/Transfer Data";
1720 ot->description = "Transfer data from active object to selected objects";
1721 ot->idname = "OBJECT_OT_make_links_data";
1722
1723 /* API callbacks. */
1724 ot->exec = make_links_data_exec;
1726
1727 /* flags */
1728 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1729
1730 /* properties */
1731 ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
1732}
1733
1735
1736/* ------------------------------------------------------------------- */
1739
1741{
1742 /* NOTE: When dealing with linked data, we always make a local copy of it.
1743 * While in theory we could rather make it local when it only has one user, this is difficult
1744 * in practice with current code of this function. */
1745 return (id != nullptr && (id->us > 1 || ID_IS_LINKED(id)));
1746}
1747
1749 Collection *collection,
1750 const bool do_collection)
1751{
1752 if (do_collection) {
1753 BKE_libblock_relink_to_newid(bmain, &collection->id, 0);
1754 }
1755
1756 for (CollectionObject *cob = static_cast<CollectionObject *>(collection->gobject.first);
1757 cob != nullptr;
1758 cob = cob->next)
1759 {
1760 BKE_libblock_relink_to_newid(bmain, &cob->ob->id, 0);
1761 }
1762
1763 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
1764 libblock_relink_collection(bmain, child->collection, true);
1765 }
1766}
1767
1769 Scene *scene,
1770 Collection *collection,
1771 const int flag,
1772 const bool copy_collections,
1773 const bool is_master_collection)
1774{
1775 /* Generate new copies for objects in given collection and all its children, * and
1776 * optionally also copy collections themselves. */
1777 if (copy_collections && !is_master_collection) {
1778 Collection *collection_new = (Collection *)BKE_id_copy_ex(
1779 bmain, &collection->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
1780 id_us_min(&collection_new->id);
1781 collection = static_cast<Collection *>(ID_NEW_SET(collection, collection_new));
1782 }
1783
1784 /* We do not remap to new objects here, this is done in separate step. */
1785 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
1786 Object *ob = cob->ob;
1787 /* an object may be in more than one collection */
1788 if ((ob->id.newid == nullptr) && ((ob->flag & flag) == flag)) {
1789 if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
1790 ID_NEW_SET(
1791 ob,
1792 BKE_id_copy_ex(bmain, &ob->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS));
1793 id_us_min(ob->id.newid);
1794 }
1795 }
1796 }
1797
1798 /* Since master collection has already be duplicated as part of scene copy, * we do not
1799 * duplicate it here. However, this means its children need to be re-added manually here, *
1800 * otherwise their parent lists are empty (which will lead to crashes, see #63101). */
1801 CollectionChild *child_next, *child = static_cast<CollectionChild *>(collection->children.first);
1802 CollectionChild *orig_child_last = static_cast<CollectionChild *>(collection->children.last);
1803 for (; child != nullptr; child = child_next) {
1804 child_next = child->next;
1805 Collection *collection_child_new = single_object_users_collection(
1806 bmain, scene, child->collection, flag, copy_collections, false);
1807
1808 if (is_master_collection && copy_collections && child->collection != collection_child_new) {
1809 /* We do not want a collection sync here, our collections are in a complete uninitialized
1810 * state currently. With current code, that would lead to a memory leak - because of
1811 * reasons. It would be a useless loss of computing anyway, since caller has to fully
1812 * refresh view-layers/collections caching at the end. */
1813 BKE_collection_child_add_no_sync(bmain, collection, collection_child_new);
1814 BLI_remlink(&collection->children, child);
1815 MEM_freeN(child);
1816 if (child == orig_child_last) {
1817 break;
1818 }
1819 }
1820 }
1821
1822 return collection;
1823}
1824
1825/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
1827 Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
1828{
1829 /* duplicate all the objects of the scene (and matching collections, if required). */
1830 Collection *master_collection = scene->master_collection;
1831 single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
1832
1833 /* Will also handle the master collection. */
1834 BKE_libblock_relink_to_newid(bmain, &scene->id, 0);
1835
1836 /* Collection and object pointers in collections */
1837 libblock_relink_collection(bmain, scene->master_collection, false);
1838
1839 /* We also have to handle runtime things in UI. */
1840 if (v3d) {
1841 ID_NEW_REMAP(v3d->camera);
1842 }
1843
1844 /* Making single user may affect other scenes if they share
1845 * with current one some collections in their ViewLayer. */
1847}
1848
1849void object_single_user_make(Main *bmain, Scene *scene, Object *ob)
1850{
1851 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
1852 ob_iter->flag &= ~OB_DONE;
1853 }
1855
1856 /* tag only the one object */
1857 ob->flag |= OB_DONE;
1858
1859 single_object_users(bmain, scene, nullptr, OB_DONE, false);
1861}
1862
1864 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
1865{
1866 Light *la;
1867 Curve *cu;
1868 Camera *cam;
1869 Mesh *mesh;
1870 Lattice *lat;
1871 ID *id;
1872
1873 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
1874 if (BKE_id_is_editable(bmain, &ob->id)) {
1875 id = static_cast<ID *>(ob->data);
1878
1879 switch (ob->type) {
1880 case OB_EMPTY:
1881 ob->data = ID_NEW_SET(ob->data,
1882 BKE_id_copy_ex(bmain,
1883 static_cast<const ID *>(ob->data),
1884 nullptr,
1886 break;
1887 case OB_LAMP:
1888 ob->data = la = static_cast<Light *>(
1889 ID_NEW_SET(ob->data,
1890 BKE_id_copy_ex(bmain,
1891 static_cast<const ID *>(ob->data),
1892 nullptr,
1894 break;
1895 case OB_CAMERA:
1896 ob->data = cam = static_cast<Camera *>(
1897 ID_NEW_SET(ob->data,
1898 BKE_id_copy_ex(bmain,
1899 static_cast<const ID *>(ob->data),
1900 nullptr,
1903 break;
1904 case OB_MESH:
1905 /* Needed to remap texcomesh below. */
1906 ob->data = mesh = static_cast<Mesh *>(
1907 ID_NEW_SET(ob->data,
1908 BKE_id_copy_ex(bmain,
1909 static_cast<const ID *>(ob->data),
1910 nullptr,
1912 break;
1913 case OB_MBALL:
1914 ob->data = ID_NEW_SET(ob->data,
1915 BKE_id_copy_ex(bmain,
1916 static_cast<const ID *>(ob->data),
1917 nullptr,
1919 break;
1920 case OB_CURVES_LEGACY:
1921 case OB_SURF:
1922 case OB_FONT:
1923 ob->data = cu = static_cast<Curve *>(
1924 ID_NEW_SET(ob->data,
1925 BKE_id_copy_ex(bmain,
1926 static_cast<const ID *>(ob->data),
1927 nullptr,
1929 ID_NEW_REMAP(cu->bevobj);
1931 break;
1932 case OB_LATTICE:
1933 ob->data = lat = static_cast<Lattice *>(
1934 ID_NEW_SET(ob->data,
1935 BKE_id_copy_ex(bmain,
1936 static_cast<const ID *>(ob->data),
1937 nullptr,
1939 break;
1940 case OB_ARMATURE:
1942 ob->data = ID_NEW_SET(ob->data,
1943 BKE_id_copy_ex(bmain,
1944 static_cast<const ID *>(ob->data),
1945 nullptr,
1947 BKE_pose_rebuild(bmain, ob, static_cast<bArmature *>(ob->data), true);
1948 break;
1949 case OB_SPEAKER:
1950 ob->data = ID_NEW_SET(ob->data,
1951 BKE_id_copy_ex(bmain,
1952 static_cast<const ID *>(ob->data),
1953 nullptr,
1955 break;
1956 case OB_LIGHTPROBE:
1957 ob->data = ID_NEW_SET(ob->data,
1958 BKE_id_copy_ex(bmain,
1959 static_cast<const ID *>(ob->data),
1960 nullptr,
1962 break;
1963 case OB_CURVES:
1964 ob->data = ID_NEW_SET(ob->data,
1965 BKE_id_copy_ex(bmain,
1966 static_cast<const ID *>(ob->data),
1967 nullptr,
1969 break;
1970 case OB_POINTCLOUD:
1971 ob->data = ID_NEW_SET(ob->data,
1972 BKE_id_copy_ex(bmain,
1973 static_cast<const ID *>(ob->data),
1974 nullptr,
1976 break;
1977 case OB_VOLUME:
1978 ob->data = ID_NEW_SET(ob->data,
1979 BKE_id_copy_ex(bmain,
1980 static_cast<const ID *>(ob->data),
1981 nullptr,
1983 break;
1984 case OB_GREASE_PENCIL:
1985 ob->data = ID_NEW_SET(ob->data,
1986 BKE_id_copy_ex(bmain,
1987 static_cast<const ID *>(ob->data),
1988 nullptr,
1990 break;
1991 default:
1992 printf("ERROR %s: can't copy %s\n", __func__, id->name);
1993 BLI_assert_msg(0, "This should never happen.");
1994
1995 /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
1996 BKE_scene_objects_iterator_end(&iter_macro);
1997 return;
1998 }
1999
2000 id_us_min(id);
2001 }
2002 }
2003 }
2005
2006 mesh = static_cast<Mesh *>(bmain->meshes.first);
2007 while (mesh) {
2008 ID_NEW_REMAP(mesh->texcomesh);
2009 mesh = static_cast<Mesh *>(mesh->id.next);
2010 }
2011}
2012
2013void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
2014{
2015 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
2016 ob_iter->flag &= ~OB_DONE;
2017 }
2019
2020 /* Tag only the one object. */
2021 ob->flag |= OB_DONE;
2022
2023 single_obdata_users(bmain, scene, nullptr, nullptr, OB_DONE);
2024}
2025
2027 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2028{
2029 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2030 if (BKE_id_is_editable(bmain, &ob->id)) {
2031 AnimData *adt = BKE_animdata_from_id(&ob->id);
2032 if (adt == nullptr) {
2033 continue;
2034 }
2035
2036 ID *id_act = (ID *)adt->action;
2037 if (single_data_needs_duplication(id_act)) {
2040 }
2041 }
2042 }
2044}
2045
2047 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2048{
2049 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2050 if (BKE_id_is_editable(bmain, &ob->id) && ob->data != nullptr) {
2051 ID *id_obdata = (ID *)ob->data;
2052 AnimData *adt = BKE_animdata_from_id(id_obdata);
2053 if (adt == nullptr) {
2054 continue;
2055 }
2056
2057 ID *id_act = (ID *)adt->action;
2058 if (single_data_needs_duplication(id_act)) {
2061 }
2062 }
2063 }
2065}
2066
2068 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2069{
2070 Material *ma, *man;
2071 int a;
2072
2073 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2074 if (BKE_id_is_editable(bmain, &ob->id)) {
2075 for (a = 1; a <= ob->totcol; a++) {
2076 ma = BKE_object_material_get(ob, short(a));
2078 man = (Material *)BKE_id_copy_ex(
2079 bmain, &ma->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
2080 man->id.us = 0;
2081 BKE_object_material_assign(bmain, ob, man, short(a), BKE_MAT_ASSIGN_USERPREF);
2082 }
2083 }
2084 }
2085 }
2087}
2088
2090
2091/* ------------------------------------------------------------------- */
2094
2095enum {
2100};
2101
2103{
2104 ID **id_pointer = cb_data->id_pointer;
2105 if (*id_pointer) {
2106 (*id_pointer)->tag &= ~ID_TAG_DOIT;
2107 }
2108
2109 return IDWALK_RET_NOP;
2110}
2111
2112static void tag_localizable_objects(bContext *C, const int mode)
2113{
2114 Main *bmain = CTX_data_main(C);
2115
2116 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2117
2118 /* Set ID_TAG_DOIT flag for all selected objects, so next we can check whether
2119 * object is gonna to become local or not.
2120 */
2121 CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
2122 object->id.tag |= ID_TAG_DOIT;
2123
2124 /* If obdata is also going to become local, mark it as such too. */
2125 if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
2126 ID *data_id = (ID *)object->data;
2127 data_id->tag |= ID_TAG_DOIT;
2128 }
2129 }
2131
2132 /* Also forbid making objects local if other library objects are using
2133 * them for modifiers or constraints.
2134 *
2135 * FIXME This is ignoring all other linked ID types potentially using the selected tagged
2136 * objects! Probably works fine in most 'usual' cases though.
2137 */
2138 for (Object *object = static_cast<Object *>(bmain->objects.first); object;
2139 object = static_cast<Object *>(object->id.next))
2140 {
2141 if ((object->id.tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(object)) {
2143 nullptr, &object->id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2144 }
2145 if (object->data) {
2146 ID *data_id = (ID *)object->data;
2147 if ((data_id->tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(data_id)) {
2149 nullptr, data_id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2150 }
2151 }
2152 }
2153
2154 /* TODO(sergey): Drivers targets? */
2155}
2156
2162 const Scene *scene,
2163 ViewLayer *view_layer,
2164 Collection *collection)
2165{
2166 Object *ob;
2167 bool changed = false;
2168
2169 for (ob = static_cast<Object *>(bmain->objects.first); ob;
2170 ob = static_cast<Object *>(ob->id.next))
2171 {
2172 if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
2173 Base *base;
2174
2175 id_us_plus(&ob->id);
2176
2177 BKE_collection_object_add(bmain, collection, ob);
2178 BKE_view_layer_synced_ensure(scene, view_layer);
2179 base = BKE_view_layer_base_find(view_layer, ob);
2180 base_select(base, BA_SELECT);
2182
2183 changed = true;
2184 }
2185 }
2186
2187 return changed;
2188}
2189
2191{
2192 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
2193 if (strip->act) {
2194 strip->act->id.tag &= ~ID_TAG_PRE_EXISTING;
2195 }
2196
2197 make_local_animdata_tag_strips(&strip->strips);
2198 }
2199}
2200
2201/* Tag all actions used by given animdata to be made local. */
2203{
2204 if (adt) {
2205 /* Actions - Active and Temp */
2206 if (adt->action) {
2208 }
2209 if (adt->tmpact) {
2211 }
2212
2213 /* Drivers */
2214 /* TODO: need to handle the ID-targets too? */
2215
2216 /* NLA Data */
2217 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
2218 make_local_animdata_tag_strips(&nlt->strips);
2219 }
2220 }
2221}
2222
2224{
2225 if (ma) {
2228
2229 /* About node-trees: root one is made local together with material,
2230 * others we keep linked (for now). */
2231 }
2232}
2233
2235{
2236 Main *bmain = CTX_data_main(C);
2237 Material *ma, ***matarar;
2238 const int mode = RNA_enum_get(op->ptr, "type");
2239 int a;
2240
2241 /* NOTE: we (ab)use ID_TAG_PRE_EXISTING to cherry pick which ID to make local... */
2242 if (mode == MAKE_LOCAL_ALL) {
2243 const Scene *scene = CTX_data_scene(C);
2244 ViewLayer *view_layer = CTX_data_view_layer(C);
2245 Collection *collection = CTX_data_collection(C);
2246
2248
2249 /* De-select so the user can differentiate newly instanced from existing objects. */
2250 BKE_view_layer_base_deselect_all(scene, view_layer);
2251
2252 if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, collection)) {
2253 BKE_report(op->reports,
2254 RPT_INFO,
2255 "Orphan library objects added to the current scene to avoid loss");
2256 }
2257 }
2258 else {
2261
2262 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2263 if ((ob->id.tag & ID_TAG_DOIT) == 0) {
2264 continue;
2265 }
2266
2267 ob->id.tag &= ~ID_TAG_PRE_EXISTING;
2269 LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
2270 psys->part->id.tag &= ~ID_TAG_PRE_EXISTING;
2271 }
2272
2274 for (a = 0; a < ob->totcol; a++) {
2275 ma = ob->mat[a];
2276 if (ma) {
2278 }
2279 }
2280
2281 matarar = BKE_object_material_array_p(ob);
2282 if (matarar) {
2283 for (a = 0; a < ob->totcol; a++) {
2284 ma = (*matarar)[a];
2285 if (ma) {
2287 }
2288 }
2289 }
2290 }
2291
2293 ob->data != nullptr)
2294 {
2295 ID *ob_data = static_cast<ID *>(ob->data);
2296 ob_data->tag &= ~ID_TAG_PRE_EXISTING;
2298 }
2299 }
2301 }
2302
2304 bmain, nullptr, nullptr, true, false, true); /* nullptr is all libraries. */
2305
2307 return OPERATOR_FINISHED;
2308}
2309
2311{
2312 static const EnumPropertyItem type_items[] = {
2313 {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
2314 {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
2316 "SELECT_OBDATA_MATERIAL",
2317 0,
2318 "Selected Objects, Data and Materials",
2319 ""},
2320 {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
2321 {0, nullptr, 0, nullptr, nullptr},
2322 };
2323
2324 /* identifiers */
2325 ot->name = "Make Local";
2326 ot->description = "Make library linked data-blocks local to this file";
2327 ot->idname = "OBJECT_OT_make_local";
2328
2329 /* API callbacks. */
2330 ot->invoke = WM_menu_invoke;
2331 ot->exec = make_local_exec;
2332 ot->poll = ED_operator_objectmode;
2333
2334 /* flags */
2335 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2336
2337 /* properties */
2338 ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
2339}
2340
2342
2343/* ------------------------------------------------------------------- */
2346
2348{
2349 /* An object is actually overridable only if it is in at least one local collection.
2350 * Unfortunately 'direct link' flag is not enough here. */
2351 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2352 if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) {
2353 return true;
2354 }
2355 }
2356 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
2357 if (!ID_IS_LINKED(scene) && BKE_collection_has_object(scene->master_collection, object)) {
2358 return true;
2359 }
2360 }
2361 return false;
2362}
2363
2365{
2366 Main *bmain = CTX_data_main(C);
2367 Scene *scene = CTX_data_scene(C);
2368 ViewLayer *view_layer = CTX_data_view_layer(C);
2370 ID *id_root = nullptr;
2371 bool is_override_instancing_object = false;
2372
2373 bool user_overrides_from_selected_objects = false;
2374
2375 if (!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2377 {
2379 BKE_reportf(op->reports,
2381 "Collection '%s' (instantiated by the active object) is not overridable",
2382 obact->instance_collection->id.name + 2);
2383 return OPERATOR_CANCELLED;
2384 }
2385
2386 id_root = &obact->instance_collection->id;
2387 is_override_instancing_object = true;
2388 user_overrides_from_selected_objects = false;
2389 }
2390 else if (!make_override_library_object_overridable_check(bmain, obact)) {
2391 const int i = RNA_property_int_get(op->ptr, op->type->prop);
2392 const uint collection_session_uid = *((const uint *)&i);
2393 if (collection_session_uid == MAIN_ID_SESSION_UID_UNSET) {
2394 BKE_reportf(op->reports,
2396 "Could not find an overridable root hierarchy for object '%s'",
2397 obact->id.name + 2);
2398 return OPERATOR_CANCELLED;
2399 }
2400 Collection *collection = static_cast<Collection *>(
2402 &collection_session_uid,
2403 sizeof(collection_session_uid),
2404 offsetof(ID, session_uid)));
2405 id_root = &collection->id;
2406 user_overrides_from_selected_objects = true;
2407 }
2408 /* Else, poll func ensures us that ID_IS_LINKED(obact) is true, or that it is already an
2409 * existing liboverride. */
2410 else {
2412 id_root = &obact->id;
2413 user_overrides_from_selected_objects = true;
2414 }
2415
2416 /* Make already existing selected liboverrides editable. */
2417 bool is_active_override = false;
2418 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2419 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2420 ob_iter->id.override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
2421 is_active_override = is_active_override || (&ob_iter->id == id_root);
2423 }
2424 }
2426 /* If the active object is a liboverride, there is no point going further, since in the weird
2427 * case where some other selected objects would be linked ones, there is no way to properly
2428 * create overrides for them currently.
2429 *
2430 * Could be added later if really needed, but would rather avoid that extra complexity here. */
2431 if (is_active_override) {
2432 return OPERATOR_FINISHED;
2433 }
2434
2436 const bool do_fully_editable = false;
2437
2438 GSet *user_overrides_objects_uids = do_fully_editable ? nullptr :
2441 __func__);
2442
2443 if (do_fully_editable) {
2444 /* Pass. */
2445 }
2446 else if (user_overrides_from_selected_objects) {
2447 /* Only selected objects can be 'user overrides'. */
2448 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2449 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2450 }
2452 }
2453 else {
2454 /* Only armatures inside the root collection (and their children) can be 'user overrides'. */
2456 if (ob_iter->type == OB_ARMATURE) {
2457 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2458 }
2459 }
2461 }
2462
2463 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2464
2465 /* For the time being, replace selected linked objects by their overrides in all collections.
2466 * While this may not be the absolute best behavior in all cases, in most common one this
2467 * should match the expected result. */
2468 if (user_overrides_objects_uids != nullptr) {
2469 LISTBASE_FOREACH (Collection *, coll_iter, &bmain->collections) {
2470 if (ID_IS_LINKED(coll_iter)) {
2471 continue;
2472 }
2473 LISTBASE_FOREACH (CollectionObject *, coll_ob_iter, &coll_iter->gobject) {
2474 if (BLI_gset_haskey(user_overrides_objects_uids,
2475 POINTER_FROM_UINT(coll_ob_iter->ob->id.session_uid)))
2476 {
2477 /* Tag for remapping when creating overrides. */
2478 coll_iter->id.tag |= ID_TAG_DOIT;
2479 break;
2480 }
2481 }
2482 }
2483 /* Also tag the Scene itself for remapping when creating overrides (includes the scene's master
2484 * collection too). */
2485 scene->id.tag |= ID_TAG_DOIT;
2486 }
2487
2488 ID *id_root_override;
2489 const bool success = BKE_lib_override_library_create(bmain,
2490 scene,
2491 view_layer,
2492 nullptr,
2493 id_root,
2494 id_root,
2495 &obact->id,
2496 &id_root_override,
2497 do_fully_editable);
2498
2499 if (!do_fully_editable) {
2500 /* Define liboverrides from selected/validated objects as user defined. */
2501 ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
2502 ID *id_iter;
2503 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2504 if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
2505 id_iter->override_library->hierarchy_root != id_hierarchy_root_override)
2506 {
2507 continue;
2508 }
2509 if (BLI_gset_haskey(user_overrides_objects_uids,
2511 {
2513 }
2514 }
2516
2517 BLI_gset_free(user_overrides_objects_uids, nullptr);
2518 }
2519
2520 if (success) {
2521 if (is_override_instancing_object) {
2522 /* Remove the instance empty from this scene, the items now have an overridden collection
2523 * instead. */
2524 base_free_and_unlink(bmain, scene, obact);
2525 }
2526 else {
2527 /* Remove the found root ID from the view layer. */
2528 switch (GS(id_root->name)) {
2529 case ID_GR: {
2530 Collection *collection_root = (Collection *)id_root;
2532 CollectionParent *, collection_parent, &collection_root->runtime.parents)
2533 {
2534 if (ID_IS_LINKED(collection_parent->collection) ||
2535 !BKE_view_layer_has_collection(view_layer, collection_parent->collection))
2536 {
2537 continue;
2538 }
2539 BKE_collection_child_remove(bmain, collection_parent->collection, collection_root);
2540 }
2541 break;
2542 }
2543 case ID_OB: {
2544 /* TODO: Not sure how well we can handle this case, when we don't have the collections
2545 * as reference containers... */
2546 break;
2547 }
2548 default:
2549 break;
2550 }
2551 }
2552 }
2553
2558
2559 return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2560}
2561
2562/* Set the object to override. */
2564 wmOperator *op,
2565 const wmEvent * /*event*/)
2566{
2567 Main *bmain = CTX_data_main(C);
2568 Scene *scene = CTX_data_scene(C);
2569 ViewLayer *view_layer = CTX_data_view_layer(C);
2570 Object *obact = context_active_object(C);
2571
2572 /* Sanity checks. */
2573 if (!scene || ID_IS_LINKED(scene) || !obact) {
2574 return OPERATOR_CANCELLED;
2575 }
2576
2577 if ((!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2580 {
2581 return make_override_library_exec(C, op);
2582 }
2583
2584 if (!ID_IS_LINKED(obact)) {
2585 if (ID_IS_OVERRIDE_LIBRARY_REAL(obact)) {
2586 return make_override_library_exec(C, op);
2587 }
2588 BKE_report(op->reports, RPT_ERROR, "Cannot make library override from a local object");
2589 return OPERATOR_CANCELLED;
2590 }
2591
2592 VectorSet<Collection *> potential_root_collections;
2593 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2594 /* Only check for linked collections from the same library, in the current view-layer. */
2595 if (!ID_IS_LINKED(&collection->id) || collection->id.lib != obact->id.lib ||
2596 !BKE_view_layer_has_collection(view_layer, collection))
2597 {
2598 continue;
2599 }
2600 if (!BKE_collection_has_object_recursive(collection, obact)) {
2601 continue;
2602 }
2603 if (potential_root_collections.is_empty()) {
2604 potential_root_collections.add_new(collection);
2605 }
2606 else {
2607 bool has_parents_in_potential_roots = false;
2608 bool is_potential_root = false;
2609 for (auto *collection_root_iter : potential_root_collections) {
2610 if (BKE_collection_has_collection(collection_root_iter, collection)) {
2611 BLI_assert_msg(!BKE_collection_has_collection(collection, collection_root_iter),
2612 "Invalid loop in collection hierarchy");
2613 /* Current potential root is already 'better' (higher up in the collection hierarchy)
2614 * than current collection, nothing else to do. */
2615 has_parents_in_potential_roots = true;
2616 }
2617 else if (BKE_collection_has_collection(collection, collection_root_iter)) {
2618 BLI_assert_msg(!BKE_collection_has_collection(collection_root_iter, collection),
2619 "Invalid loop in collection hierarchy");
2620 /* Current potential root is in the current collection's hierarchy, so the later is a
2621 * better candidate as root collection. */
2622 is_potential_root = true;
2623 potential_root_collections.remove(collection_root_iter);
2624 }
2625 else {
2626 /* Current potential root is not found in current collection's hierarchy, so the later
2627 * is a potential candidate as root collection. */
2628 is_potential_root = true;
2629 }
2630 }
2631 /* Only add the current collection as potential root if it is not a descendant of any
2632 * already known potential root collections. */
2633 if (is_potential_root && !has_parents_in_potential_roots) {
2634 potential_root_collections.add_new(collection);
2635 }
2636 }
2637 }
2638
2639 if (potential_root_collections.is_empty()) {
2641 return make_override_library_exec(C, op);
2642 }
2643 if (potential_root_collections.size() == 1) {
2644 Collection *collection_root = potential_root_collections.pop();
2645 RNA_property_int_set(op->ptr, op->type->prop, *((int *)&collection_root->id.session_uid));
2646 return make_override_library_exec(C, op);
2647 }
2648
2649 BKE_reportf(op->reports,
2650 RPT_ERROR,
2651 "Too many potential root collections (%d) for the override hierarchy, "
2652 "please use the Outliner instead",
2653 int(potential_root_collections.size()));
2654 return OPERATOR_CANCELLED;
2655}
2656
2658{
2659 Base *base_act = CTX_data_active_base(C);
2660 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2661 * misbehave if the active object is not also selected, see e.g. #120701. */
2662 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2663 return false;
2664 }
2665
2666 /* Object must be directly linked to be overridable. */
2667 Object *obact = base_act->object;
2668 return (
2669 ED_operator_objectmode(C) && obact != nullptr &&
2670 (ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) ||
2671 (obact->instance_collection != nullptr &&
2673}
2674
2676{
2677 /* identifiers */
2678 ot->name = "Make Library Override";
2679 ot->description =
2680 "Create a local override of the selected linked objects, and their hierarchy of "
2681 "dependencies";
2682 ot->idname = "OBJECT_OT_make_override_library";
2683
2684 /* API callbacks. */
2688
2689 /* flags */
2690 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2691
2692 /* properties */
2693 PropertyRNA *prop;
2694 prop = RNA_def_int(ot->srna,
2695 "collection",
2697 INT_MIN,
2698 INT_MAX,
2699 "Override Collection",
2700 "Session UID of the directly linked collection containing the selected "
2701 "object, to make an override from",
2702 INT_MIN,
2703 INT_MAX);
2705 ot->prop = prop;
2706}
2707
2709
2710/* ------------------------------------------------------------------- */
2713
2715{
2716 Base *base_act = CTX_data_active_base(C);
2717 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2718 * misbehave if the active object is not also selected, see e.g. #120701. */
2719 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2720 return false;
2721 }
2722
2723 /* Object must be local and an override. */
2724 Object *obact = base_act->object;
2725 return (ED_operator_objectmode(C) && obact != nullptr && !ID_IS_LINKED(obact) &&
2726 ID_IS_OVERRIDE_LIBRARY(obact));
2727}
2728
2730{
2731 Main *bmain = CTX_data_main(C);
2732
2733 /* Reset all selected liboverrides. */
2735 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2736 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, false);
2737 }
2738 }
2740
2744
2745 return OPERATOR_FINISHED;
2746}
2747
2749{
2750 /* identifiers */
2751 ot->name = "Reset Library Override";
2752 ot->description = "Reset the selected local overrides to their linked references values";
2753 ot->idname = "OBJECT_OT_reset_override_library";
2754
2755 /* API callbacks. */
2758
2759 /* flags */
2760 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2761}
2762
2764
2765/* ------------------------------------------------------------------- */
2768
2770{
2771 Main *bmain = CTX_data_main(C);
2772 ViewLayer *view_layer = CTX_data_view_layer(C);
2773 Scene *scene = CTX_data_scene(C);
2774 LinkNode *todo_objects = nullptr, *todo_object_iter;
2775
2776 /* Make already existing selected liboverrides editable. */
2777 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2778 if (ID_IS_LINKED(ob_iter)) {
2779 continue;
2780 }
2781 BLI_linklist_prepend_alloca(&todo_objects, ob_iter);
2782 }
2784
2785 for (todo_object_iter = todo_objects; todo_object_iter != nullptr;
2786 todo_object_iter = todo_object_iter->next)
2787 {
2788 Object *ob_iter = static_cast<Object *>(todo_object_iter->link);
2789 if (BKE_lib_override_library_is_hierarchy_leaf(bmain, &ob_iter->id)) {
2790 bool do_remap_active = false;
2791 BKE_view_layer_synced_ensure(scene, view_layer);
2792 if (BKE_view_layer_active_object_get(view_layer) == ob_iter) {
2793 do_remap_active = true;
2794 }
2795 BKE_libblock_remap(bmain,
2796 &ob_iter->id,
2797 ob_iter->id.override_library->reference,
2799 if (do_remap_active) {
2800 BKE_view_layer_synced_ensure(scene, view_layer);
2801 Object *ref_object = (Object *)ob_iter->id.override_library->reference;
2802 Base *basact = BKE_view_layer_base_find(view_layer, ref_object);
2803 if (basact != nullptr) {
2804 view_layer->basact = basact;
2805 }
2807 }
2808 BKE_id_delete(bmain, &ob_iter->id);
2809 }
2810 else {
2811 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, true);
2812 }
2813 }
2814
2819
2820 return OPERATOR_FINISHED;
2821}
2822
2824{
2825 /* identifiers */
2826 ot->name = "Clear Library Override";
2827 ot->description =
2828 "Delete the selected local overrides and relink their usages to the linked data-blocks if "
2829 "possible, else reset them and mark them as non editable";
2830 ot->idname = "OBJECT_OT_clear_override_library";
2831
2832 /* API callbacks. */
2835
2836 /* flags */
2837 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2838}
2839
2841
2842/* ------------------------------------------------------------------- */
2845
2846enum {
2849};
2850
2852{
2853 Main *bmain = CTX_data_main(C);
2854 Scene *scene = CTX_data_scene(C);
2855 ViewLayer *view_layer = CTX_data_view_layer(C);
2856 View3D *v3d = CTX_wm_view3d(C); /* ok if this is nullptr */
2857 const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
2858 const bool copy_collections = false;
2859 bool update_deps = false;
2860
2861 if (RNA_boolean_get(op->ptr, "object")) {
2862 if (flag == SELECT) {
2863 BKE_view_layer_selected_objects_tag(scene, view_layer, OB_DONE);
2864 single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
2865 }
2866 else {
2867 single_object_users(bmain, scene, v3d, 0, copy_collections);
2868 }
2869
2870 /* needed since object relationships may have changed */
2871 update_deps = true;
2872 }
2873
2874 if (RNA_boolean_get(op->ptr, "obdata")) {
2875 single_obdata_users(bmain, scene, view_layer, v3d, flag);
2876
2877 /* Needed since some IDs were remapped? (incl. mesh->texcomesh, see #73797). */
2878 update_deps = true;
2879 }
2880
2881 if (RNA_boolean_get(op->ptr, "material")) {
2882 single_mat_users(bmain, scene, view_layer, v3d, flag);
2883 }
2884
2885 if (RNA_boolean_get(op->ptr, "animation")) {
2886 single_object_action_users(bmain, scene, view_layer, v3d, flag);
2887 }
2888
2889 if (RNA_boolean_get(op->ptr, "obdata_animation")) {
2890 single_objectdata_action_users(bmain, scene, view_layer, v3d, flag);
2891 }
2892
2894
2896
2897 if (update_deps) {
2899 }
2900
2901 return OPERATOR_FINISHED;
2902}
2903
2905{
2907 C, op, event, IFACE_("Make Selected Objects Single-User"), IFACE_("Make Single"));
2908}
2909
2911{
2912 static const EnumPropertyItem type_items[] = {
2913 {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
2914 {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
2915 {0, nullptr, 0, nullptr, nullptr},
2916 };
2917
2918 /* identifiers */
2919 ot->name = "Make Single User";
2920 ot->description = "Make linked data local to each object";
2921 ot->idname = "OBJECT_OT_make_single_user";
2922
2923 /* Note that the invoke callback is only used from operator search, * otherwise this does
2924 * nothing by default. */
2925
2926 /* API callbacks. */
2927 ot->invoke = make_single_user_invoke;
2928 ot->exec = make_single_user_exec;
2929 ot->poll = ED_operator_objectmode;
2930
2931 /* flags */
2932 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2933
2934 /* properties */
2935 ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
2936
2937 RNA_def_boolean(ot->srna, "object", false, "Object", "Make single user objects");
2938 RNA_def_boolean(ot->srna, "obdata", false, "Object Data", "Make single user object data");
2940 ot->srna, "material", false, "Materials", "Make materials local to each data-block");
2941 RNA_def_boolean(ot->srna,
2942 "animation",
2943 false,
2944 "Object Animation",
2945 "Make object animation data local to each object");
2946 RNA_def_boolean(ot->srna,
2947 "obdata_animation",
2948 false,
2949 "Object Data Animation",
2950 "Make object data (mesh, curve etc.) animation data local to each object");
2951}
2952
2954
2955/* ------------------------------------------------------------------- */
2958
2959std::string drop_named_material_tooltip(bContext *C, const char *name, const int mval[2])
2960{
2961 int mat_slot = 0;
2962 Object *ob = ED_view3d_give_material_slot_under_cursor(C, mval, &mat_slot);
2963 if (ob == nullptr) {
2964 return {};
2965 }
2966 mat_slot = max_ii(mat_slot, 1);
2967
2968 Material *prev_mat = BKE_object_material_get(ob, mat_slot);
2969
2970 if (prev_mat) {
2971 return fmt::format(fmt::runtime(TIP_("Drop {} on {} (slot {}, replacing {})")),
2972 name,
2973 ob->id.name + 2,
2974 mat_slot,
2975 prev_mat->id.name + 2);
2976 }
2977 return fmt::format(
2978 fmt::runtime(TIP_("Drop {} on {} (slot {})")), name, ob->id.name + 2, mat_slot);
2979}
2980
2982 wmOperator *op,
2983 const wmEvent *event)
2984{
2985 Main *bmain = CTX_data_main(C);
2986 int mat_slot = 0;
2987 Object *ob = ED_view3d_give_material_slot_under_cursor(C, event->mval, &mat_slot);
2988 mat_slot = max_ii(mat_slot, 1);
2989
2991 bmain, op->ptr, ID_MA);
2992
2993 if (ob == nullptr || ma == nullptr) {
2994 return OPERATOR_CANCELLED;
2995 }
2996
2998
3000
3004
3005 return OPERATOR_FINISHED;
3006}
3007
3009{
3010 /* identifiers */
3011 ot->name = "Drop Named Material on Object";
3012 ot->idname = "OBJECT_OT_drop_named_material";
3013
3014 /* API callbacks. */
3017
3018 /* flags */
3019 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
3020
3021 /* properties */
3023}
3024
3026
3027/* ------------------------------------------------------------------- */
3030
3031std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2])
3032{
3033 const Object *ob = ED_view3d_give_object_under_cursor(C, mval);
3034 if (ob == nullptr) {
3035 return {};
3036 }
3037
3038 const uint32_t session_uid = RNA_int_get(properties, "session_uid");
3039 const ID *id = BKE_libblock_find_session_uid(CTX_data_main(C), ID_NT, session_uid);
3040 if (!id) {
3041 return {};
3042 }
3043
3044 return fmt::format(fmt::runtime(TIP_("Add modifier with node group \"{}\" on object \"{}\"")),
3045 id->name,
3046 ob->id.name);
3047}
3048
3050{
3051 tree->ensure_interface_cache();
3052 if (!tree->interface_outputs().is_empty()) {
3053 const bNodeTreeInterfaceSocket *first_output = tree->interface_outputs()[0];
3054 if (!first_output) {
3055 BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry output socket");
3056 return false;
3057 }
3058 const bke::bNodeSocketType *typeinfo = first_output->socket_typeinfo();
3059 const eNodeSocketDatatype type = typeinfo ? typeinfo->type : SOCK_CUSTOM;
3060 if (type != SOCK_GEOMETRY) {
3061 BKE_report(op->reports, RPT_ERROR, "The first output must be a geometry socket");
3062 return false;
3063 }
3064 }
3065 return true;
3066}
3067
3069 wmOperator *op,
3070 const wmEvent *event)
3071{
3073 if (!ob) {
3074 return OPERATOR_CANCELLED;
3075 }
3076
3077 Main *bmain = CTX_data_main(C);
3078 Scene *scene = CTX_data_scene(C);
3079
3080 const uint32_t uid = RNA_int_get(op->ptr, "session_uid");
3081 bNodeTree *node_tree = (bNodeTree *)BKE_libblock_find_session_uid(bmain, ID_NT, uid);
3082 if (!node_tree) {
3083 return OPERATOR_CANCELLED;
3084 }
3085 if (node_tree->type != NTREE_GEOMETRY) {
3086 BKE_report(op->reports, RPT_ERROR, "Node group must be a geometry node tree");
3087 return OPERATOR_CANCELLED;
3088 }
3089
3090 if (!check_geometry_node_group_sockets(op, node_tree)) {
3091 return OPERATOR_CANCELLED;
3092 }
3093
3095 op->reports, bmain, scene, ob, node_tree->id.name + 2, eModifierType_Nodes);
3096 if (!nmd) {
3097 BKE_report(op->reports, RPT_ERROR, "Could not add geometry nodes modifier");
3098 return OPERATOR_CANCELLED;
3099 }
3100
3101 if (!RNA_boolean_get(op->ptr, "show_datablock_in_modifier")) {
3103 }
3104
3105 nmd->node_group = node_tree;
3106 id_us_plus(&node_tree->id);
3108
3111
3112 return OPERATOR_FINISHED;
3113}
3114
3116{
3117 ot->name = "Drop Geometry Node Group on Object";
3118 ot->idname = "OBJECT_OT_drop_geometry_nodes";
3119
3122
3124
3125 PropertyRNA *prop = RNA_def_int(ot->srna,
3126 "session_uid",
3127 0,
3128 INT32_MIN,
3129 INT32_MAX,
3130 "Session UID",
3131 "Session UID of the geometry node group being dropped",
3132 INT32_MIN,
3133 INT32_MAX);
3135 RNA_def_boolean(ot->srna,
3136 "show_datablock_in_modifier",
3137 true,
3138 "Show the datablock selector in the modifier",
3139 "");
3140}
3141
3143
3144/* ------------------------------------------------------------------- */
3147
3149{
3150 ID *id;
3151 PropertyPointerRNA pprop;
3152
3154
3155 if (pprop.prop == nullptr) {
3156 BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
3157 return OPERATOR_CANCELLED;
3158 }
3159
3160 id = pprop.ptr.owner_id;
3161
3162 if (GS(id->name) == ID_OB) {
3163 Object *ob = (Object *)id;
3164 if (ob->data) {
3165 ID *id_data = static_cast<ID *>(ob->data);
3166
3167 if (GS(id_data->name) == ID_IM) {
3168 id_us_min(id_data);
3169 ob->data = nullptr;
3170 }
3171 else {
3172 BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
3173 return OPERATOR_CANCELLED;
3174 }
3175 }
3176 }
3177
3178 RNA_property_update(C, &pprop.ptr, pprop.prop);
3179
3180 return OPERATOR_FINISHED;
3181}
3182
3184{
3185 /* identifiers */
3186 ot->name = "Unlink";
3187 ot->idname = "OBJECT_OT_unlink_data";
3188
3189 /* API callbacks. */
3191
3192 /* flags */
3193 ot->flag = OPTYPE_INTERNAL;
3194}
3195
3197
3198} // 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
#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
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_COPY_DEFAULT
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
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
@ ID_REMAP_SKIP_INDIRECT_USAGE
#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_DONE
#define OB_TYPE_SUPPORT_PARVERT(_type)
@ PARVERT1
@ PARSKEL
@ PAROBJECT
@ PARTYPE
@ PARVERT3
@ PARBONE
@ 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)
@ OB_DUPLICOLLECTION
#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
#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
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#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 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