Blender V4.5
wm_files_link.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cctype>
12#include <cerrno>
13#include <cfloat>
14#include <cstring>
15
16#include "CLG_log.h"
17
18#include "DNA_ID.h"
19#include "DNA_scene_types.h"
20#include "DNA_screen_types.h"
22
23#include "BLI_fileops.h"
24#include "BLI_map.hh"
25#include "BLI_path_utils.hh"
26#include "BLI_string.h"
27
28#include "BLO_readfile.hh"
29
30#include "BKE_armature.hh"
31#include "BKE_blendfile.hh"
33#include "BKE_context.hh"
34#include "BKE_global.hh"
35#include "BKE_key.hh"
36#include "BKE_layer.hh"
37#include "BKE_lib_id.hh"
38#include "BKE_lib_override.hh"
39#include "BKE_lib_query.hh"
40#include "BKE_lib_remap.hh"
41#include "BKE_library.hh"
42#include "BKE_main.hh"
43#include "BKE_material.hh"
44#include "BKE_object.hh"
45#include "BKE_report.hh"
46#include "BKE_rigidbody.h"
47#include "BKE_scene.hh"
48
49#include "BKE_idtype.hh"
50
51#include "DEG_depsgraph.hh"
53
55
56#include "ED_datafiles.h"
57#include "ED_screen.hh"
58
59#include "RNA_access.hh"
60#include "RNA_define.hh"
61
62#include "WM_api.hh"
63#include "WM_types.hh"
64
65#include "wm_files.hh"
66
67static CLG_LogRef LOG = {"wm.files_link"};
68
69/* -------------------------------------------------------------------- */
72
74{
76 /* NOTE(@sergey): Linking changes active object which is pretty useful in general,
77 * but which totally confuses edit mode (i.e. it becoming not so obvious
78 * to leave from edit mode and invalid tools in toolbar might be displayed)
79 * so disable link/append when in edit mode. */
81 return false;
82 }
83
84 return true;
85 }
86
87 return false;
88}
89
91 wmOperator *op,
92 const wmEvent * /*event*/)
93{
94 if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
95 const char *blendfile_path = BKE_main_blendfile_path_from_global();
96 if (G.filepath_last_library[0] != '\0') {
97 RNA_string_set(op->ptr, "filepath", G.filepath_last_library);
98 }
99 else if (blendfile_path[0] != '\0') {
100 char dirpath[FILE_MAX];
101 BLI_path_split_dir_part(blendfile_path, dirpath, sizeof(dirpath));
102 RNA_string_set(op->ptr, "filepath", dirpath);
103 }
104 }
105
108}
109
111{
112 PropertyRNA *prop;
113 int flag = 0;
114
115 if (RNA_boolean_get(op->ptr, "autoselect")) {
117 }
118 if (RNA_boolean_get(op->ptr, "active_collection")) {
120 }
121 if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
122 RNA_property_boolean_get(op->ptr, prop))
123 {
125 }
126 if (RNA_boolean_get(op->ptr, "link")) {
127 flag |= FILE_LINK;
128 }
129 else {
130 if (RNA_boolean_get(op->ptr, "use_recursive")) {
132 }
133 if (RNA_boolean_get(op->ptr, "set_fake")) {
135 }
136 if (RNA_boolean_get(op->ptr, "do_reuse_local_id")) {
138 }
139 if (RNA_boolean_get(op->ptr, "clear_asset_data")) {
141 }
142 }
143 if (RNA_boolean_get(op->ptr, "instance_collections")) {
145 }
146 if (RNA_boolean_get(op->ptr, "instance_object_data")) {
148 }
149
150 return flag;
151}
152
159 const char *filepath,
160 const char *group,
161 const char *name,
162 const bool do_append)
163{
164 short idcode;
165
166 if (!group || !name) {
167 CLOG_WARN(&LOG, "Skipping %s", filepath);
168 return false;
169 }
170
171 idcode = BKE_idtype_idcode_from_name(group);
172
173 if (!BKE_idtype_idcode_is_linkable(idcode) ||
174 (!do_append && BKE_idtype_idcode_is_only_appendable(idcode)))
175 {
176 if (reports) {
177 if (do_append) {
180 "Can't append data-block '%s' of type '%s'",
181 name,
182 group);
183 }
184 else {
187 "Can't link data-block '%s' of type '%s'",
188 name,
189 group);
190 }
191 }
192 return false;
193 }
194
195 return true;
196}
197
199{
200 Main *bmain = CTX_data_main(C);
201 Scene *scene = CTX_data_scene(C);
202 ViewLayer *view_layer = CTX_data_view_layer(C);
203 PropertyRNA *prop;
204 BlendfileLinkAppendContext *lapp_context;
205 char filepath[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA],
206 relname[FILE_MAX];
207 char *group, *name;
208 int totfiles = 0;
209
210 RNA_string_get(op->ptr, "filename", relname);
211 RNA_string_get(op->ptr, "directory", root);
212
213 BLI_path_join(filepath, sizeof(filepath), root, relname);
214
215 /* Test if we have a valid data. */
216 const bool is_librarypath_valid = BKE_blendfile_library_path_explode(
217 filepath, libname, &group, &name);
218
219 /* NOTE: Need to also check filepath, as typically libname is an empty string here (when trying
220 * to append from current file from the file-browser e.g.). */
221 if (BLI_path_cmp(BKE_main_blendfile_path(bmain), filepath) == 0 ||
222 BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0)
223 {
224 BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", filepath);
225 return OPERATOR_CANCELLED;
226 }
227 if (!group) {
228 BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", filepath);
229 return OPERATOR_CANCELLED;
230 }
231 if (!is_librarypath_valid) {
232 BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", filepath);
233 return OPERATOR_CANCELLED;
234 }
235
236 /* Check if something is indicated for append/link. */
237 prop = RNA_struct_find_property(op->ptr, "files");
238 if (prop) {
239 totfiles = RNA_property_collection_length(op->ptr, prop);
240 if (totfiles == 0) {
241 if (!name) {
242 BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", filepath);
243 return OPERATOR_CANCELLED;
244 }
245 }
246 }
247 else if (!name) {
248 BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", filepath);
249 return OPERATOR_CANCELLED;
250 }
251
252 int flag = wm_link_append_flag(op);
253 const bool do_append = (flag & FILE_LINK) == 0;
254
255 /* From here down, no error returns. */
256
257 if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
258 BKE_view_layer_base_deselect_all(scene, view_layer);
259 }
260
261 /* Sanity checks for flag. */
262 if (scene && scene->id.lib) {
265 "Scene '%s' is linked, instantiation of objects is disabled",
266 scene->id.name + 2);
268 scene = nullptr;
269 }
270
271 /* Tag everything, all untagged data can be made local
272 * its also generally useful to know what is new.
273 *
274 * Take extra care `BKE_main_id_flag_all(bmain, ID_TAG_PRE_EXISTING, false)` is called after! */
276
277 /* We define our working data...
278 * Note that here, each item 'uses' one library, and only one. */
279 LibraryLink_Params lapp_params;
281 &lapp_params, bmain, flag, 0, scene, view_layer, CTX_wm_view3d(C));
282
283 lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
286
287 if (totfiles != 0) {
289 int lib_idx = 0;
290
291 RNA_BEGIN (op->ptr, itemptr, "files") {
292 RNA_string_get(&itemptr, "name", relname);
293
294 BLI_path_join(filepath, sizeof(filepath), root, relname);
295
296 if (BKE_blendfile_library_path_explode(filepath, libname, &group, &name)) {
297 if (!wm_link_append_item_poll(nullptr, filepath, group, name, do_append)) {
298 continue;
299 }
300
301 if (libraries.add(libname, lib_idx)) {
302 lib_idx++;
303 BKE_blendfile_link_append_context_library_add(lapp_context, libname, nullptr);
304 }
305 }
306 }
307 RNA_END;
308
309 RNA_BEGIN (op->ptr, itemptr, "files") {
310 RNA_string_get(&itemptr, "name", relname);
311
312 BLI_path_join(filepath, sizeof(filepath), root, relname);
313
314 if (BKE_blendfile_library_path_explode(filepath, libname, &group, &name)) {
316
317 if (!wm_link_append_item_poll(op->reports, filepath, group, name, do_append)) {
318 continue;
319 }
320
321 lib_idx = libraries.lookup(libname);
322
324 lapp_context, name, BKE_idtype_idcode_from_name(group), nullptr);
326 }
327 }
328 RNA_END;
329 }
330 else {
332
333 BKE_blendfile_link_append_context_library_add(lapp_context, libname, nullptr);
335 lapp_context, name, BKE_idtype_idcode_from_name(group), nullptr);
337 }
338
340 /* Early out in case there is nothing to link. */
342 /* Clear pre existing tag. */
344 return OPERATOR_CANCELLED;
345 }
346
348
349 /* XXX We'd need re-entrant locking on Main for this to work... */
350 // BKE_main_lock(bmain);
351
352 BKE_blendfile_link(lapp_context, op->reports);
353
354 // BKE_main_unlock(bmain);
355
356 /* Mark all library linked objects to be updated. */
359
360 /* Append, rather than linking. */
361 if (do_append) {
362 BKE_blendfile_append(lapp_context, op->reports);
363 }
364
365 /* Instantiate loose data in the scene (e.g. add object to the active collection). */
367
369
371
372 /* Important we unset, otherwise these object won't
373 * link into other scenes from this blend file. */
375
376 /* TODO(sergey): Use proper flag for tagging here. */
377
378 /* TODO(dalai): Temporary solution!
379 * Ideally we only need to tag the new objects themselves, not the scene.
380 * This way we'll avoid flush of collection properties
381 * to all objects and limit update to the particular object only.
382 * But afraid first we need to change collection evaluation in DEG
383 * according to depsgraph manifesto. */
384 if (scene) {
385 DEG_id_tag_update(&scene->id, 0);
386 }
387
388 /* Recreate dependency graph to include new objects. */
390
391 /* TODO: align `G.filepath_last_library` with other directory storage
392 * (like last opened image, etc). */
393 STRNCPY(G.filepath_last_library, root);
394
396
397 return OPERATOR_FINISHED;
398}
399
401 const bool is_link,
402 const bool is_relocate)
403{
404 PropertyRNA *prop;
405
406 /* Better not save _any_ settings for this operator. */
407
408 /* Properties. */
409 prop = RNA_def_boolean(ot->srna,
410 "link",
411 is_link || is_relocate,
412 "Link",
413 "Link the objects or data-blocks rather than appending");
415
416 prop = RNA_def_boolean(
417 ot->srna,
418 "do_reuse_local_id",
419 false,
420 "Re-Use Local Data",
421 "Try to re-use previously matching appended data-blocks instead of appending a new copy");
423 prop = RNA_def_boolean(ot->srna,
424 "clear_asset_data",
425 false,
426 "Clear Asset Data",
427 "Don't add asset meta-data or tags from the original data-block");
429
430 prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects");
432
433 prop = RNA_def_boolean(ot->srna,
434 "active_collection",
435 !is_relocate,
436 "Active Collection",
437 "Put new objects on the active collection");
439
440 /* NOTE: do not force instancing when relocating, as direct data (the selected ID) status should
441 * not change on that regard, and other dependencies would be indirectly linked and therefore
442 * should not require any enforced instancing when linked. */
443 prop = RNA_def_boolean(
444 ot->srna,
445 "instance_collections",
446 is_link && !is_relocate,
447 "Instance Collections",
448 "Create instances for collections, rather than adding them directly to the scene");
450
451 prop = RNA_def_boolean(
452 ot->srna,
453 "instance_object_data",
454 !is_relocate,
455 "Instance Object Data",
456 "Create instances for object data which are not referenced by any objects");
458}
459
461{
462 ot->name = "Link";
463 ot->idname = "WM_OT_link";
464 ot->description = "Link from a Library .blend file";
465
466 ot->invoke = wm_link_append_invoke;
467 ot->exec = wm_link_append_exec;
468 ot->poll = wm_link_append_poll;
469
470 ot->flag = OPTYPE_UNDO;
471
480
482}
483
485{
486 ot->name = "Append";
487 ot->idname = "WM_OT_append";
488 ot->description = "Append from a Library .blend file";
489
490 ot->invoke = wm_link_append_invoke;
491 ot->exec = wm_link_append_exec;
492 ot->poll = wm_link_append_poll;
493
494 ot->flag = OPTYPE_UNDO;
495
504
506 RNA_def_boolean(ot->srna,
507 "set_fake",
508 false,
509 "Fake User",
510 "Set \"Fake User\" for appended items (except objects and collections)");
512 ot->srna,
513 "use_recursive",
514 true,
515 "Localize All",
516 "Localize all appended data, including those indirectly linked from other libraries");
517}
518
520{
521 Main *bmain = CTX_data_main(C);
522 Scene *scene = CTX_data_scene(C);
523 ViewLayer *view_layer = CTX_data_view_layer(C);
524 BlendfileLinkAppendContext *lapp_context;
525 char filepath[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA],
526 relname[FILE_MAX];
527 char *group, *name;
528
529 RNA_string_get(op->ptr, "filename", relname);
530 RNA_string_get(op->ptr, "directory", root);
531
532 BLI_path_join(filepath, sizeof(filepath), root, relname);
533
534 /* Test if we have a valid data. */
535 const bool is_librarypath_valid = BKE_blendfile_library_path_explode(
536 filepath, libname, &group, &name);
537
538 /* NOTE: Need to also check filepath, as typically libname is an empty string here (when trying
539 * to append from current file from the file-browser e.g.). */
540 if (BLI_path_cmp(BKE_main_blendfile_path(bmain), filepath) == 0 ||
541 BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0)
542 {
543 BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", filepath);
544 return OPERATOR_CANCELLED;
545 }
546 if (!is_librarypath_valid) {
547 BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", filepath);
548 return OPERATOR_CANCELLED;
549 }
550 if (!group || !name) {
551 BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", filepath);
552 return OPERATOR_CANCELLED;
553 }
554
555 int flag = wm_link_append_flag(op);
557
558 const short id_type_code = BKE_idtype_idcode_from_name(group);
559
560 const int tmp_id_session_uid = RNA_int_get(op->ptr, "id_session_uid");
561 const uint id_session_uid = *reinterpret_cast<const uint *>(&tmp_id_session_uid);
562 /* NOTE: Creating a full ID map for a single lookup is not worth it. */
563 ID *linked_id = BKE_libblock_find_session_uid(bmain, id_session_uid);
564
565 {
566 const char *linked_id_name = BKE_id_name(*linked_id);
567
568 if (!linked_id || !ID_IS_LINKED(linked_id)) {
569 BKE_reportf(op->reports, RPT_ERROR, "No valid existing linked ID given to relocate");
570 return OPERATOR_CANCELLED;
571 }
572 if (GS(linked_id->name) != id_type_code) {
574 RPT_ERROR,
575 "Selected ID '%s' is a %s, cannot be used to relocate existing linked ID '%s' "
576 "which is a %s",
577 name,
578 group,
579 linked_id_name,
580 BKE_idtype_idcode_to_name(GS(linked_id->name)));
581 return OPERATOR_CANCELLED;
582 }
583 if (STREQ(linked_id_name, name) && STREQ(linked_id->lib->runtime->filepath_abs, libname)) {
585 RPT_ERROR,
586 "Selected ID '%s' seems to be the same as the relocated ID '%s', use 'Reload' "
587 "operation instead",
588 name,
589 linked_id_name);
590 return OPERATOR_CANCELLED;
591 }
592 }
593
594 /* From here down, no error returns. */
595
596 if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
597 BKE_view_layer_base_deselect_all(scene, view_layer);
598 }
599
600 /* Never enforce instantiation of anything when relocating. */
602
603 /* Tag everything, its generally useful to know what is new.
604 *
605 * Take extra care `BKE_main_id_flag_all(bmain, ID_TAG_PRE_EXISTING, false)` is called after! */
607
608 /* We define our working data...
609 * Note that here, each item 'uses' one library, and only one. */
610 LibraryLink_Params lapp_params;
612 &lapp_params, bmain, flag, 0, scene, view_layer, CTX_wm_view3d(C));
613
614 lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
617
618 BKE_blendfile_link_append_context_library_add(lapp_context, libname, nullptr);
620 lapp_context, name, id_type_code, linked_id);
622
624
625 BKE_blendfile_id_relocate(*lapp_context, op->reports);
626
628
630
631 /* TODO(sergey): Use proper flag for tagging here. */
632
633 /* TODO(dalai): Temporary solution!
634 * Ideally we only need to tag the new objects themselves, not the scene.
635 * This way we'll avoid flush of collection properties
636 * to all objects and limit update to the particular object only.
637 * But afraid first we need to change collection evaluation in DEG
638 * according to depsgraph manifesto. */
639 if (scene) {
640 DEG_id_tag_update(&scene->id, 0);
641 }
642
643 /* Recreate dependency graph to include new objects. */
645
646 /* TODO: align `G.filepath_last_library` with other directory storage
647 * (like last opened image, etc). */
648 STRNCPY(G.filepath_last_library, root);
649
651
652 return OPERATOR_FINISHED;
653}
654
656{
657 ot->name = "Relocate Linked ID";
658 ot->idname = "WM_OT_id_linked_relocate";
659 ot->description =
660 "Relocate a linked ID, i.e. select another ID to link, and remap its local usages to that "
661 "newly linked data-block). Currently only designed as an internal operator, not directly "
662 "exposed to the user";
663
664 ot->invoke = wm_link_append_invoke;
666 ot->poll = wm_link_append_poll;
667
669
670 PropertyRNA *prop = RNA_def_int(ot->srna,
671 "id_session_uid",
673 0,
674 INT_MAX,
675 "Linked ID Session UID",
676 "Unique runtime identifier for the linked ID to relocate",
677 0,
678 INT_MAX);
680
689
691}
692
694
695/* -------------------------------------------------------------------- */
699
701 Scene *scene,
702 ViewLayer *view_layer,
703 View3D *v3d,
704 const char *filepath,
705 const short id_code,
706 const char *id_name,
707 const int flag)
708{
709 const bool do_append = (flag & FILE_LINK) == 0;
710 /* Tag everything so we can make local only the new datablock. */
712
713 /* Define working data, with just the one item we want to link. */
714 LibraryLink_Params lapp_params;
715 BLO_library_link_params_init_with_context(&lapp_params, bmain, flag, 0, scene, view_layer, v3d);
716
720
721 BKE_blendfile_link_append_context_library_add(lapp_context, filepath, nullptr);
723 lapp_context, id_name, id_code, nullptr);
725
727
728 /* Link datablock. */
729 BKE_blendfile_link(lapp_context, nullptr);
730
731 if (do_append) {
732 BKE_blendfile_append(lapp_context, nullptr);
733 }
734
735 BKE_blendfile_link_append_instantiate_loose(lapp_context, nullptr);
736
738
739 /* Get linked datablock and free working data. */
741
743
745
746 return id;
747}
748
750 Scene *scene,
751 ViewLayer *view_layer,
752 View3D *v3d,
753 const char *filepath,
754 const short id_code,
755 const char *id_name,
756 int flag)
757{
758 flag |= FILE_LINK;
760 bmain, scene, view_layer, v3d, filepath, id_code, id_name, flag);
761}
762
764 Scene *scene,
765 ViewLayer *view_layer,
766 View3D *v3d,
767 const char *filepath,
768 const short id_code,
769 const char *id_name,
770 int flag)
771{
772 BLI_assert((flag & FILE_LINK) == 0);
774 bmain, scene, view_layer, v3d, filepath, id_code, id_name, flag);
775
776 return id;
777}
778
780
781/* -------------------------------------------------------------------- */
784
786 wmOperator *op,
787 const wmEvent * /*event*/)
788{
789 Library *lib;
790 char lib_name[MAX_NAME];
791
792 RNA_string_get(op->ptr, "library", lib_name);
794
795 if (lib) {
796 if (lib->runtime->parent) {
799 "Cannot relocate indirectly linked library '%s'",
800 lib->runtime->filepath_abs);
801 return OPERATOR_CANCELLED;
802 }
803 RNA_string_set(op->ptr, "filepath", lib->runtime->filepath_abs);
804
806
808 }
809
810 return OPERATOR_CANCELLED;
811}
812
814{
815 if (!BKE_blendfile_extension_check(lib->runtime->filepath_abs)) {
817 reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->runtime->filepath_abs);
818 return;
819 }
820
821 if (!BLI_exists(lib->runtime->filepath_abs)) {
823 RPT_ERROR,
824 "Trying to reload library '%s' from invalid path '%s'",
825 lib->id.name,
826 lib->runtime->filepath_abs);
827 return;
828 }
829
830 Main *bmain = CTX_data_main(C);
831 LibraryLink_Params lapp_params;
833 bmain,
836 0,
839 nullptr);
840
842
843 BKE_blendfile_link_append_context_library_add(lapp_context, lib->runtime->filepath_abs, nullptr);
844
845 BKE_blendfile_library_relocate(lapp_context, reports, lib, true);
846
848
851
852 /* Important we unset, otherwise these object won't link into other scenes from this blend file.
853 */
855
856 /* Recreate dependency graph to include new IDs. */
858
860}
861
863{
864 Main *bmain = CTX_data_main(C);
865 char lib_name[MAX_NAME];
866
867 RNA_string_get(op->ptr, "library", lib_name);
868 Library *lib = (Library *)BKE_libblock_find_name(bmain, ID_LI, lib_name);
869 if (lib == nullptr) {
870 return OPERATOR_CANCELLED;
871 }
872
873 PropertyRNA *prop;
874 BlendfileLinkAppendContext *lapp_context;
875
876 char filepath[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
877 short flag = 0;
878
879 if (RNA_boolean_get(op->ptr, "relative_path")) {
881 }
882
883 if (lib->runtime->parent && !do_reload) {
886 "Cannot relocate indirectly linked library '%s'",
887 lib->runtime->filepath_abs);
888 return OPERATOR_CANCELLED;
889 }
890
891 RNA_string_get(op->ptr, "directory", root);
892 RNA_string_get(op->ptr, "filename", libname);
893
894 if (!BKE_blendfile_extension_check(libname)) {
895 BKE_report(op->reports, RPT_ERROR, "Not a library");
896 return OPERATOR_CANCELLED;
897 }
898
899 BLI_path_join(filepath, sizeof(filepath), root, libname);
900
901 if (!BLI_exists(filepath)) {
904 "Trying to reload or relocate library '%s' to invalid path '%s'",
905 lib->id.name,
906 filepath);
907 return OPERATOR_CANCELLED;
908 }
909
910 if (BLI_path_cmp(BKE_main_blendfile_path(bmain), filepath) == 0) {
913 "Cannot relocate library '%s' to current blend file '%s'",
914 lib->id.name,
915 filepath);
916 return OPERATOR_CANCELLED;
917 }
918
919 LibraryLink_Params lapp_params;
921 &lapp_params, bmain, flag, 0, CTX_data_scene(C), CTX_data_view_layer(C), nullptr);
922
923 if (BLI_path_cmp(lib->runtime->filepath_abs, filepath) == 0) {
924 CLOG_INFO(&LOG, 4, "We are supposed to reload '%s' lib (%d)", lib->filepath, lib->id.us);
925
926 do_reload = true;
927
928 lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
929 BKE_blendfile_link_append_context_library_add(lapp_context, filepath, nullptr);
930 }
931 else {
932 int totfiles = 0;
933
934 CLOG_INFO(
935 &LOG, 4, "We are supposed to relocate '%s' lib to new '%s' one", lib->filepath, libname);
936
937 /* Check if something is indicated for relocate. */
938 prop = RNA_struct_find_property(op->ptr, "files");
939 if (prop) {
940 totfiles = RNA_property_collection_length(op->ptr, prop);
941 if (totfiles == 0) {
942 if (!libname[0]) {
943 BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
944 return OPERATOR_CANCELLED;
945 }
946 }
947 }
948
949 lapp_context = BKE_blendfile_link_append_context_new(&lapp_params);
950
951 if (totfiles) {
952 RNA_BEGIN (op->ptr, itemptr, "files") {
953 RNA_string_get(&itemptr, "name", relname);
954
955 BLI_path_join(filepath, sizeof(filepath), root, relname);
956
957 if (BLI_path_cmp(filepath, lib->runtime->filepath_abs) == 0 ||
959 {
960 continue;
961 }
962
963 CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", filepath);
964 BKE_blendfile_link_append_context_library_add(lapp_context, filepath, nullptr);
965 }
966 RNA_END;
967 }
968 else {
969 CLOG_INFO(&LOG, 4, "\tCandidate new lib to reload datablocks from: %s", filepath);
970 BKE_blendfile_link_append_context_library_add(lapp_context, filepath, nullptr);
971 }
972 }
973
976 (do_reload ? BLO_LIBLINK_USE_PLACEHOLDERS : 0),
977 true);
978
979 BKE_blendfile_library_relocate(lapp_context, op->reports, lib, do_reload);
980
982
983 /* TODO: align `G.filepath_last_library` with other directory storage
984 * (like last opened image, etc). */
985 STRNCPY(G.filepath_last_library, root);
986
989
990 /* Important we unset, otherwise these object won't link into other scenes from this blend
991 * file.
992 */
994
995 /* Recreate dependency graph to include new IDs. */
997
999
1000 return OPERATOR_FINISHED;
1001}
1002
1004{
1005 return wm_lib_relocate_exec_do(C, op, false);
1006}
1007
1009{
1010 PropertyRNA *prop;
1011
1012 ot->name = "Relocate Library";
1013 ot->idname = "WM_OT_lib_relocate";
1014 ot->description = "Relocate the given library to one or several others";
1015
1016 ot->invoke = wm_lib_relocate_invoke;
1017 ot->exec = wm_lib_relocate_exec;
1018
1019 ot->flag = OPTYPE_UNDO;
1020
1021 prop = RNA_def_string(ot->srna, "library", nullptr, MAX_NAME, "Library", "Library to relocate");
1023
1032}
1033
1035{
1036 return wm_lib_relocate_exec_do(C, op, true);
1037}
1038
1040{
1041 PropertyRNA *prop;
1042
1043 ot->name = "Reload Library";
1044 ot->idname = "WM_OT_lib_reload";
1045 ot->description = "Reload the given library";
1046
1047 ot->exec = wm_lib_reload_exec;
1048
1049 ot->flag = OPTYPE_UNDO;
1050
1051 prop = RNA_def_string(ot->srna, "library", nullptr, MAX_NAME, "Library", "Library to reload");
1053
1062}
1063
bool BKE_blendfile_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
Definition blendfile.cc:90
bool BKE_blendfile_extension_check(const char *str)
Definition blendfile.cc:84
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:165
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:198
short BKE_idtype_idcode_from_name(const char *idtype_name)
Definition idtype.cc:186
bool BKE_idtype_idcode_is_only_appendable(short idcode)
Definition idtype.cc:205
void BKE_view_layer_base_deselect_all(const Scene *scene, ViewLayer *view_layer)
ID * BKE_libblock_find_session_uid(Main *bmain, short type, uint32_t session_uid)
Definition lib_id.cc:1697
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition lib_id.cc:1679
#define MAIN_ID_SESSION_UID_UNSET
void BKE_main_lib_objects_recalc_all(Main *bmain)
Definition lib_id.cc:1280
const char * BKE_id_name(const ID &id)
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1214
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:877
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:882
General operations, lookup, etc. for materials.
General operations, lookup, etc. for blender objects.
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
API for Blender-side Rigid Body stuff.
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:373
#define FILE_MAX
#define BLI_path_join(...)
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
#define FILE_MAXDIR
#define BLI_path_cmp
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
#define STREQ(a, b)
external readfile function prototypes.
@ BLO_LIBLINK_APPEND_RECURSIVE
@ BLO_LIBLINK_USE_PLACEHOLDERS
@ BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR
@ BLO_LIBLINK_OBDATA_INSTANCE
@ BLO_LIBLINK_APPEND_SET_FAKEUSER
@ BLO_LIBLINK_FORCE_INDIRECT
@ BLO_LIBLINK_APPEND_LOCAL_ID_REUSE
@ BLO_LIBLINK_COLLECTION_INSTANCE
void BLO_library_link_params_init_with_context(LibraryLink_Params *params, Main *bmain, int flag, int id_tag_extra, Scene *scene, ViewLayer *view_layer, const View3D *v3d)
Definition readfile.cc:4614
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
ID and Library types, which are fundamental for SDNA.
@ ID_TAG_PRE_EXISTING
Definition DNA_ID.h:834
@ ID_LI
@ FILE_SORT_DEFAULT
@ FILE_LOADLIB
@ FILE_BLENDER
@ FILE_TYPE_BLENDER
@ FILE_TYPE_FOLDER
@ FILE_TYPE_BLENDERLIB
@ FILE_DEFAULTDISPLAY
@ FILE_ACTIVE_COLLECTION
@ FILE_RELPATH
@ FILE_AUTOSELECT
@ FILE_LINK
#define FILE_MAX_LIBEXTRA
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ RPT_ERROR_INVALID_INPUT
int datatoc_startup_blend_size
const char datatoc_startup_blend[]
void IMB_colormanagement_check_file_config(Main *bmain)
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
@ PROP_SKIP_SAVE
Definition RNA_types.hh:330
@ PROP_HIDDEN
Definition RNA_types.hh:324
#define C
Definition RandGen.cpp:29
@ WM_FILESEL_FILES
Definition WM_api.hh:1076
@ WM_FILESEL_DIRECTORY
Definition WM_api.hh:1073
@ WM_FILESEL_RELPATH
Definition WM_api.hh:1072
@ WM_FILESEL_SHOW_PROPS
Definition WM_api.hh:1078
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1075
@ WM_FILESEL_FILENAME
Definition WM_api.hh:1074
@ FILE_OPENFILE
Definition WM_api.hh:1084
#define NC_WINDOW
Definition WM_types.hh:372
ReportList * reports
Definition WM_types.hh:1025
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
std::string id_name(void *id)
#define ID_IS_LINKED(_id)
#define MAX_NAME
#define GS(a)
#define LOG(severity)
Definition log.h:32
#define G(x, y, z)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_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)
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)
Definition DNA_ID.h:404
struct Library * lib
Definition DNA_ID.h:410
char name[66]
Definition DNA_ID.h:415
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:516
struct ReportList * reports
struct PointerRNA * ptr
static DynamicLibrary lib
void WM_event_add_fileselect(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4226
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
bool WM_operator_winactive(bContext *C)
uint8_t flag
Definition wm_window.cc:139