Blender V5.0
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_utf8.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"
78#include "UI_resources.hh"
79
80#include "RNA_access.hh"
81#include "RNA_define.hh"
82#include "RNA_enum_types.hh"
83
84#include "ED_armature.hh"
85#include "ED_curve.hh"
86#include "ED_gpencil_legacy.hh"
87#include "ED_grease_pencil.hh"
88#include "ED_mesh.hh"
89#include "ED_object.hh"
90#include "ED_screen.hh"
91#include "ED_view3d.hh"
92
93#include "ANIM_action.hh"
94#include "ANIM_animdata.hh"
95
96#include "MOD_nodes.hh"
97
98#include "object_intern.hh"
99
100namespace blender::ed::object {
101
102/* ------------------------------------------------------------------- */
105
110
112{
113 Main *bmain = CTX_data_main(C);
114 Scene *scene = CTX_data_scene(C);
115 View3D *v3d = CTX_wm_view3d(C);
117 ViewLayer *view_layer = CTX_data_view_layer(C);
118 Object *obedit = CTX_data_edit_object(C);
119 Object *par;
120
121#define INDEX_UNSET -1
122 int par1, par2, par3, par4;
123 par1 = par2 = par3 = par4 = INDEX_UNSET;
124
125 /* we need 1 to 3 selected vertices */
126
127 if (obedit->type == OB_MESH) {
128 Mesh *mesh = static_cast<Mesh *>(obedit->data);
129
130 EDBM_mesh_load(bmain, obedit);
131 EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
132
133 DEG_id_tag_update(static_cast<ID *>(obedit->data), 0);
134
135 BMEditMesh *em = mesh->runtime->edit_mesh.get();
136
138
139 /* Make sure the evaluated mesh is updated.
140 *
141 * Most reliable way is to update the tagged objects, which will ensure
142 * proper copy-on-evaluation update, but also will make sure all dependent
143 * objects are also up to date. */
145
146 BMVert *eve;
147 BMIter iter;
148 int curr_index;
149 BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, curr_index) {
151 if (par1 == INDEX_UNSET) {
152 par1 = curr_index;
153 }
154 else if (par2 == INDEX_UNSET) {
155 par2 = curr_index;
156 }
157 else if (par3 == INDEX_UNSET) {
158 par3 = curr_index;
159 }
160 else if (par4 == INDEX_UNSET) {
161 par4 = curr_index;
162 }
163 else {
164 break;
165 }
166 }
167 }
168 }
169 else if (ELEM(obedit->type, OB_SURF, OB_CURVES_LEGACY)) {
170 ListBase *editnurb = object_editcurve_get(obedit);
171 int curr_index = 0;
172 for (Nurb *nu = static_cast<Nurb *>(editnurb->first); nu != nullptr; nu = nu->next) {
173 if (nu->type == CU_BEZIER) {
174 BezTriple *bezt = nu->bezt;
175 for (int nurb_index = 0; nurb_index < nu->pntsu; nurb_index++, bezt++, curr_index++) {
176 if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
177 if (par1 == INDEX_UNSET) {
178 par1 = curr_index;
179 }
180 else if (par2 == INDEX_UNSET) {
181 par2 = curr_index;
182 }
183 else if (par3 == INDEX_UNSET) {
184 par3 = curr_index;
185 }
186 else if (par4 == INDEX_UNSET) {
187 par4 = curr_index;
188 }
189 else {
190 break;
191 }
192 }
193 }
194 }
195 else {
196 BPoint *bp = nu->bp;
197 const int points_num = nu->pntsu * nu->pntsv;
198 for (int nurb_index = 0; nurb_index < points_num; nurb_index++, bp++, curr_index++) {
199 if (bp->f1 & SELECT) {
200 if (par1 == INDEX_UNSET) {
201 par1 = curr_index;
202 }
203 else if (par2 == INDEX_UNSET) {
204 par2 = curr_index;
205 }
206 else if (par3 == INDEX_UNSET) {
207 par3 = curr_index;
208 }
209 else if (par4 == INDEX_UNSET) {
210 par4 = curr_index;
211 }
212 else {
213 break;
214 }
215 }
216 }
217 }
218 }
219 }
220 else if (obedit->type == OB_LATTICE) {
221 Lattice *lt = static_cast<Lattice *>(obedit->data);
222
223 const int points_num = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv *
224 lt->editlatt->latt->pntsw;
225 BPoint *bp = lt->editlatt->latt->def;
226 for (int curr_index = 0; curr_index < points_num; curr_index++, bp++) {
227 if (bp->f1 & SELECT) {
228 if (par1 == INDEX_UNSET) {
229 par1 = curr_index;
230 }
231 else if (par2 == INDEX_UNSET) {
232 par2 = curr_index;
233 }
234 else if (par3 == INDEX_UNSET) {
235 par3 = curr_index;
236 }
237 else if (par4 == INDEX_UNSET) {
238 par4 = curr_index;
239 }
240 else {
241 break;
242 }
243 }
244 }
245 }
246
247 if (par4 != INDEX_UNSET || par1 == INDEX_UNSET || (par2 != INDEX_UNSET && par3 == INDEX_UNSET)) {
248 BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
249 return OPERATOR_CANCELLED;
250 }
251
252 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
253 if (ob != obedit) {
255 par = obedit->parent;
256
257 if (BKE_object_parent_loop_check(par, ob)) {
258 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
259 }
260 else {
261 BKE_view_layer_synced_ensure(scene, view_layer);
262 ob->parent = BKE_view_layer_active_object_get(view_layer);
263 if (par3 != INDEX_UNSET) {
264 ob->partype = PARVERT3;
265 ob->par1 = par1;
266 ob->par2 = par2;
267 ob->par3 = par3;
268
269 /* inverse parent matrix */
270 invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
271 }
272 else {
273 ob->partype = PARVERT1;
274 ob->par1 = par1;
275
276 /* inverse parent matrix */
277 invert_m4_m4(ob->parentinv, BKE_object_calc_parent(depsgraph, scene, ob).ptr());
278 }
279 }
280 }
281 }
283
285
287
288 return OPERATOR_FINISHED;
289
290#undef INDEX_UNSET
291}
292
294{
295 /* identifiers */
296 ot->name = "Make Vertex Parent";
297 ot->description = "Parent selected objects to the selected vertices";
298 ot->idname = "OBJECT_OT_vertex_parent_set";
299
300 /* API callbacks. */
303
304 /* flags */
306}
307
309
310/* ------------------------------------------------------------------- */
313
316 "CLEAR",
317 0,
318 "Clear Parent",
319 "Completely clear the parenting relationship, including involved modifiers if any"},
321 "CLEAR_KEEP_TRANSFORM",
322 0,
323 "Clear and Keep Transformation",
324 "As 'Clear Parent', but keep the current visual transformations of the object"},
326 "CLEAR_INVERSE",
327 0,
328 "Clear Parent Inverse",
329 "Reset the transform corrections applied to the parenting relationship, does not remove "
330 "parenting itself"},
331 {0, nullptr, 0, nullptr, nullptr},
332};
333
334/* Helper for parent_clear() - Remove deform-modifiers associated with parent */
336{
338 ModifierData *md, *mdn;
339
340 /* assume that we only need to remove the first instance of matching deform modifier here */
341 for (md = static_cast<ModifierData *>(ob->modifiers.first); md; md = mdn) {
342 bool free = false;
343
344 mdn = md->next;
345
346 /* need to match types (modifier + parent) and references */
347 if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
349 if (amd->object == par) {
350 free = true;
351 }
352 }
353 else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
355 if (lmd->object == par) {
356 free = true;
357 }
358 }
359 else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVES_LEGACY)) {
361 if (cmd->object == par) {
362 free = true;
363 }
364 }
365
366 /* free modifier if match */
367 if (free) {
370 }
371 }
372 }
373}
374
375static void parent_clear_data(Object *ob)
376{
377 ob->parent = nullptr;
378 /* Set parent type to default PAROBJECT and reset enum explicitly, to prevent rna enum errors
379 * later. */
380 ob->partype = PAROBJECT;
381 ob->parsubstr[0] = '\0';
382}
383
384void parent_clear(Object *ob, const int type)
385{
386 if (ob->parent == nullptr) {
387 return;
388 }
390 switch (type) {
391 case CLEAR_PARENT_ALL: {
392 /* for deformers, remove corresponding modifiers to prevent
393 * a large number of modifiers building up */
395
396 /* clear parenting relationship completely */
398 break;
399 }
401 /* remove parent, and apply the parented transform
402 * result as object's local transforms */
404 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, false);
405 /* Don't recalculate the animation because it would change the transform
406 * instead of keeping it. */
407 flags &= ~ID_RECALC_ANIMATION;
408 break;
409 }
411 /* object stays parented, but the parent inverse
412 * (i.e. offset from parent to retain binding state)
413 * is cleared. In other words: nothing to do here! */
414 break;
415 }
416 }
417
418 /* Always clear parentinv matrix for sake of consistency, see #41950. */
419 unit_m4(ob->parentinv);
420
421 DEG_id_tag_update(&ob->id, flags);
422}
423
424/* NOTE: poll should check for editable scene. */
426{
427 Main *bmain = CTX_data_main(C);
428 /* Dependency graph must be evaluated for access to object's evaluated transform matrices. */
430 const int type = RNA_enum_get(op->ptr, "type");
431
432 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
433 parent_clear(ob, type);
434 }
436
440 return OPERATOR_FINISHED;
441}
442
444{
445 /* identifiers */
446 ot->name = "Clear Parent";
447 ot->description = "Clear the object's parenting";
448 ot->idname = "OBJECT_OT_parent_clear";
449
450 /* API callbacks. */
451 ot->invoke = WM_menu_invoke;
452 ot->exec = parent_clear_exec;
453
454 /* flags */
456
457 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
458}
459
461
462/* ------------------------------------------------------------------- */
465
466void parent_set(Object *ob, Object *par, const int type, const char *substr)
467{
468 /* Always clear parentinv matrix for sake of consistency, see #41950. */
469 unit_m4(ob->parentinv);
470
471 if (!par || BKE_object_parent_loop_check(par, ob)) {
473 return;
474 }
475
476 /* Other partypes are deprecated, do not use here! */
478
479 /* this could use some more checks */
480
481 ob->parent = par;
482 ob->partype &= ~PARTYPE;
483 ob->partype |= type;
484 STRNCPY_UTF8(ob->parsubstr, substr);
485}
486
488 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
489 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
490 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
491 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
492 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
493 {PAR_BONE, "BONE", 0, "Bone", ""},
494 {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
495 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
496 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
497 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
498 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
499 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
500 {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
501 {0, nullptr, 0, nullptr, nullptr},
502};
503
505 const bContext *C,
506 Scene *scene,
507 Depsgraph *depsgraph,
508 Object *const ob,
509 Object *const par,
510 Object *const parent_eval,
511 int partype,
512 const bool xmirror,
513 const bool keep_transform,
514 const int vert_par[3])
515{
516 Main *bmain = CTX_data_main(C);
517 bPoseChannel *pchan = nullptr;
518 bPoseChannel *pchan_eval = nullptr;
519
520 /* Preconditions. */
521 if (ob == par) {
522 /* Parenting an object to itself is impossible. */
523 return false;
524 }
525
526 if (BKE_object_parent_loop_check(par, ob)) {
527 BKE_report(reports, RPT_ERROR, "Loop in parents");
528 return false;
529 }
530
531 switch (partype) {
532 case PAR_FOLLOW:
533 case PAR_PATH_CONST: {
534 if (par->type != OB_CURVES_LEGACY) {
535 return false;
536 }
537 Curve *cu = static_cast<Curve *>(par->data);
538 Curve *cu_eval = static_cast<Curve *>(parent_eval->data);
539 if ((cu->flag & CU_PATH) == 0) {
540 cu->flag |= CU_PATH | CU_FOLLOW;
541 cu_eval->flag |= CU_PATH | CU_FOLLOW;
542 /* force creation of path data */
543 BKE_displist_make_curveTypes(depsgraph, scene, par, false);
544 }
545 else {
546 cu->flag |= CU_FOLLOW;
547 cu_eval->flag |= CU_FOLLOW;
548 }
549
550 /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
551 if (partype == PAR_FOLLOW) {
552 /* get or create F-Curve */
553 bAction *act = animrig::id_action_ensure(bmain, &cu->id);
554 PointerRNA id_ptr = RNA_id_pointer_create(&cu->id);
556 bmain, act, nullptr, &id_ptr, {"eval_time", 0});
557
558 /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
559 if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
561 }
562 }
563
564 /* fall back on regular parenting now (for follow only) */
565 if (partype == PAR_FOLLOW) {
566 partype = PAR_OBJECT;
567 }
568 break;
569 }
570 case PAR_BONE:
573 pchan_eval = BKE_pose_channel_active_if_bonecoll_visible(parent_eval);
574
575 if (pchan == nullptr || pchan_eval == nullptr) {
576 /* If pchan_eval is nullptr, pchan should also be nullptr. */
577 BLI_assert_msg(pchan == nullptr, "Missing evaluated bone data");
578 BKE_report(reports, RPT_ERROR, "No active bone");
579 return false;
580 }
581 }
582
583 /* Apply transformation of previous parenting. */
584 if (keep_transform) {
585 /* Was removed because of bug #23577, * but this can be handy in some cases too #32616, so
586 * make optional. */
587 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), false, false);
588 }
589
590 /* Set the parent (except for follow-path constraint option). */
591 if (partype != PAR_PATH_CONST) {
592 ob->parent = par;
593 /* Always clear parentinv matrix for sake of consistency, see #41950. */
594 unit_m4(ob->parentinv);
595 }
596
597 /* Handle types. */
598 if (pchan) {
599 STRNCPY_UTF8(ob->parsubstr, pchan->name);
600 }
601 else {
602 ob->parsubstr[0] = 0;
603 }
604
605 switch (partype) {
606 case PAR_PATH_CONST:
607 /* Don't do anything here, since this is not technically "parenting". */
608 break;
609 case PAR_CURVE:
610 case PAR_LATTICE:
611 case PAR_ARMATURE:
615 /* partype is now set to PAROBJECT so that invisible 'virtual'
616 * modifiers don't need to be created.
617 * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, * creating the
618 * virtual modifiers.
619 */
620 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
621 // ob->partype = PARSKEL; /* NOTE: DNA define, not operator property. */
622
623 /* BUT, to keep the deforms, we need a modifier, * and then we need to set the object
624 * that it uses
625 * - We need to ensure that the modifier we're adding doesn't already exist, * so we
626 * check this by assuming that the parent is selected too.
627 */
628 /* XXX currently this should only happen for meshes, curves, surfaces, * and lattices
629 * - this stuff isn't available for meta-balls yet. */
630 if (ELEM(
632 {
633 ModifierData *md;
634
635 switch (partype) {
636 case PAR_CURVE: /* curve deform */
637 if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
638 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Curve);
639 if (md) {
640 ((CurveModifierData *)md)->object = par;
641 }
642 if (par->runtime->curve_cache &&
643 par->runtime->curve_cache->anim_path_accum_length == nullptr)
644 {
646 }
647 }
648 break;
649 case PAR_LATTICE: /* lattice deform */
651 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Lattice);
652 if (md) {
653 ((LatticeModifierData *)md)->object = par;
654 }
655 }
656 break;
657 default: /* armature deform */
659 if (ob->type == OB_GREASE_PENCIL) {
660 md = modifier_add(
661 reports, bmain, scene, ob, nullptr, eModifierType_GreasePencilArmature);
662 if (md) {
663 ((GreasePencilArmatureModifierData *)md)->object = par;
664 }
665 }
666 else {
667 md = modifier_add(reports, bmain, scene, ob, nullptr, eModifierType_Armature);
668 if (md) {
669 ((ArmatureModifierData *)md)->object = par;
670 }
671 }
672 }
673 break;
674 }
675 }
676 break;
677 case PAR_BONE:
678 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
679 if (pchan->bone) {
681 pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
682 }
683 break;
685 ob->partype = PARBONE; /* NOTE: DNA define, not operator property. */
686 if (pchan->bone) {
688 pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
689 }
690 break;
691 case PAR_VERTEX:
692 ob->partype = PARVERT1;
693 ob->par1 = vert_par[0];
694 break;
695 case PAR_VERTEX_TRI:
696 ob->partype = PARVERT3;
697 copy_v3_v3_int(&ob->par1, vert_par);
698 break;
699 case PAR_OBJECT:
700 case PAR_FOLLOW:
701 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
702 break;
703 }
704
705 /* Constraint and set parent inverse. */
706 const bool is_armature_parent = ELEM(
708 if (partype == PAR_PATH_CONST) {
709 bConstraint *con;
711 float cmat[4][4], vec[3];
712
714
715 data = static_cast<bFollowPathConstraint *>(con->data);
716 data->tar = par;
717
719 depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, nullptr, cmat, scene->r.cfra);
720 sub_v3_v3v3(vec, ob->object_to_world().location(), cmat[3]);
721
722 copy_v3_v3(ob->loc, vec);
723 }
724 else if (is_armature_parent && (ob->type == OB_LATTICE) && (par->type == OB_ARMATURE) &&
725 (partype == PAR_ARMATURE_NAME))
726 {
728 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
729 }
730 else if (is_armature_parent && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
731 if (partype == PAR_ARMATURE_NAME) {
733 reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
734 }
735 else if (partype == PAR_ARMATURE_ENVELOPE) {
737 reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
738 }
739 else if (partype == PAR_ARMATURE_AUTO) {
740 WM_cursor_wait(true);
742 reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
743 WM_cursor_wait(false);
744 }
745 /* Get corrected inverse. */
746 ob->partype = PAROBJECT;
747
749 }
750 else if (is_armature_parent && (ob->type == OB_GREASE_PENCIL) && (par->type == OB_ARMATURE)) {
751 if (partype == PAR_ARMATURE_NAME) {
753 }
754 else if (partype == PAR_ARMATURE_ENVELOPE) {
756 }
757 else if (partype == PAR_ARMATURE_AUTO) {
759 }
760 /* get corrected inverse */
761 ob->partype = PAROBJECT;
762
764 }
765 else {
766 /* calculate inverse parent matrix */
768 }
769
772 return true;
773}
774
775bool parent_set(ReportList *reports,
776 const bContext *C,
777 Scene *scene,
778 Object *const ob,
779 Object *const par,
780 int partype,
781 const bool xmirror,
782 const bool keep_transform,
783 const int vert_par[3])
784{
786 Object *parent_eval = DEG_get_evaluated(depsgraph, par);
787
788 return parent_set_with_depsgraph(reports,
789 C,
790 scene,
791 depsgraph,
792 ob,
793 par,
794 parent_eval,
795 partype,
796 xmirror,
797 keep_transform,
798 vert_par);
799}
800
801static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
802{
803 const float *co_find = child->object_to_world().location();
804 if (is_tri) {
805 KDTreeNearest_3d nearest[3];
806 int tot;
807
808 tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
809 BLI_assert(tot == 3);
810 UNUSED_VARS(tot);
811
812 vert_par[0] = nearest[0].index;
813 vert_par[1] = nearest[1].index;
814 vert_par[2] = nearest[2].index;
815
816 BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
817 }
818 else {
819 vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, nullptr);
820 BLI_assert(vert_par[0] >= 0);
821 vert_par[1] = 0;
822 vert_par[2] = 0;
823 }
824}
825
835
837{
839 Object *parent_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
840
841 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
842 if (ob == parenting_context->par) {
843 /* parent_set() will fail (and thus return false), but this case
844 * shouldn't break this loop. It's expected that the active object is also selected. */
845 continue;
846 }
847
848 if (!parent_set_with_depsgraph(parenting_context->reports,
849 C,
850 parenting_context->scene,
851 depsgraph,
852 ob,
853 parenting_context->par,
854 parent_eval,
855 parenting_context->partype,
856 parenting_context->xmirror,
857 parenting_context->keep_transform,
858 nullptr))
859 {
860 return false;
861 }
862 }
864
865 return true;
866}
867
869 ParentingContext *parenting_context,
870 KDTree_3d *tree)
871{
872 int vert_par[3] = {0, 0, 0};
873
874 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
875 if (ob == parenting_context->par) {
876 /* parent_set() will fail (and thus return false), but this case
877 * shouldn't break this loop. It's expected that the active object is also selected. */
878 continue;
879 }
880
881 parent_set_vert_find(tree, ob, vert_par, parenting_context->is_vertex_tri);
882 if (!parent_set(parenting_context->reports,
883 C,
884 parenting_context->scene,
885 ob,
886 parenting_context->par,
887 parenting_context->partype,
888 parenting_context->xmirror,
889 parenting_context->keep_transform,
890 vert_par))
891 {
892 return false;
893 }
894 }
896 return true;
897}
898
899static bool parent_set_vertex_parent(bContext *C, ParentingContext *parenting_context)
900{
901 KDTree_3d *tree = nullptr;
902 int tree_tot;
903
905 Object *par_eval = DEG_get_evaluated(depsgraph, parenting_context->par);
906
907 tree = BKE_object_as_kdtree(par_eval, &tree_tot);
908 BLI_assert(tree != nullptr);
909
910 if (tree_tot < (parenting_context->is_vertex_tri ? 3 : 1)) {
911 BKE_report(parenting_context->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
912 BLI_kdtree_3d_free(tree);
913 return false;
914 }
915
916 const bool ok = parent_set_vertex_parent_with_kdtree(C, parenting_context, tree);
917 BLI_kdtree_3d_free(tree);
918 return ok;
919}
920
922{
923 const int partype = RNA_enum_get(op->ptr, "type");
924 ParentingContext parenting_context{};
925 parenting_context.reports = op->reports;
926 parenting_context.scene = CTX_data_scene(C);
927 parenting_context.par = context_active_object(C);
928 parenting_context.partype = partype;
929 parenting_context.is_vertex_tri = partype == PAR_VERTEX_TRI;
930 parenting_context.xmirror = RNA_boolean_get(op->ptr, "xmirror");
931 parenting_context.keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
932
933 bool ok;
934 if (ELEM(parenting_context.partype, PAR_VERTEX, PAR_VERTEX_TRI)) {
935 ok = parent_set_vertex_parent(C, &parenting_context);
936 }
937 else {
938 ok = parent_set_nonvertex_parent(C, &parenting_context);
939 }
940 if (!ok) {
941 return OPERATOR_CANCELLED;
942 }
943
944 Main *bmain = CTX_data_main(C);
948
949 return OPERATOR_FINISHED;
950}
951
953{
954 Object *parent = context_active_object(C);
955 uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
956 uiLayout *layout = UI_popup_menu_layout(pup);
957
958 PointerRNA opptr = layout->op(
959 ot, IFACE_("Object"), ICON_NONE, wm::OpCallContext::ExecDefault, UI_ITEM_NONE);
960 RNA_enum_set(&opptr, "type", PAR_OBJECT);
961 RNA_boolean_set(&opptr, "keep_transform", false);
962
963 opptr = layout->op(ot,
964 IFACE_("Object (Keep Transform)"),
965 ICON_NONE,
968 RNA_enum_set(&opptr, "type", PAR_OBJECT);
969 RNA_boolean_set(&opptr, "keep_transform", true);
970
971 PointerRNA op_ptr = layout->op(
972 "OBJECT_OT_parent_no_inverse_set", IFACE_("Object (Without Inverse)"), ICON_NONE);
973 RNA_boolean_set(&op_ptr, "keep_transform", false);
974
975 op_ptr = layout->op("OBJECT_OT_parent_no_inverse_set",
976 IFACE_("Object (Keep Transform Without Inverse)"),
977 ICON_NONE);
978 RNA_boolean_set(&op_ptr, "keep_transform", true);
979
980 struct {
981 bool armature_deform, empty_groups, envelope_weights, automatic_weights, attach_surface;
982 } can_support = {false};
983
984 CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) {
985 if (child == parent) {
986 continue;
987 }
988 if (ELEM(child->type,
989 OB_MESH,
991 OB_SURF,
992 OB_FONT,
994 OB_LATTICE))
995 {
996 can_support.armature_deform = true;
997 can_support.envelope_weights = true;
998 }
999 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL, OB_LATTICE)) {
1000 can_support.empty_groups = true;
1001 }
1002 if (ELEM(child->type, OB_MESH, OB_GREASE_PENCIL)) {
1003 can_support.automatic_weights = true;
1004 }
1005 if (child->type == OB_CURVES) {
1006 can_support.attach_surface = true;
1007 }
1008 }
1010
1011 if (parent->type == OB_ARMATURE) {
1012
1013 if (can_support.armature_deform) {
1014 op_ptr = layout->op(ot, IFACE_("Armature Deform"), ICON_NONE);
1015 RNA_enum_set(&op_ptr, "type", PAR_ARMATURE);
1016 }
1017 if (can_support.empty_groups) {
1018 op_ptr = layout->op(ot, IFACE_(" With Empty Groups"), ICON_NONE);
1019 RNA_enum_set(&op_ptr, "type", PAR_ARMATURE_NAME);
1020 }
1021 if (can_support.envelope_weights) {
1022 op_ptr = layout->op(ot, IFACE_(" With Envelope Weights"), ICON_NONE);
1023 RNA_enum_set(&op_ptr, "type", PAR_ARMATURE_ENVELOPE);
1024 }
1025 if (can_support.automatic_weights) {
1026 op_ptr = layout->op(ot, IFACE_(" With Automatic Weights"), ICON_NONE);
1027 RNA_enum_set(&op_ptr, "type", PAR_ARMATURE_AUTO);
1028 }
1029 op_ptr = layout->op(ot, IFACE_("Bone"), ICON_NONE);
1030 RNA_enum_set(&op_ptr, "type", PAR_BONE);
1031 op_ptr = layout->op(ot, IFACE_("Bone Relative"), ICON_NONE);
1032 RNA_enum_set(&op_ptr, "type", PAR_BONE_RELATIVE);
1033 }
1034 else if (parent->type == OB_CURVES_LEGACY) {
1035 op_ptr = layout->op(ot, IFACE_("Curve Deform"), ICON_NONE);
1036 RNA_enum_set(&op_ptr, "type", PAR_CURVE);
1037 op_ptr = layout->op(ot, IFACE_("Follow Path"), ICON_NONE);
1038 RNA_enum_set(&op_ptr, "type", PAR_FOLLOW);
1039 op_ptr = layout->op(ot, IFACE_("Path Constraint"), ICON_NONE);
1040 RNA_enum_set(&op_ptr, "type", PAR_PATH_CONST);
1041 }
1042 else if (parent->type == OB_LATTICE) {
1043 op_ptr = layout->op(ot, IFACE_("Lattice Deform"), ICON_NONE);
1044 RNA_enum_set(&op_ptr, "type", PAR_LATTICE);
1045 }
1046 else if (parent->type == OB_MESH) {
1047 if (can_support.attach_surface) {
1048 layout->op("CURVES_OT_surface_set", IFACE_("Object (Attach Curves to Surface)"), ICON_NONE);
1049 }
1050 }
1051
1052 /* vertex parenting */
1053 if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
1054 op_ptr = layout->op(ot, IFACE_("Vertex"), ICON_NONE);
1055 RNA_enum_set(&op_ptr, "type", PAR_VERTEX);
1056 op_ptr = layout->op(ot, IFACE_("Vertex (Triangle)"), ICON_NONE);
1057 RNA_enum_set(&op_ptr, "type", PAR_VERTEX_TRI);
1058 }
1059
1060 UI_popup_menu_end(C, pup);
1061
1062 return OPERATOR_INTERFACE;
1063}
1064
1066{
1067 if (RNA_property_is_set(op->ptr, op->type->prop)) {
1068 return parent_set_exec(C, op);
1069 }
1070 return parent_set_invoke_menu(C, op->type);
1071}
1072
1073static bool parent_set_poll_property(const bContext * /*C*/,
1074 wmOperator *op,
1075 const PropertyRNA *prop)
1076{
1077 const char *prop_id = RNA_property_identifier(prop);
1078
1079 /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
1080 if (STREQ(prop_id, "xmirror")) {
1081 const int type = RNA_enum_get(op->ptr, "type");
1083 return true;
1084 }
1085 return false;
1086 }
1087
1088 return true;
1089}
1090
1092{
1093 /* identifiers */
1094 ot->name = "Make Parent";
1095 ot->description = "Set the object's parenting";
1096 ot->idname = "OBJECT_OT_parent_set";
1097
1098 /* API callbacks. */
1099 ot->invoke = parent_set_invoke;
1100 ot->exec = parent_set_exec;
1102 ot->poll_property = parent_set_poll_property;
1103
1104 /* flags */
1105 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1106
1107 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
1109 ot->srna,
1110 "xmirror",
1111 false,
1112 "X Mirror",
1113 "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
1114 RNA_def_boolean(ot->srna,
1115 "keep_transform",
1116 false,
1117 "Keep Transform",
1118 "Apply transformation before parenting");
1119}
1120
1122
1123/* ------------------------------------------------------------------- */
1126
1128{
1129 Main *bmain = CTX_data_main(C);
1131
1132 const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
1133
1135
1136 /* context iterator */
1137 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1138 if (ob != par) {
1139 if (BKE_object_parent_loop_check(par, ob)) {
1140 BKE_report(op->reports, RPT_ERROR, "Loop in parents");
1141 }
1142 else {
1143 /* set recalc flags */
1145
1146 /* set parenting type for object - object only... */
1147 ob->parent = par;
1148 ob->partype = PAROBJECT; /* NOTE: DNA define, not operator property. */
1149
1150 if (keep_transform) {
1152 continue;
1153 }
1154
1155 /* clear inverse matrix and also the object location */
1156 unit_m4(ob->parentinv);
1157 memset(ob->loc, 0, sizeof(float[3]));
1158 }
1159 }
1160 }
1162
1166
1167 return OPERATOR_FINISHED;
1168}
1169
1171{
1172 /* identifiers */
1173 ot->name = "Make Parent without Inverse";
1174 ot->description = "Set the object's parenting without setting the inverse parent correction";
1175 ot->idname = "OBJECT_OT_parent_no_inverse_set";
1176
1177 /* API callbacks. */
1178 ot->exec = parent_noinv_set_exec;
1180
1181 /* flags */
1182 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1183
1184 RNA_def_boolean(ot->srna,
1185 "keep_transform",
1186 false,
1187 "Keep Transform",
1188 "Preserve the world transform throughout parenting");
1189}
1190
1192
1193/* ------------------------------------------------------------------- */
1196
1197enum {
1200};
1201
1203 {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
1205 "CLEAR_KEEP_TRANSFORM",
1206 0,
1207 "Clear and Keep Transformation (Clear Track)",
1208 ""},
1209 {0, nullptr, 0, nullptr, nullptr},
1210};
1211
1212/* NOTE: poll should check for editable scene. */
1214{
1215 Main *bmain = CTX_data_main(C);
1216 const int type = RNA_enum_get(op->ptr, "type");
1217
1218 if (CTX_data_edit_object(C)) {
1219 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
1220 return OPERATOR_CANCELLED;
1221 }
1222 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1223 bConstraint *con, *pcon;
1224
1225 /* remove track-object for old track */
1226 ob->track = nullptr;
1228
1229 /* also remove all tracking constraints */
1230 for (con = static_cast<bConstraint *>(ob->constraints.last); con; con = pcon) {
1231 pcon = con->prev;
1232 if (ELEM(con->type,
1236 {
1237 BKE_constraint_remove_ex(&ob->constraints, ob, con);
1238 }
1239 }
1240
1241 if (type == CLEAR_TRACK_KEEP_TRANSFORM) {
1242 BKE_object_apply_mat4(ob, ob->object_to_world().ptr(), true, true);
1243 }
1244 }
1246
1249
1250 return OPERATOR_FINISHED;
1251}
1252
1254{
1255 /* identifiers */
1256 ot->name = "Clear Track";
1257 ot->description = "Clear tracking constraint or flag from object";
1258 ot->idname = "OBJECT_OT_track_clear";
1259
1260 /* API callbacks. */
1261 ot->invoke = WM_menu_invoke;
1263
1264 ot->poll = ED_operator_objectmode;
1265
1266 /* flags */
1267 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1268
1269 ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1270}
1271
1273
1274/* ------------------------------------------------------------------- */
1277
1278enum {
1282};
1283
1285 {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
1286 {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""},
1287 {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
1288 {0, nullptr, 0, nullptr, nullptr},
1289};
1290
1292{
1293 Main *bmain = CTX_data_main(C);
1294 Object *obact = context_active_object(C);
1295
1296 const int type = RNA_enum_get(op->ptr, "type");
1297
1298 switch (type) {
1300 bConstraint *con;
1302
1303 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1304 if (ob != obact) {
1306
1307 data = static_cast<bDampTrackConstraint *>(con->data);
1308 data->tar = obact;
1309 DEG_id_tag_update(&ob->id,
1311
1312 /* Light, Camera and Speaker track differently by default */
1313 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1314 data->trackflag = TRACK_nZ;
1315 }
1316 }
1317 }
1319 break;
1320 }
1321 case CREATE_TRACK_TRACKTO: {
1322 bConstraint *con;
1324
1325 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1326 if (ob != obact) {
1328
1329 data = static_cast<bTrackToConstraint *>(con->data);
1330 data->tar = obact;
1331 DEG_id_tag_update(&ob->id,
1333
1334 /* Light, Camera and Speaker track differently by default */
1335 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1336 data->reserved1 = TRACK_nZ;
1337 data->reserved2 = UP_Y;
1338 }
1339 }
1340 }
1342 break;
1343 }
1345 bConstraint *con;
1347
1348 CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
1349 if (ob != obact) {
1351
1352 data = static_cast<bLockTrackConstraint *>(con->data);
1353 data->tar = obact;
1354 DEG_id_tag_update(&ob->id,
1356
1357 /* Light, Camera and Speaker track differently by default */
1358 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1359 data->trackflag = TRACK_nZ;
1360 data->lockflag = LOCK_Y;
1361 }
1362 }
1363 }
1365 break;
1366 }
1367 }
1368
1371
1372 return OPERATOR_FINISHED;
1373}
1374
1376{
1377 /* identifiers */
1378 ot->name = "Make Track";
1379 ot->description = "Make the object track another object, using various methods/constraints";
1380 ot->idname = "OBJECT_OT_track_set";
1381
1382 /* API callbacks. */
1383 ot->invoke = WM_menu_invoke;
1384 ot->exec = track_set_exec;
1385
1386 ot->poll = ED_operator_objectmode;
1387
1388 /* flags */
1389 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1390
1391 /* properties */
1392 ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
1393}
1394
1396
1397/* ------------------------------------------------------------------- */
1400
1401#if 0
1402static void link_to_scene(Main * /*bmain*/, ushort /*nr*/)
1403{
1404 Scene *sce = (Scene *)BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
1405 Base *base, *nbase;
1406
1407 if (sce == nullptr) {
1408 return;
1409 }
1410 if (sce->id.lib) {
1411 return;
1412 }
1413
1414 for (base = FIRSTBASE; base; base = base->next) {
1415 if (BASE_SELECTED(v3d, base)) {
1416 nbase = MEM_mallocN(sizeof(Base), "newbase");
1417 *nbase = *base;
1418 BLI_addhead(&(sce->base), nbase);
1419 id_us_plus((ID *)base->object);
1420 }
1421 }
1422}
1423#endif
1424
1426{
1427 Main *bmain = CTX_data_main(C);
1428 Scene *scene_to = static_cast<Scene *>(
1429 BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene")));
1430
1431 if (scene_to == nullptr) {
1432 BKE_report(op->reports, RPT_ERROR, "Could not find scene");
1433 return OPERATOR_CANCELLED;
1434 }
1435
1436 if (scene_to == CTX_data_scene(C)) {
1437 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
1438 return OPERATOR_CANCELLED;
1439 }
1440
1441 if (!BKE_id_is_editable(bmain, &scene_to->id)) {
1442 BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
1443 return OPERATOR_CANCELLED;
1444 }
1445
1446 Collection *collection_to = scene_to->master_collection;
1447 CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
1448 BKE_collection_object_add(bmain, collection_to, base->object);
1449 }
1451
1452 DEG_id_tag_update(&collection_to->id, ID_RECALC_HIERARCHY);
1453
1455
1456 /* redraw the 3D view because the object center points are colored differently */
1458
1459 /* one day multiple scenes will be visible, then we should have some update function for them
1460 */
1461 return OPERATOR_FINISHED;
1462}
1463
1464enum {
1473};
1474
1475/* Return true if make link data is allowed, false otherwise */
1476static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
1477{
1478 switch (type) {
1479 case MAKE_LINKS_OBDATA:
1480 if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
1481 return true;
1482 }
1483 break;
1486 /* Linking non-grease-pencil materials to a grease-pencil object causes issues.
1487 * We make sure that if one of the objects is a grease-pencil object, the other must be
1488 * as well. */
1489 ((ob_src->type == OB_GREASE_PENCIL) == (ob_dst->type == OB_GREASE_PENCIL)))
1490 {
1491 return true;
1492 }
1493 break;
1495 if (ob_dst->type == OB_EMPTY) {
1496 return true;
1497 }
1498 break;
1500 case MAKE_LINKS_GROUP:
1501 return true;
1503 if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
1504 return true;
1505 }
1506 break;
1507 case MAKE_LINKS_FONTS:
1508 if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT))
1509 {
1510 return true;
1511 }
1512 break;
1514 if ((ob_src->type == OB_GREASE_PENCIL) && (ob_dst->type == OB_GREASE_PENCIL)) {
1515 return true;
1516 }
1517 break;
1518 }
1519 return false;
1520}
1521
1523{
1524 Scene *scene = CTX_data_scene(C);
1525 Main *bmain = CTX_data_main(C);
1526 const int type = RNA_enum_get(op->ptr, "type");
1527 Object *ob_src;
1528 ID *obdata_id;
1529 int a;
1530
1531 /* collection */
1532 LinkNode *ob_collections = nullptr;
1533 bool is_cycle = false;
1534 bool is_lib = false;
1535
1536 ob_src = context_active_object(C);
1537
1538 /* avoid searching all collections in source object each time */
1539 if (type == MAKE_LINKS_GROUP) {
1540 ob_collections = BKE_object_groups(bmain, scene, ob_src);
1541 }
1542
1543 CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) {
1544 Object *ob_dst = base_dst->object;
1545
1546 if (ob_src != ob_dst) {
1547 if (allow_make_links_data(type, ob_src, ob_dst)) {
1548 obdata_id = static_cast<ID *>(ob_dst->data);
1549
1550 switch (type) {
1551 case MAKE_LINKS_OBDATA: /* obdata */
1552 id_us_min(obdata_id);
1553
1554 obdata_id = static_cast<ID *>(ob_src->data);
1555 id_us_plus(obdata_id);
1556 ob_dst->data = obdata_id;
1557
1558 /* if amount of material indices changed: */
1559 BKE_object_materials_sync_length(bmain, ob_dst, static_cast<ID *>(ob_dst->data));
1560
1561 if (ob_dst->type == OB_ARMATURE) {
1562 BKE_pose_rebuild(bmain, ob_dst, static_cast<bArmature *>(ob_dst->data), true);
1563 }
1565 break;
1567 /* new approach, using functions from kernel */
1568 for (a = 0; a < ob_src->totcol; a++) {
1569 Material *ma = BKE_object_material_get(ob_src, a + 1);
1570 /* also works with `ma == nullptr` */
1571 BKE_object_material_assign(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
1572 }
1574 break;
1576 BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
1577 if (ob_dst->data && ob_src->data) {
1578 if (BKE_id_is_editable(bmain, obdata_id)) {
1579 BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
1580 }
1581 else {
1582 is_lib = true;
1583 }
1584 }
1585 DEG_id_tag_update(&ob_dst->id,
1587 break;
1588 case MAKE_LINKS_GROUP: {
1589 LinkNode *collection_node;
1590
1591 /* first clear collections */
1592 BKE_object_groups_clear(bmain, scene, ob_dst);
1593
1594 /* now add in the collections from the link nodes */
1595 for (collection_node = ob_collections; collection_node;
1596 collection_node = collection_node->next)
1597 {
1598 if (ob_dst->instance_collection != collection_node->link) {
1600 bmain, static_cast<Collection *>(collection_node->link), ob_dst);
1601 }
1602 else {
1603 is_cycle = true;
1604 }
1605 }
1606 break;
1607 }
1609 ob_dst->instance_collection = ob_src->instance_collection;
1610 if (ob_dst->instance_collection) {
1611 id_us_plus(&ob_dst->instance_collection->id);
1612 ob_dst->transflag |= OB_DUPLICOLLECTION;
1613 }
1615 break;
1617 BKE_object_link_modifiers(ob_dst, ob_src);
1618 DEG_id_tag_update(&ob_dst->id,
1620 break;
1621 case MAKE_LINKS_FONTS: {
1622 Curve *cu_src = static_cast<Curve *>(ob_src->data);
1623 Curve *cu_dst = static_cast<Curve *>(ob_dst->data);
1624
1625 if (!BKE_id_is_editable(bmain, obdata_id)) {
1626 is_lib = true;
1627 break;
1628 }
1629
1630#define CURVE_VFONT_SET(vfont_member) \
1631 { \
1632 if (cu_dst->vfont_member) { \
1633 id_us_min(&cu_dst->vfont_member->id); \
1634 } \
1635 cu_dst->vfont_member = cu_src->vfont_member; \
1636 id_us_plus((ID *)cu_dst->vfont_member); \
1637 } \
1638 ((void)0)
1639
1640 CURVE_VFONT_SET(vfont);
1641 CURVE_VFONT_SET(vfontb);
1642 CURVE_VFONT_SET(vfonti);
1643 CURVE_VFONT_SET(vfontbi);
1644
1645#undef CURVE_VFONT_SET
1646
1647 DEG_id_tag_update(&ob_dst->id,
1649 break;
1650 }
1652 shaderfx_link(ob_dst, ob_src);
1653 DEG_id_tag_update(&ob_dst->id,
1655 break;
1656 }
1657 }
1658 }
1659 }
1661
1662 if (type == MAKE_LINKS_GROUP) {
1663 if (ob_collections) {
1664 BLI_linklist_free(ob_collections, nullptr);
1665 }
1666
1667 if (is_cycle) {
1668 BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
1669 }
1670 }
1671
1672 if (is_lib) {
1673 BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
1674 }
1675
1680
1681 return OPERATOR_FINISHED;
1682}
1683
1685{
1686 PropertyRNA *prop;
1687
1688 /* identifiers */
1689 ot->name = "Link Objects to Scene";
1690 ot->description = "Link selection to another scene";
1691 ot->idname = "OBJECT_OT_make_links_scene";
1692
1693 /* API callbacks. */
1694 ot->invoke = WM_enum_search_invoke;
1695 ot->exec = make_links_scene_exec;
1696 /* better not run the poll check */
1697
1698 /* flags */
1699 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1700
1701 /* properties */
1702 prop = RNA_def_enum(ot->srna, "scene", rna_enum_dummy_NULL_items, 0, "Scene", "");
1705 ot->prop = prop;
1706}
1707
1709{
1710 static const EnumPropertyItem make_links_items[] = {
1711 {MAKE_LINKS_OBDATA, "OBDATA", 0, "Link Object Data", "Replace assigned Object Data"},
1712 {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Link Materials", "Replace assigned Materials"},
1714 "ANIMATION",
1715 0,
1716 "Link Animation Data",
1717 "Replace assigned Animation Data"},
1718 {MAKE_LINKS_GROUP, "GROUPS", 0, "Link Collections", "Replace assigned Collections"},
1720 "DUPLICOLLECTION",
1721 0,
1722 "Link Instance Collection",
1723 "Replace assigned Collection Instance"},
1724 {MAKE_LINKS_FONTS, "FONTS", 0, "Link Fonts to Text", "Replace Text object Fonts"},
1726 {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Copy Modifiers", "Replace Modifiers"},
1728 "EFFECTS",
1729 0,
1730 "Copy Grease Pencil Effects",
1731 "Replace Grease Pencil Effects"},
1732 {0, nullptr, 0, nullptr, nullptr},
1733 };
1734
1735 /* identifiers */
1736 ot->name = "Link/Transfer Data";
1737 ot->description = "Transfer data from active object to selected objects";
1738 ot->idname = "OBJECT_OT_make_links_data";
1739
1740 /* API callbacks. */
1741 ot->exec = make_links_data_exec;
1743
1744 /* flags */
1745 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1746
1747 /* properties */
1748 ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
1749}
1750
1752
1753/* ------------------------------------------------------------------- */
1756
1758{
1759 /* NOTE: When dealing with linked data, we always make a local copy of it.
1760 * While in theory we could rather make it local when it only has one user, this is difficult
1761 * in practice with current code of this function. */
1762 return (id != nullptr && (id->us > 1 || ID_IS_LINKED(id)));
1763}
1764
1766 Collection *collection,
1767 const bool do_collection)
1768{
1769 if (do_collection) {
1770 BKE_libblock_relink_to_newid(bmain, &collection->id, 0);
1771 }
1772
1773 for (CollectionObject *cob = static_cast<CollectionObject *>(collection->gobject.first);
1774 cob != nullptr;
1775 cob = cob->next)
1776 {
1777 BKE_libblock_relink_to_newid(bmain, &cob->ob->id, 0);
1778 }
1779
1780 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
1781 libblock_relink_collection(bmain, child->collection, true);
1782 }
1783}
1784
1786 Scene *scene,
1787 Collection *collection,
1788 const int flag,
1789 const bool copy_collections,
1790 const bool is_master_collection)
1791{
1792 /* Generate new copies for objects in given collection and all its children, * and
1793 * optionally also copy collections themselves. */
1794 if (copy_collections && !is_master_collection) {
1795 Collection *collection_new = (Collection *)BKE_id_copy_ex(
1796 bmain, &collection->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
1797 id_us_min(&collection_new->id);
1798 collection = static_cast<Collection *>(ID_NEW_SET(collection, collection_new));
1799 }
1800
1801 /* We do not remap to new objects here, this is done in separate step. */
1802 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
1803 Object *ob = cob->ob;
1804 /* an object may be in more than one collection */
1805 if ((ob->id.newid == nullptr) && ((ob->flag & flag) == flag)) {
1806 if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
1807 ID_NEW_SET(
1808 ob,
1809 BKE_id_copy_ex(bmain, &ob->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS));
1810 id_us_min(ob->id.newid);
1811 }
1812 }
1813 }
1814
1815 /* Since master collection has already be duplicated as part of scene copy, * we do not
1816 * duplicate it here. However, this means its children need to be re-added manually here, *
1817 * otherwise their parent lists are empty (which will lead to crashes, see #63101). */
1818 CollectionChild *child_next, *child = static_cast<CollectionChild *>(collection->children.first);
1819 CollectionChild *orig_child_last = static_cast<CollectionChild *>(collection->children.last);
1820 for (; child != nullptr; child = child_next) {
1821 child_next = child->next;
1822 Collection *collection_child_new = single_object_users_collection(
1823 bmain, scene, child->collection, flag, copy_collections, false);
1824
1825 if (is_master_collection && copy_collections && child->collection != collection_child_new) {
1826 /* We do not want a collection sync here, our collections are in a complete uninitialized
1827 * state currently. With current code, that would lead to a memory leak - because of
1828 * reasons. It would be a useless loss of computing anyway, since caller has to fully
1829 * refresh view-layers/collections caching at the end. */
1830 BKE_collection_child_add_no_sync(bmain, collection, collection_child_new);
1831 BLI_remlink(&collection->children, child);
1832 MEM_freeN(child);
1833 if (child == orig_child_last) {
1834 break;
1835 }
1836 }
1837 }
1838
1839 return collection;
1840}
1841
1842/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
1844 Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
1845{
1846 /* duplicate all the objects of the scene (and matching collections, if required). */
1847 Collection *master_collection = scene->master_collection;
1848 single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
1849
1850 /* Will also handle the master collection. */
1851 BKE_libblock_relink_to_newid(bmain, &scene->id, 0);
1852
1853 /* Collection and object pointers in collections */
1854 libblock_relink_collection(bmain, scene->master_collection, false);
1855
1856 /* We also have to handle runtime things in UI. */
1857 if (v3d) {
1858 ID_NEW_REMAP(v3d->camera);
1859 }
1860
1861 /* Making single user may affect other scenes if they share
1862 * with current one some collections in their ViewLayer. */
1864}
1865
1866void object_single_user_make(Main *bmain, Scene *scene, Object *ob)
1867{
1868 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
1869 ob_iter->flag &= ~OB_DONE;
1870 }
1872
1873 /* tag only the one object */
1874 ob->flag |= OB_DONE;
1875
1876 single_object_users(bmain, scene, nullptr, OB_DONE, false);
1878}
1879
1881 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
1882{
1883 Light *la;
1884 Curve *cu;
1885 Camera *cam;
1886 Mesh *mesh;
1887 Lattice *lat;
1888 ID *id;
1889
1890 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
1891 if (BKE_id_is_editable(bmain, &ob->id)) {
1892 id = static_cast<ID *>(ob->data);
1895
1896 switch (ob->type) {
1897 case OB_EMPTY:
1898 ob->data = ID_NEW_SET(ob->data,
1899 BKE_id_copy_ex(bmain,
1900 static_cast<const ID *>(ob->data),
1901 nullptr,
1903 break;
1904 case OB_LAMP:
1905 ob->data = la = static_cast<Light *>(
1906 ID_NEW_SET(ob->data,
1907 BKE_id_copy_ex(bmain,
1908 static_cast<const ID *>(ob->data),
1909 nullptr,
1911 break;
1912 case OB_CAMERA:
1913 ob->data = cam = static_cast<Camera *>(
1914 ID_NEW_SET(ob->data,
1915 BKE_id_copy_ex(bmain,
1916 static_cast<const ID *>(ob->data),
1917 nullptr,
1920 break;
1921 case OB_MESH:
1922 /* Needed to remap texcomesh below. */
1923 ob->data = mesh = static_cast<Mesh *>(
1924 ID_NEW_SET(ob->data,
1925 BKE_id_copy_ex(bmain,
1926 static_cast<const ID *>(ob->data),
1927 nullptr,
1929 break;
1930 case OB_MBALL:
1931 ob->data = ID_NEW_SET(ob->data,
1932 BKE_id_copy_ex(bmain,
1933 static_cast<const ID *>(ob->data),
1934 nullptr,
1936 break;
1937 case OB_CURVES_LEGACY:
1938 case OB_SURF:
1939 case OB_FONT:
1940 ob->data = cu = static_cast<Curve *>(
1941 ID_NEW_SET(ob->data,
1942 BKE_id_copy_ex(bmain,
1943 static_cast<const ID *>(ob->data),
1944 nullptr,
1946 ID_NEW_REMAP(cu->bevobj);
1948 break;
1949 case OB_LATTICE:
1950 ob->data = lat = static_cast<Lattice *>(
1951 ID_NEW_SET(ob->data,
1952 BKE_id_copy_ex(bmain,
1953 static_cast<const ID *>(ob->data),
1954 nullptr,
1956 break;
1957 case OB_ARMATURE:
1959 ob->data = ID_NEW_SET(ob->data,
1960 BKE_id_copy_ex(bmain,
1961 static_cast<const ID *>(ob->data),
1962 nullptr,
1964 BKE_pose_rebuild(bmain, ob, static_cast<bArmature *>(ob->data), true);
1965 break;
1966 case OB_SPEAKER:
1967 ob->data = ID_NEW_SET(ob->data,
1968 BKE_id_copy_ex(bmain,
1969 static_cast<const ID *>(ob->data),
1970 nullptr,
1972 break;
1973 case OB_LIGHTPROBE:
1974 ob->data = ID_NEW_SET(ob->data,
1975 BKE_id_copy_ex(bmain,
1976 static_cast<const ID *>(ob->data),
1977 nullptr,
1979 break;
1980 case OB_CURVES:
1981 ob->data = ID_NEW_SET(ob->data,
1982 BKE_id_copy_ex(bmain,
1983 static_cast<const ID *>(ob->data),
1984 nullptr,
1986 break;
1987 case OB_POINTCLOUD:
1988 ob->data = ID_NEW_SET(ob->data,
1989 BKE_id_copy_ex(bmain,
1990 static_cast<const ID *>(ob->data),
1991 nullptr,
1993 break;
1994 case OB_VOLUME:
1995 ob->data = ID_NEW_SET(ob->data,
1996 BKE_id_copy_ex(bmain,
1997 static_cast<const ID *>(ob->data),
1998 nullptr,
2000 break;
2001 case OB_GREASE_PENCIL:
2002 ob->data = ID_NEW_SET(ob->data,
2003 BKE_id_copy_ex(bmain,
2004 static_cast<const ID *>(ob->data),
2005 nullptr,
2007 break;
2008 default:
2009 printf("ERROR %s: cannot copy %s\n", __func__, id->name);
2010 BLI_assert_msg(0, "This should never happen.");
2011
2012 /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
2013 BKE_scene_objects_iterator_end(&iter_macro);
2014 return;
2015 }
2016
2017 id_us_min(id);
2018 }
2019 }
2020 }
2022
2023 mesh = static_cast<Mesh *>(bmain->meshes.first);
2024 while (mesh) {
2025 ID_NEW_REMAP(mesh->texcomesh);
2026 mesh = static_cast<Mesh *>(mesh->id.next);
2027 }
2028}
2029
2030void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
2031{
2032 FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
2033 ob_iter->flag &= ~OB_DONE;
2034 }
2036
2037 /* Tag only the one object. */
2038 ob->flag |= OB_DONE;
2039
2040 single_obdata_users(bmain, scene, nullptr, nullptr, OB_DONE);
2041}
2042
2044 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2045{
2046 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2047 if (BKE_id_is_editable(bmain, &ob->id)) {
2048 AnimData *adt = BKE_animdata_from_id(&ob->id);
2049 if (adt == nullptr) {
2050 continue;
2051 }
2052
2053 ID *id_act = (ID *)adt->action;
2054 if (single_data_needs_duplication(id_act)) {
2057 }
2058 }
2059 }
2061}
2062
2064 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2065{
2066 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2067 if (BKE_id_is_editable(bmain, &ob->id) && ob->data != nullptr) {
2068 ID *id_obdata = (ID *)ob->data;
2069 AnimData *adt = BKE_animdata_from_id(id_obdata);
2070 if (adt == nullptr) {
2071 continue;
2072 }
2073
2074 ID *id_act = (ID *)adt->action;
2075 if (single_data_needs_duplication(id_act)) {
2078 }
2079 }
2080 }
2082}
2083
2085 Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
2086{
2087 Material *ma, *man;
2088 int a;
2089
2090 FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
2091 if (BKE_id_is_editable(bmain, &ob->id)) {
2092 for (a = 1; a <= ob->totcol; a++) {
2093 ma = BKE_object_material_get(ob, short(a));
2095 man = (Material *)BKE_id_copy_ex(
2096 bmain, &ma->id, nullptr, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS);
2097 man->id.us = 0;
2098 BKE_object_material_assign(bmain, ob, man, short(a), BKE_MAT_ASSIGN_USERPREF);
2099 }
2100 }
2101 }
2102 }
2104}
2105
2107
2108/* ------------------------------------------------------------------- */
2111
2112enum {
2117};
2118
2120{
2121 ID **id_pointer = cb_data->id_pointer;
2122 if (*id_pointer) {
2123 (*id_pointer)->tag &= ~ID_TAG_DOIT;
2124 }
2125
2126 return IDWALK_RET_NOP;
2127}
2128
2129static void tag_localizable_objects(bContext *C, const int mode)
2130{
2131 Main *bmain = CTX_data_main(C);
2132
2133 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2134
2135 /* Set ID_TAG_DOIT flag for all selected objects, so next we can check whether
2136 * object is gonna to become local or not.
2137 */
2138 CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
2139 object->id.tag |= ID_TAG_DOIT;
2140
2141 /* If obdata is also going to become local, mark it as such too. */
2142 if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
2143 ID *data_id = (ID *)object->data;
2144 data_id->tag |= ID_TAG_DOIT;
2145 }
2146 }
2148
2149 /* Also forbid making objects local if other library objects are using
2150 * them for modifiers or constraints.
2151 *
2152 * FIXME This is ignoring all other linked ID types potentially using the selected tagged
2153 * objects! Probably works fine in most 'usual' cases though.
2154 */
2155 for (Object *object = static_cast<Object *>(bmain->objects.first); object;
2156 object = static_cast<Object *>(object->id.next))
2157 {
2158 if ((object->id.tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(object)) {
2160 nullptr, &object->id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2161 }
2162 if (object->data) {
2163 ID *data_id = (ID *)object->data;
2164 if ((data_id->tag & ID_TAG_DOIT) == 0 && ID_IS_LINKED(data_id)) {
2166 nullptr, data_id, tag_localizable_looper, nullptr, IDWALK_READONLY);
2167 }
2168 }
2169 }
2170
2171 /* TODO(sergey): Drivers targets? */
2172}
2173
2179 const Scene *scene,
2180 ViewLayer *view_layer,
2181 Collection *collection)
2182{
2183 Object *ob;
2184 bool changed = false;
2185
2186 for (ob = static_cast<Object *>(bmain->objects.first); ob;
2187 ob = static_cast<Object *>(ob->id.next))
2188 {
2189 if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
2190 Base *base;
2191
2192 id_us_plus(&ob->id);
2193
2194 BKE_collection_object_add(bmain, collection, ob);
2195 BKE_view_layer_synced_ensure(scene, view_layer);
2196 base = BKE_view_layer_base_find(view_layer, ob);
2197 base_select(base, BA_SELECT);
2199
2200 changed = true;
2201 }
2202 }
2203
2204 return changed;
2205}
2206
2208{
2209 LISTBASE_FOREACH (NlaStrip *, strip, strips) {
2210 if (strip->act) {
2211 strip->act->id.tag &= ~ID_TAG_PRE_EXISTING;
2212 }
2213
2214 make_local_animdata_tag_strips(&strip->strips);
2215 }
2216}
2217
2218/* Tag all actions used by given animdata to be made local. */
2220{
2221 if (adt) {
2222 /* Actions - Active and Temp */
2223 if (adt->action) {
2225 }
2226 if (adt->tmpact) {
2228 }
2229
2230 /* Drivers */
2231 /* TODO: need to handle the ID-targets too? */
2232
2233 /* NLA Data */
2234 LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
2235 make_local_animdata_tag_strips(&nlt->strips);
2236 }
2237 }
2238}
2239
2241{
2242 if (ma) {
2245
2246 /* About node-trees: root one is made local together with material,
2247 * others we keep linked (for now). */
2248 }
2249}
2250
2252{
2253 Main *bmain = CTX_data_main(C);
2254 Material *ma, ***matarar;
2255 const int mode = RNA_enum_get(op->ptr, "type");
2256 int a;
2257
2258 /* NOTE: we (ab)use ID_TAG_PRE_EXISTING to cherry pick which ID to make local... */
2259 if (mode == MAKE_LOCAL_ALL) {
2260 const Scene *scene = CTX_data_scene(C);
2261 ViewLayer *view_layer = CTX_data_view_layer(C);
2262 Collection *collection = CTX_data_collection(C);
2263
2265
2266 /* De-select so the user can differentiate newly instanced from existing objects. */
2267 BKE_view_layer_base_deselect_all(scene, view_layer);
2268
2269 if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, collection)) {
2270 BKE_report(op->reports,
2271 RPT_INFO,
2272 "Orphan library objects added to the current scene to avoid loss");
2273 }
2274 }
2275 else {
2278
2279 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
2280 if ((ob->id.tag & ID_TAG_DOIT) == 0) {
2281 continue;
2282 }
2283
2284 ob->id.tag &= ~ID_TAG_PRE_EXISTING;
2286 LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
2287 psys->part->id.tag &= ~ID_TAG_PRE_EXISTING;
2288 }
2289
2291 for (a = 0; a < ob->totcol; a++) {
2292 ma = ob->mat[a];
2293 if (ma) {
2295 }
2296 }
2297
2298 matarar = BKE_object_material_array_p(ob);
2299 if (matarar) {
2300 for (a = 0; a < ob->totcol; a++) {
2301 ma = (*matarar)[a];
2302 if (ma) {
2304 }
2305 }
2306 }
2307 }
2308
2310 ob->data != nullptr)
2311 {
2312 ID *ob_data = static_cast<ID *>(ob->data);
2313 ob_data->tag &= ~ID_TAG_PRE_EXISTING;
2315 }
2316 }
2318 }
2319
2321 bmain, nullptr, nullptr, true, false, true); /* nullptr is all libraries. */
2322
2324 return OPERATOR_FINISHED;
2325}
2326
2328{
2329 static const EnumPropertyItem type_items[] = {
2330 {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
2331 {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
2333 "SELECT_OBDATA_MATERIAL",
2334 0,
2335 "Selected Objects, Data and Materials",
2336 ""},
2337 {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
2338 {0, nullptr, 0, nullptr, nullptr},
2339 };
2340
2341 /* identifiers */
2342 ot->name = "Make Local";
2343 ot->description = "Make library linked data-blocks local to this file";
2344 ot->idname = "OBJECT_OT_make_local";
2345
2346 /* API callbacks. */
2347 ot->invoke = WM_menu_invoke;
2348 ot->exec = make_local_exec;
2349 ot->poll = ED_operator_objectmode;
2350
2351 /* flags */
2352 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2353
2354 /* properties */
2355 ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
2356}
2357
2359
2360/* ------------------------------------------------------------------- */
2363
2365{
2366 /* An object is actually overridable only if it is in at least one local collection.
2367 * Unfortunately 'direct link' flag is not enough here. */
2368 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2369 if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) {
2370 return true;
2371 }
2372 }
2373 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
2374 if (!ID_IS_LINKED(scene) && BKE_collection_has_object(scene->master_collection, object)) {
2375 return true;
2376 }
2377 }
2378 return false;
2379}
2380
2382{
2383 Main *bmain = CTX_data_main(C);
2384 Scene *scene = CTX_data_scene(C);
2385 ViewLayer *view_layer = CTX_data_view_layer(C);
2387 ID *id_root = nullptr;
2388 bool is_override_instancing_object = false;
2389
2390 bool user_overrides_from_selected_objects = false;
2391
2392 if (!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2394 {
2396 BKE_reportf(op->reports,
2398 "Collection '%s' (instantiated by the active object) is not overridable",
2399 obact->instance_collection->id.name + 2);
2400 return OPERATOR_CANCELLED;
2401 }
2402
2403 id_root = &obact->instance_collection->id;
2404 is_override_instancing_object = true;
2405 user_overrides_from_selected_objects = false;
2406 }
2407 else if (!make_override_library_object_overridable_check(bmain, obact)) {
2408 const int i = RNA_property_int_get(op->ptr, op->type->prop);
2409 const uint collection_session_uid = *((const uint *)&i);
2410 if (collection_session_uid == MAIN_ID_SESSION_UID_UNSET) {
2411 BKE_reportf(op->reports,
2413 "Could not find an overridable root hierarchy for object '%s'",
2414 obact->id.name + 2);
2415 return OPERATOR_CANCELLED;
2416 }
2417 Collection *collection = static_cast<Collection *>(
2419 &collection_session_uid,
2420 sizeof(collection_session_uid),
2421 offsetof(ID, session_uid)));
2422 id_root = &collection->id;
2423 user_overrides_from_selected_objects = true;
2424 }
2425 /* Else, poll func ensures us that ID_IS_LINKED(obact) is true, or that it is already an
2426 * existing liboverride. */
2427 else {
2429 id_root = &obact->id;
2430 user_overrides_from_selected_objects = true;
2431 }
2432
2433 /* Make already existing selected liboverrides editable. */
2434 bool is_active_override = false;
2435 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2436 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2437 ob_iter->id.override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
2438 is_active_override = is_active_override || (&ob_iter->id == id_root);
2440 }
2441 }
2443 /* If the active object is a liboverride, there is no point going further, since in the weird
2444 * case where some other selected objects would be linked ones, there is no way to properly
2445 * create overrides for them currently.
2446 *
2447 * Could be added later if really needed, but would rather avoid that extra complexity here. */
2448 if (is_active_override) {
2449 return OPERATOR_FINISHED;
2450 }
2451
2453 const bool do_fully_editable = false;
2454
2455 GSet *user_overrides_objects_uids = do_fully_editable ? nullptr :
2458 __func__);
2459
2460 if (do_fully_editable) {
2461 /* Pass. */
2462 }
2463 else if (user_overrides_from_selected_objects) {
2464 /* Only selected objects can be 'user overrides'. */
2465 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2466 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2467 }
2469 }
2470 else {
2471 /* Only armatures inside the root collection (and their children) can be 'user overrides'. */
2473 if (ob_iter->type == OB_ARMATURE) {
2474 BLI_gset_add(user_overrides_objects_uids, POINTER_FROM_UINT(ob_iter->id.session_uid));
2475 }
2476 }
2478 }
2479
2480 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2481
2482 /* For the time being, replace selected linked objects by their overrides in all collections.
2483 * While this may not be the absolute best behavior in all cases, in most common one this
2484 * should match the expected result. */
2485 if (user_overrides_objects_uids != nullptr) {
2486 LISTBASE_FOREACH (Collection *, coll_iter, &bmain->collections) {
2487 if (ID_IS_LINKED(coll_iter)) {
2488 continue;
2489 }
2490 LISTBASE_FOREACH (CollectionObject *, coll_ob_iter, &coll_iter->gobject) {
2491 if (BLI_gset_haskey(user_overrides_objects_uids,
2492 POINTER_FROM_UINT(coll_ob_iter->ob->id.session_uid)))
2493 {
2494 /* Tag for remapping when creating overrides. */
2495 coll_iter->id.tag |= ID_TAG_DOIT;
2496 break;
2497 }
2498 }
2499 }
2500 /* Also tag the Scene itself for remapping when creating overrides (includes the scene's master
2501 * collection too). */
2502 scene->id.tag |= ID_TAG_DOIT;
2503 }
2504
2505 ID *id_root_override;
2506 const bool success = BKE_lib_override_library_create(bmain,
2507 scene,
2508 view_layer,
2509 nullptr,
2510 id_root,
2511 id_root,
2512 &obact->id,
2513 &id_root_override,
2514 do_fully_editable);
2515
2516 if (!do_fully_editable) {
2517 /* Define liboverrides from selected/validated objects as user defined. */
2518 ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
2519 ID *id_iter;
2520 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2521 if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
2522 id_iter->override_library->hierarchy_root != id_hierarchy_root_override)
2523 {
2524 continue;
2525 }
2526 if (BLI_gset_haskey(user_overrides_objects_uids,
2528 {
2530 }
2531 }
2533
2534 BLI_gset_free(user_overrides_objects_uids, nullptr);
2535 }
2536
2537 if (success) {
2538 if (is_override_instancing_object) {
2539 /* Remove the instance empty from this scene, the items now have an overridden collection
2540 * instead. */
2541 base_free_and_unlink(bmain, scene, obact);
2542 }
2543 else {
2544 /* Remove the found root ID from the view layer. */
2545 switch (GS(id_root->name)) {
2546 case ID_GR: {
2547 Collection *collection_root = (Collection *)id_root;
2549 CollectionParent *, collection_parent, &collection_root->runtime->parents)
2550 {
2551 if (ID_IS_LINKED(collection_parent->collection) ||
2552 !BKE_view_layer_has_collection(view_layer, collection_parent->collection))
2553 {
2554 continue;
2555 }
2556 BKE_collection_child_remove(bmain, collection_parent->collection, collection_root);
2557 }
2558 break;
2559 }
2560 case ID_OB: {
2561 /* TODO: Not sure how well we can handle this case, when we don't have the collections
2562 * as reference containers... */
2563 break;
2564 }
2565 default:
2566 break;
2567 }
2568 }
2569 }
2570
2575
2576 return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2577}
2578
2579/* Set the object to override. */
2581 wmOperator *op,
2582 const wmEvent * /*event*/)
2583{
2584 Main *bmain = CTX_data_main(C);
2585 Scene *scene = CTX_data_scene(C);
2586 ViewLayer *view_layer = CTX_data_view_layer(C);
2587 Object *obact = context_active_object(C);
2588
2589 /* Sanity checks. */
2590 if (!scene || ID_IS_LINKED(scene) || !obact) {
2591 return OPERATOR_CANCELLED;
2592 }
2593
2594 if ((!ID_IS_LINKED(obact) && obact->instance_collection != nullptr &&
2597 {
2598 return make_override_library_exec(C, op);
2599 }
2600
2601 if (!ID_IS_LINKED(obact)) {
2602 if (ID_IS_OVERRIDE_LIBRARY_REAL(obact)) {
2603 return make_override_library_exec(C, op);
2604 }
2605 BKE_report(op->reports, RPT_ERROR, "Cannot make library override from a local object");
2606 return OPERATOR_CANCELLED;
2607 }
2608
2609 VectorSet<Collection *> potential_root_collections;
2610 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2611 /* Only check for linked collections from the same library, in the current view-layer. */
2612 if (!ID_IS_LINKED(&collection->id) || collection->id.lib != obact->id.lib ||
2613 !BKE_view_layer_has_collection(view_layer, collection))
2614 {
2615 continue;
2616 }
2617 if (!BKE_collection_has_object_recursive(collection, obact)) {
2618 continue;
2619 }
2620 if (potential_root_collections.is_empty()) {
2621 potential_root_collections.add_new(collection);
2622 }
2623 else {
2624 bool has_parents_in_potential_roots = false;
2625 bool is_potential_root = false;
2626 for (auto *collection_root_iter : potential_root_collections) {
2627 if (BKE_collection_has_collection(collection_root_iter, collection)) {
2628 BLI_assert_msg(!BKE_collection_has_collection(collection, collection_root_iter),
2629 "Invalid loop in collection hierarchy");
2630 /* Current potential root is already 'better' (higher up in the collection hierarchy)
2631 * than current collection, nothing else to do. */
2632 has_parents_in_potential_roots = true;
2633 }
2634 else if (BKE_collection_has_collection(collection, collection_root_iter)) {
2635 BLI_assert_msg(!BKE_collection_has_collection(collection_root_iter, collection),
2636 "Invalid loop in collection hierarchy");
2637 /* Current potential root is in the current collection's hierarchy, so the later is a
2638 * better candidate as root collection. */
2639 is_potential_root = true;
2640 potential_root_collections.remove(collection_root_iter);
2641 }
2642 else {
2643 /* Current potential root is not found in current collection's hierarchy, so the later
2644 * is a potential candidate as root collection. */
2645 is_potential_root = true;
2646 }
2647 }
2648 /* Only add the current collection as potential root if it is not a descendant of any
2649 * already known potential root collections. */
2650 if (is_potential_root && !has_parents_in_potential_roots) {
2651 potential_root_collections.add_new(collection);
2652 }
2653 }
2654 }
2655
2656 if (potential_root_collections.is_empty()) {
2658 return make_override_library_exec(C, op);
2659 }
2660 if (potential_root_collections.size() == 1) {
2661 Collection *collection_root = potential_root_collections.pop();
2662 RNA_property_int_set(op->ptr, op->type->prop, *((int *)&collection_root->id.session_uid));
2663 return make_override_library_exec(C, op);
2664 }
2665
2666 BKE_reportf(op->reports,
2667 RPT_ERROR,
2668 "Too many potential root collections (%d) for the override hierarchy, "
2669 "please use the Outliner instead",
2670 int(potential_root_collections.size()));
2671 return OPERATOR_CANCELLED;
2672}
2673
2675{
2676 Base *base_act = CTX_data_active_base(C);
2677 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2678 * misbehave if the active object is not also selected, see e.g. #120701. */
2679 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2680 return false;
2681 }
2682
2683 /* Object must be directly linked to be overridable. */
2684 Object *obact = base_act->object;
2685 return (
2686 ED_operator_objectmode(C) && obact != nullptr &&
2687 (ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY(obact) ||
2688 (obact->instance_collection != nullptr &&
2690}
2691
2693{
2694 /* identifiers */
2695 ot->name = "Make Library Override";
2696 ot->description =
2697 "Create a local override of the selected linked objects, and their hierarchy of "
2698 "dependencies";
2699 ot->idname = "OBJECT_OT_make_override_library";
2700
2701 /* API callbacks. */
2705
2706 /* flags */
2707 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2708
2709 /* properties */
2710 PropertyRNA *prop;
2711 prop = RNA_def_int(ot->srna,
2712 "collection",
2714 INT_MIN,
2715 INT_MAX,
2716 "Override Collection",
2717 "Session UID of the directly linked collection containing the selected "
2718 "object, to make an override from",
2719 INT_MIN,
2720 INT_MAX);
2722 ot->prop = prop;
2723}
2724
2726
2727/* ------------------------------------------------------------------- */
2730
2732{
2733 Base *base_act = CTX_data_active_base(C);
2734 /* If the active object is not selected, do nothing (operators rely on selection too, they will
2735 * misbehave if the active object is not also selected, see e.g. #120701. */
2736 if ((base_act == nullptr) || ((base_act->flag & BASE_SELECTED) == 0)) {
2737 return false;
2738 }
2739
2740 /* Object must be local and an override. */
2741 Object *obact = base_act->object;
2742 return (ED_operator_objectmode(C) && obact != nullptr && !ID_IS_LINKED(obact) &&
2743 ID_IS_OVERRIDE_LIBRARY(obact));
2744}
2745
2747{
2748 Main *bmain = CTX_data_main(C);
2749
2750 /* Reset all selected liboverrides. */
2752 if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
2753 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, false);
2754 }
2755 }
2757
2761
2762 return OPERATOR_FINISHED;
2763}
2764
2766{
2767 /* identifiers */
2768 ot->name = "Reset Library Override";
2769 ot->description = "Reset the selected local overrides to their linked references values";
2770 ot->idname = "OBJECT_OT_reset_override_library";
2771
2772 /* API callbacks. */
2775
2776 /* flags */
2777 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2778}
2779
2781
2782/* ------------------------------------------------------------------- */
2785
2787{
2788 Main *bmain = CTX_data_main(C);
2789 ViewLayer *view_layer = CTX_data_view_layer(C);
2790 Scene *scene = CTX_data_scene(C);
2791 LinkNode *todo_objects = nullptr, *todo_object_iter;
2792
2793 /* Make already existing selected liboverrides editable. */
2794 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
2795 if (ID_IS_LINKED(ob_iter)) {
2796 continue;
2797 }
2798 BLI_linklist_prepend_alloca(&todo_objects, ob_iter);
2799 }
2801
2802 for (todo_object_iter = todo_objects; todo_object_iter != nullptr;
2803 todo_object_iter = todo_object_iter->next)
2804 {
2805 Object *ob_iter = static_cast<Object *>(todo_object_iter->link);
2806 if (BKE_lib_override_library_is_hierarchy_leaf(bmain, &ob_iter->id)) {
2807 bool do_remap_active = false;
2808 BKE_view_layer_synced_ensure(scene, view_layer);
2809 if (BKE_view_layer_active_object_get(view_layer) == ob_iter) {
2810 do_remap_active = true;
2811 }
2812 BKE_libblock_remap(bmain,
2813 &ob_iter->id,
2814 ob_iter->id.override_library->reference,
2816 if (do_remap_active) {
2817 BKE_view_layer_synced_ensure(scene, view_layer);
2818 Object *ref_object = (Object *)ob_iter->id.override_library->reference;
2819 Base *basact = BKE_view_layer_base_find(view_layer, ref_object);
2820 if (basact != nullptr) {
2821 view_layer->basact = basact;
2822 }
2824 }
2825 BKE_id_delete(bmain, &ob_iter->id);
2826 }
2827 else {
2828 BKE_lib_override_library_id_reset(bmain, &ob_iter->id, true);
2829 }
2830 }
2831
2836
2837 return OPERATOR_FINISHED;
2838}
2839
2841{
2842 /* identifiers */
2843 ot->name = "Clear Library Override";
2844 ot->description =
2845 "Delete the selected local overrides and relink their usages to the linked data-blocks if "
2846 "possible, else reset them and mark them as non editable";
2847 ot->idname = "OBJECT_OT_clear_override_library";
2848
2849 /* API callbacks. */
2852
2853 /* flags */
2854 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2855}
2856
2858
2859/* ------------------------------------------------------------------- */
2862
2863enum {
2866};
2867
2869{
2870 Main *bmain = CTX_data_main(C);
2871 Scene *scene = CTX_data_scene(C);
2872 ViewLayer *view_layer = CTX_data_view_layer(C);
2873 View3D *v3d = CTX_wm_view3d(C); /* ok if this is nullptr */
2874 const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
2875 const bool copy_collections = false;
2876 bool update_deps = false;
2877
2878 if (RNA_boolean_get(op->ptr, "object")) {
2879 if (flag == SELECT) {
2880 BKE_view_layer_selected_objects_tag(scene, view_layer, OB_DONE);
2881 single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
2882 }
2883 else {
2884 single_object_users(bmain, scene, v3d, 0, copy_collections);
2885 }
2886
2887 /* needed since object relationships may have changed */
2888 update_deps = true;
2889 }
2890
2891 if (RNA_boolean_get(op->ptr, "obdata")) {
2892 single_obdata_users(bmain, scene, view_layer, v3d, flag);
2893
2894 /* Needed since some IDs were remapped? (incl. mesh->texcomesh, see #73797). */
2895 update_deps = true;
2896 }
2897
2898 if (RNA_boolean_get(op->ptr, "material")) {
2899 single_mat_users(bmain, scene, view_layer, v3d, flag);
2900 }
2901
2902 if (RNA_boolean_get(op->ptr, "animation")) {
2903 single_object_action_users(bmain, scene, view_layer, v3d, flag);
2904 }
2905
2906 if (RNA_boolean_get(op->ptr, "obdata_animation")) {
2907 single_objectdata_action_users(bmain, scene, view_layer, v3d, flag);
2908 }
2909
2911
2913
2914 if (update_deps) {
2916 }
2917
2918 return OPERATOR_FINISHED;
2919}
2920
2922{
2924 C, op, event, IFACE_("Make Selected Objects Single-User"), IFACE_("Make Single"));
2925}
2926
2928{
2929 static const EnumPropertyItem type_items[] = {
2930 {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
2931 {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
2932 {0, nullptr, 0, nullptr, nullptr},
2933 };
2934
2935 /* identifiers */
2936 ot->name = "Make Single User";
2937 ot->description = "Make linked data local to each object";
2938 ot->idname = "OBJECT_OT_make_single_user";
2939
2940 /* Note that the invoke callback is only used from operator search, * otherwise this does
2941 * nothing by default. */
2942
2943 /* API callbacks. */
2944 ot->invoke = make_single_user_invoke;
2945 ot->exec = make_single_user_exec;
2946 ot->poll = ED_operator_objectmode;
2947
2948 /* flags */
2949 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2950
2951 /* properties */
2952 ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
2953
2954 RNA_def_boolean(ot->srna, "object", false, "Object", "Make single user objects");
2955 RNA_def_boolean(ot->srna, "obdata", false, "Object Data", "Make single user object data");
2957 ot->srna, "material", false, "Materials", "Make materials local to each data-block");
2958 RNA_def_boolean(ot->srna,
2959 "animation",
2960 false,
2961 "Object Animation",
2962 "Make object animation data local to each object");
2963 RNA_def_boolean(ot->srna,
2964 "obdata_animation",
2965 false,
2966 "Object Data Animation",
2967 "Make object data (mesh, curve etc.) animation data local to each object");
2968}
2969
2971
2972/* ------------------------------------------------------------------- */
2975
2976std::string drop_named_material_tooltip(bContext *C, const char *name, const int mval[2])
2977{
2978 int mat_slot = 0;
2979 Object *ob = ED_view3d_give_material_slot_under_cursor(C, mval, &mat_slot);
2980 if (ob == nullptr) {
2981 return {};
2982 }
2983 mat_slot = max_ii(mat_slot, 1);
2984
2985 Material *prev_mat = BKE_object_material_get(ob, mat_slot);
2986
2987 if (prev_mat) {
2988 return fmt::format(fmt::runtime(TIP_("Drop {} on {} (slot {}, replacing {})")),
2989 name,
2990 ob->id.name + 2,
2991 mat_slot,
2992 prev_mat->id.name + 2);
2993 }
2994 return fmt::format(
2995 fmt::runtime(TIP_("Drop {} on {} (slot {})")), name, ob->id.name + 2, mat_slot);
2996}
2997
2999 wmOperator *op,
3000 const wmEvent *event)
3001{
3002 Main *bmain = CTX_data_main(C);
3003 int mat_slot = 0;
3004 Object *ob = ED_view3d_give_material_slot_under_cursor(C, event->mval, &mat_slot);
3005 mat_slot = max_ii(mat_slot, 1);
3006
3008 bmain, op->ptr, ID_MA);
3009
3010 if (ob == nullptr || ma == nullptr) {
3011 return OPERATOR_CANCELLED;
3012 }
3013
3014 int assign_type = BKE_MAT_ASSIGN_USERPREF;
3015 /* When trying to assign to non-editable object data, assign to the object instead. */
3016 if (BKE_id_is_editable(bmain, &ob->id) && ob->data &&
3017 !BKE_id_is_editable(bmain, static_cast<ID *>(ob->data)))
3018 {
3019 assign_type = BKE_MAT_ASSIGN_OBJECT;
3020 }
3021
3022 BKE_object_material_assign(CTX_data_main(C), ob, ma, mat_slot, assign_type);
3023
3025
3029
3030 return OPERATOR_FINISHED;
3031}
3032
3034{
3035 /* identifiers */
3036 ot->name = "Drop Named Material on Object";
3037 ot->idname = "OBJECT_OT_drop_named_material";
3038
3039 /* API callbacks. */
3042
3043 /* flags */
3044 ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
3045
3046 /* properties */
3048}
3049
3051
3052/* ------------------------------------------------------------------- */
3055
3056std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2])
3057{
3058 const Object *ob = ED_view3d_give_object_under_cursor(C, mval);
3059 if (ob == nullptr) {
3060 return {};
3061 }
3062
3063 const uint32_t session_uid = RNA_int_get(properties, "session_uid");
3064 const ID *id = BKE_libblock_find_session_uid(CTX_data_main(C), ID_NT, session_uid);
3065 if (!id) {
3066 return {};
3067 }
3068
3069 return fmt::format(fmt::runtime(TIP_("Add modifier with node group \"{}\" on object \"{}\"")),
3070 id->name,
3071 ob->id.name);
3072}
3073
3075{
3076 tree->ensure_interface_cache();
3077 if (!tree->interface_outputs().is_empty()) {
3078 const bNodeTreeInterfaceSocket *first_output = tree->interface_outputs()[0];
3079 if (!first_output) {
3080 BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry output socket");
3081 return false;
3082 }
3083 const bke::bNodeSocketType *typeinfo = first_output->socket_typeinfo();
3084 const eNodeSocketDatatype type = typeinfo ? typeinfo->type : SOCK_CUSTOM;
3085 if (type != SOCK_GEOMETRY) {
3086 BKE_report(op->reports, RPT_ERROR, "The first output must be a geometry socket");
3087 return false;
3088 }
3089 }
3090 return true;
3091}
3092
3094 wmOperator *op,
3095 const wmEvent *event)
3096{
3098 if (!ob) {
3099 return OPERATOR_CANCELLED;
3100 }
3101
3102 Main *bmain = CTX_data_main(C);
3103 Scene *scene = CTX_data_scene(C);
3104
3105 const uint32_t uid = RNA_int_get(op->ptr, "session_uid");
3106 bNodeTree *node_tree = (bNodeTree *)BKE_libblock_find_session_uid(bmain, ID_NT, uid);
3107 if (!node_tree) {
3108 return OPERATOR_CANCELLED;
3109 }
3110 if (node_tree->type != NTREE_GEOMETRY) {
3111 BKE_report(op->reports, RPT_ERROR, "Node group must be a geometry node tree");
3112 return OPERATOR_CANCELLED;
3113 }
3114
3115 if (!check_geometry_node_group_sockets(op, node_tree)) {
3116 return OPERATOR_CANCELLED;
3117 }
3118
3120 op->reports, bmain, scene, ob, node_tree->id.name + 2, eModifierType_Nodes);
3121 if (!nmd) {
3122 BKE_report(op->reports, RPT_ERROR, "Could not add geometry nodes modifier");
3123 return OPERATOR_CANCELLED;
3124 }
3125
3126 if (!RNA_boolean_get(op->ptr, "show_datablock_in_modifier")) {
3128 }
3130 node_tree->geometry_node_asset_traits &&
3131 (node_tree->geometry_node_asset_traits->flag &
3134
3135 nmd->node_group = node_tree;
3136 id_us_plus(&node_tree->id);
3138
3141
3142 return OPERATOR_FINISHED;
3143}
3144
3146{
3147 ot->name = "Drop Geometry Node Group on Object";
3148 ot->idname = "OBJECT_OT_drop_geometry_nodes";
3149
3152
3154
3155 PropertyRNA *prop = RNA_def_int(ot->srna,
3156 "session_uid",
3157 0,
3158 INT32_MIN,
3159 INT32_MAX,
3160 "Session UID",
3161 "Session UID of the geometry node group being dropped",
3162 INT32_MIN,
3163 INT32_MAX);
3165 RNA_def_boolean(ot->srna,
3166 "show_datablock_in_modifier",
3167 true,
3168 "Show the data-block selector in the modifier",
3169 "");
3170}
3171
3173
3174/* ------------------------------------------------------------------- */
3177
3179{
3180 ID *id;
3181 PropertyPointerRNA pprop;
3182
3184
3185 if (pprop.prop == nullptr) {
3186 BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
3187 return OPERATOR_CANCELLED;
3188 }
3189
3190 id = pprop.ptr.owner_id;
3191
3192 if (GS(id->name) == ID_OB) {
3193 Object *ob = (Object *)id;
3194 if (ob->data) {
3195 ID *id_data = static_cast<ID *>(ob->data);
3196
3197 if (GS(id_data->name) == ID_IM) {
3198 id_us_min(id_data);
3199 ob->data = nullptr;
3200 }
3201 else {
3202 BKE_report(op->reports, RPT_ERROR, "Cannot unlink this object data");
3203 return OPERATOR_CANCELLED;
3204 }
3205 }
3206 }
3207
3208 RNA_property_update(C, &pprop.ptr, pprop.prop);
3209
3210 return OPERATOR_FINISHED;
3211}
3212
3214{
3215 /* identifiers */
3216 ot->name = "Unlink";
3217 ot->idname = "OBJECT_OT_unlink_data";
3218
3219 /* API callbacks. */
3221
3222 /* flags */
3223 ot->flag = OPTYPE_INTERNAL;
3224}
3225
3227
3228} // 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:369
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_animdata_duplicate_id_action(Main *bmain, ID *id, uint duplicate_flags)
Definition anim_data.cc:438
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
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:1728
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:2523
void id_us_plus(ID *id)
Definition lib_id.cc:358
#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:2129
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:2001
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_COPY_ACTIONS
@ LIB_ID_COPY_DEFAULT
void id_us_min(ID *id)
Definition lib_id.cc:366
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1224
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)
@ IDWALK_RET_NOP
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_READONLY
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:931
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:583
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
General operations, lookup, etc. for materials.
@ BKE_MAT_ASSIGN_USERPREF
@ BKE_MAT_ASSIGN_OBJECT
void BKE_object_materials_sync_length(Main *bmain, Object *ob, ID *id)
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
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR_INVALID_INPUT
Definition BKE_report.hh:40
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain)
Definition scene.cc:2621
#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])
#define STRNCPY_UTF8(dst, src)
unsigned int uint
unsigned short ushort
#define UNUSED_VARS(...)
#define SET_FLAG_FROM_TEST(value, test, flag)
#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_TAG_PRE_EXISTING
Definition DNA_ID.h:926
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
#define ID_NEW_REMAP(a)
Definition DNA_ID.h:760
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_HIERARCHY
Definition DNA_ID.h:1158
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1077
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1104
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:723
#define ID_IS_OVERRIDABLE_LIBRARY(_id)
Definition DNA_ID.h:716
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define ID_NEW_SET(_id, _idn)
Definition DNA_ID.h:756
@ LIBOVERRIDE_FLAG_SYSTEM_DEFINED
Definition DNA_ID.h:363
@ 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_FOLLOW
@ CU_PATH
@ CU_BEZIER
#define BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)
@ NODES_MODIFIER_HIDE_DATABLOCK_SELECTOR
@ NODES_MODIFIER_HIDE_MANAGE_PANEL
@ eModifierType_Curve
@ eModifierType_Lattice
@ eModifierType_GreasePencilArmature
@ eModifierType_Armature
@ eModifierType_Nodes
@ GEO_NODE_ASSET_HIDE_MODIFIER_MANAGE_PANEL
@ NTREE_GEOMETRY
eNodeSocketDatatype
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
Object is a sort of wrapper for general info.
@ PARVERT1
@ PARSKEL
@ PAROBJECT
@ PARTYPE
@ PARVERT3
@ PARBONE
#define OB_TYPE_SUPPORT_PARVERT(_type)
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
@ OB_DONE
@ OB_DUPLICOLLECTION
#define OB_TYPE_SUPPORT_MATERIAL(_type)
#define BASE_SELECTED(v3d, base)
@ USER_DUP_LINKED_ID
@ USER_DUP_ACT
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
#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:449
const EnumPropertyItem * RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
#define RNA_ENUM_ITEM_SEPR
Definition RNA_types.hh:676
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:432
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
@ PROP_HIDDEN
Definition RNA_types.hh:338
#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
#define NC_WINDOW
Definition WM_types.hh:375
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:498
#define ND_DRAW
Definition WM_types.hh:461
#define NC_WM
Definition WM_types.hh:374
#define NC_ANIMATION
Definition WM_types.hh:388
#define ND_LIB_OVERRIDE_CHANGED
Definition WM_types.hh:419
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define ND_MODIFIER
Definition WM_types.hh:462
#define ND_PARENT
Definition WM_types.hh:467
#define NC_MATERIAL
Definition WM_types.hh:380
#define ND_TRANSFORM
Definition WM_types.hh:456
#define ND_OB_SHADING
Definition WM_types.hh:457
#define ND_SPACE_VIEW3D
Definition WM_types.hh:528
#define NC_OBJECT
Definition WM_types.hh:379
#define ND_SHADING_LINKS
Definition WM_types.hh:479
#define NC_SPACE
Definition WM_types.hh:392
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:92
KDTree_3d * tree
#define GS(x)
#define INT32_MAX
#define INT32_MIN
#define printf(...)
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
#define INDEX_UNSET
bAction * id_action_ensure(Main *bmain, ID *id)
Definition animdata.cc:195
FCurve * action_fcurve_ensure_ex(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, const FCurveDescriptor &fcurve_descriptor)
void add_armature_automatic_weights(Scene &scene, Object &object, const Object &ob_armature)
void add_armature_envelope_weights(Scene &scene, Object &object, const Object &ob_armature)
bool add_armature_vertex_groups(Object &object, const Object &ob_armature)
ModifierData * modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
static wmOperatorStatus object_unlink_data_exec(bContext *C, wmOperator *op)
void single_obdata_user_make(Main *bmain, Scene *scene, Object *ob)
static bool make_override_library_object_overridable_check(Main *bmain, Object *object)
static wmOperatorStatus drop_geometry_nodes_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_make_local(wmOperatorType *ot)
static wmOperatorStatus clear_override_library_exec(bContext *C, wmOperator *)
void OBJECT_OT_clear_override_library(wmOperatorType *ot)
const EnumPropertyItem prop_clear_parent_types[]
static const EnumPropertyItem prop_clear_track_types[]
static bool parent_set_vertex_parent_with_kdtree(bContext *C, ParentingContext *parenting_context, KDTree_3d *tree)
void OBJECT_OT_unlink_data(wmOperatorType *ot)
static bool check_geometry_node_group_sockets(wmOperator *op, const bNodeTree *tree)
static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static bool parent_set_vertex_parent(bContext *C, ParentingContext *parenting_context)
static void parent_clear_data(Object *ob)
static void make_local_animdata_tag_strips(ListBase *strips)
static wmOperatorStatus object_track_clear_exec(bContext *C, wmOperator *op)
static wmOperatorStatus parent_set_invoke(bContext *C, wmOperator *op, const wmEvent *)
std::string drop_named_material_tooltip(bContext *C, const char *name, const int mval[2])
void OBJECT_OT_make_links_scene(wmOperatorType *ot)
std::string drop_geometry_nodes_tooltip(bContext *C, PointerRNA *properties, const int mval[2])
void OBJECT_OT_track_clear(wmOperatorType *ot)
static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static wmOperatorStatus make_links_scene_exec(bContext *C, wmOperator *op)
void OBJECT_OT_drop_named_material(wmOperatorType *ot)
const EnumPropertyItem prop_make_parent_types[]
void base_select(Base *base, eObjectSelect_Mode mode)
void parent_clear(Object *ob, int type)
void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static wmOperatorStatus make_single_user_exec(bContext *C, wmOperator *op)
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
static bool single_data_needs_duplication(ID *id)
static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
void OBJECT_OT_track_set(wmOperatorType *ot)
static const EnumPropertyItem prop_make_track_types[]
static wmOperatorStatus track_set_exec(bContext *C, wmOperator *op)
static wmOperatorStatus vertex_parent_set_exec(bContext *C, wmOperator *op)
void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
static void single_objectdata_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static wmOperatorStatus parent_clear_exec(bContext *C, wmOperator *op)
bool parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *const ob, Object *const par, int partype, bool xmirror, bool keep_transform, const int vert_par[3])
static wmOperatorStatus make_local_exec(bContext *C, wmOperator *op)
static wmOperatorStatus make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *)
Object * context_active_object(const bContext *C)
void OBJECT_OT_make_links_data(wmOperatorType *ot)
static wmOperatorStatus parent_noinv_set_exec(bContext *C, wmOperator *op)
static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
static wmOperatorStatus reset_override_library_exec(bContext *C, wmOperator *)
static wmOperatorStatus make_links_data_exec(bContext *C, wmOperator *op)
static bool reset_clear_override_library_poll(bContext *C)
static bool make_override_library_poll(bContext *C)
void OBJECT_OT_reset_override_library(wmOperatorType *ot)
void OBJECT_OT_parent_clear(wmOperatorType *ot)
static void make_local_animdata_tag(AnimData *adt)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
void OBJECT_OT_make_override_library(wmOperatorType *ot)
static bool parent_set_nonvertex_parent(bContext *C, ParentingContext *parenting_context)
void OBJECT_OT_drop_geometry_nodes(wmOperatorType *ot)
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
void OBJECT_OT_make_single_user(wmOperatorType *ot)
static wmOperatorStatus parent_set_invoke_menu(bContext *C, wmOperatorType *ot)
static bool vertex_parent_set_poll(bContext *C)
static void make_local_material_tag(Material *ma)
static void libblock_relink_collection(Main *bmain, Collection *collection, const bool do_collection)
static void tag_localizable_objects(bContext *C, const int mode)
static bool parent_set_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
static wmOperatorStatus drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_parent_set(wmOperatorType *ot)
static bool parent_set_with_depsgraph(ReportList *reports, const bContext *C, Scene *scene, Depsgraph *depsgraph, Object *const ob, Object *const par, Object *const parent_eval, int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
static wmOperatorStatus parent_set_exec(bContext *C, wmOperator *op)
static int tag_localizable_looper(LibraryIDLinkCallbackData *cb_data)
static bool make_local_all__instance_indirect_unused(Main *bmain, const Scene *scene, ViewLayer *view_layer, Collection *collection)
void object_single_user_make(Main *bmain, Scene *scene, Object *ob)
static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
static Collection * single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections, const bool is_master_collection)
static wmOperatorStatus make_override_library_exec(bContext *C, wmOperator *op)
static wmOperatorStatus make_single_user_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void shaderfx_link(Object *dst, Object *src)
#define CURVE_VFONT_SET(vfont_member)
const char * name
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
CollectionRuntimeHandle * 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:348
struct ID * hierarchy_root
Definition DNA_ID.h:344
struct ID * reference
Definition DNA_ID.h:334
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
int us
Definition DNA_ID.h:443
struct ID * newid
Definition DNA_ID.h:418
IDOverrideLibrary * override_library
Definition DNA_ID.h:494
void * next
Definition DNA_ID.h:417
unsigned int session_uid
Definition DNA_ID.h:462
struct EditLatt * editlatt
struct BPoint * def
void * link
struct LinkNode * next
void * last
void * first
ListBase scenes
Definition BKE_main.hh:278
ListBase meshes
Definition BKE_main.hh:281
ListBase collections
Definition BKE_main.hh:298
ListBase objects
Definition BKE_main.hh:280
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:146
struct Collection * master_collection
struct ToolSettings * toolsettings
struct RenderData r
struct Object * camera
struct Base * basact
struct bConstraint * prev
struct GeometryNodeAssetTraits * geometry_node_asset_traits
struct Bone * bone
Defines a socket type.
Definition BKE_node.hh:158
eNodeSocketDatatype type
Definition BKE_node.hh:193
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
int mval[2]
Definition WM_types.hh:763
PropertyRNA * prop
Definition WM_types.hh:1139
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:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
wmOperatorStatus WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *)
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, std::optional< std::string > message)
uint8_t flag
Definition wm_window.cc:145