Blender  V2.93
wm_files_link.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include <ctype.h>
27 #include <errno.h>
28 #include <float.h>
29 #include <stddef.h>
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include "MEM_guardedalloc.h"
34 
35 #include "DNA_ID.h"
36 #include "DNA_key_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_screen_types.h"
40 
41 #include "BLI_bitmap.h"
42 #include "BLI_blenlib.h"
43 #include "BLI_ghash.h"
44 #include "BLI_linklist.h"
45 #include "BLI_math.h"
46 #include "BLI_memarena.h"
47 #include "BLI_utildefines.h"
48 
49 #include "BLO_readfile.h"
50 
51 #include "BKE_context.h"
52 #include "BKE_global.h"
53 #include "BKE_key.h"
54 #include "BKE_layer.h"
55 #include "BKE_lib_id.h"
56 #include "BKE_lib_override.h"
57 #include "BKE_lib_remap.h"
58 #include "BKE_main.h"
59 #include "BKE_report.h"
60 
61 #include "BKE_idtype.h"
62 
63 #include "DEG_depsgraph.h"
64 #include "DEG_depsgraph_build.h"
65 
66 #include "IMB_colormanagement.h"
67 
68 #include "ED_datafiles.h"
69 #include "ED_screen.h"
70 
71 #include "RNA_access.h"
72 #include "RNA_define.h"
73 
74 #include "WM_api.h"
75 #include "WM_types.h"
76 
77 #include "wm_files.h"
78 
79 /* -------------------------------------------------------------------- */
84 {
85  if (WM_operator_winactive(C)) {
86  /* linking changes active object which is pretty useful in general,
87  * but which totally confuses edit mode (i.e. it becoming not so obvious
88  * to leave from edit mode and invalid tools in toolbar might be displayed)
89  * so disable link/append when in edit mode (sergey) */
90  if (CTX_data_edit_object(C)) {
91  return 0;
92  }
93 
94  return 1;
95  }
96 
97  return 0;
98 }
99 
100 static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
101 {
102  if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
103  if (G.lib[0] != '\0') {
104  RNA_string_set(op->ptr, "filepath", G.lib);
105  }
106  else if (G.relbase_valid) {
107  char path[FILE_MAX];
108  BLI_strncpy(path, BKE_main_blendfile_path_from_global(), sizeof(path));
109  BLI_path_parent_dir(path);
110  RNA_string_set(op->ptr, "filepath", path);
111  }
112  }
113 
115  return OPERATOR_RUNNING_MODAL;
116 }
117 
119 {
120  PropertyRNA *prop;
121  short flag = 0;
122 
123  if (RNA_boolean_get(op->ptr, "autoselect")) {
124  flag |= FILE_AUTOSELECT;
125  }
126  if (RNA_boolean_get(op->ptr, "active_collection")) {
127  flag |= FILE_ACTIVE_COLLECTION;
128  }
129  if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) &&
130  RNA_property_boolean_get(op->ptr, prop)) {
131  flag |= FILE_RELPATH;
132  }
133  if (RNA_boolean_get(op->ptr, "link")) {
134  flag |= FILE_LINK;
135  }
136  if (RNA_boolean_get(op->ptr, "instance_collections")) {
137  flag |= FILE_COLLECTION_INSTANCE;
138  }
139  if (RNA_boolean_get(op->ptr, "instance_object_data")) {
140  flag |= FILE_OBDATA_INSTANCE;
141  }
142 
143  return flag;
144 }
145 
146 typedef struct WMLinkAppendDataItem {
147  char *name;
148  BLI_bitmap
149  *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */
150  short idcode;
151 
153  void *customdata;
155 
156 typedef struct WMLinkAppendData {
164  int flag;
165 
166  /* Internal 'private' data */
169 
171 {
173  WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data));
174 
175  lapp_data->flag = flag;
176  lapp_data->memarena = ma;
177 
178  return lapp_data;
179 }
180 
182 {
183  BLI_memarena_free(lapp_data->memarena);
184 }
185 
186 /* WARNING! *Never* call wm_link_append_data_library_add() after having added some items! */
187 
188 static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const char *libname)
189 {
190  size_t len = strlen(libname) + 1;
191  char *libpath = BLI_memarena_alloc(lapp_data->memarena, len);
192 
193  BLI_strncpy(libpath, libname, len);
194  BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena);
195  lapp_data->num_libraries++;
196 }
197 
199  const char *idname,
200  const short idcode,
201  void *customdata)
202 {
203  WMLinkAppendDataItem *item = BLI_memarena_alloc(lapp_data->memarena, sizeof(*item));
204  size_t len = strlen(idname) + 1;
205 
206  item->name = BLI_memarena_alloc(lapp_data->memarena, len);
207  BLI_strncpy(item->name, idname, len);
208  item->idcode = idcode;
209  item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries);
210 
211  item->new_id = NULL;
212  item->customdata = customdata;
213 
214  BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena);
215  lapp_data->num_items++;
216 
217  return item;
218 }
219 
220 static void wm_link_do(WMLinkAppendData *lapp_data,
221  ReportList *reports,
222  Main *bmain,
223  Scene *scene,
224  ViewLayer *view_layer,
225  const View3D *v3d)
226 {
227  Main *mainl;
228  BlendHandle *bh;
229  Library *lib;
230 
231  const int flag = lapp_data->flag;
232  const int id_tag_extra = 0;
233 
234  LinkNode *liblink, *itemlink;
235  int lib_idx, item_idx;
236 
237  BLI_assert(lapp_data->num_items && lapp_data->num_libraries);
238 
239  for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink;
240  lib_idx++, liblink = liblink->next) {
241  char *libname = liblink->link;
242 
243  if (STREQ(libname, BLO_EMBEDDED_STARTUP_BLEND)) {
245  }
246  else {
247  bh = BLO_blendhandle_from_file(libname, reports);
248  }
249 
250  if (bh == NULL) {
251  /* Unlikely since we just browsed it, but possible
252  * Error reports will have been made by BLO_blendhandle_from_file() */
253  continue;
254  }
255 
256  /* here appending/linking starts */
257  struct LibraryLink_Params liblink_params;
259  &liblink_params, bmain, flag, id_tag_extra, scene, view_layer, v3d);
260 
261  mainl = BLO_library_link_begin(&bh, libname, &liblink_params);
262  lib = mainl->curlib;
263  BLI_assert(lib);
264  /* In case lib was already existing but not found originally, see T99820. */
265  lib->id.tag &= ~LIB_TAG_MISSING;
266 
267  if (mainl->versionfile < 250) {
268  BKE_reportf(reports,
269  RPT_WARNING,
270  "Linking or appending from a very old .blend file format (%d.%d), no animation "
271  "conversion will "
272  "be done! You may want to re-save your lib file with current Blender",
273  mainl->versionfile,
274  mainl->subversionfile);
275  }
276 
277  /* For each lib file, we try to link all items belonging to that lib,
278  * and tag those successful to not try to load them again with the other libs. */
279  for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
280  item_idx++, itemlink = itemlink->next) {
281  WMLinkAppendDataItem *item = itemlink->link;
282  ID *new_id;
283 
284  if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
285  continue;
286  }
287 
288  new_id = BLO_library_link_named_part(mainl, &bh, item->idcode, item->name, &liblink_params);
289 
290  if (new_id) {
291  /* If the link is successful, clear item's libs 'todo' flags.
292  * This avoids trying to link same item with other libraries to come. */
293  BLI_bitmap_set_all(item->libraries, false, lapp_data->num_libraries);
294  item->new_id = new_id;
295  }
296  }
297 
298  BLO_library_link_end(mainl, &bh, &liblink_params);
300  }
301 }
302 
309  const char *path,
310  const char *group,
311  const char *name,
312  const bool do_append)
313 {
314  short idcode;
315 
316  if (!group || !name) {
317  printf("skipping %s\n", path);
318  return false;
319  }
320 
321  idcode = BKE_idtype_idcode_from_name(group);
322 
323  /* XXX For now, we do a nasty exception for workspace, forbid linking them.
324  * Not nice, ultimately should be solved! */
325  if (!BKE_idtype_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) {
326  if (reports) {
327  if (do_append) {
328  BKE_reportf(reports,
330  "Can't append data-block '%s' of type '%s'",
331  name,
332  group);
333  }
334  else {
335  BKE_reportf(reports,
337  "Can't link data-block '%s' of type '%s'",
338  name,
339  group);
340  }
341  }
342  return false;
343  }
344 
345  return true;
346 }
347 
349 {
353  PropertyRNA *prop;
354  WMLinkAppendData *lapp_data;
355  char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
356  char *group, *name;
357  int totfiles = 0;
358 
359  RNA_string_get(op->ptr, "filename", relname);
360  RNA_string_get(op->ptr, "directory", root);
361 
362  BLI_join_dirfile(path, sizeof(path), root, relname);
363 
364  /* test if we have a valid data */
365  if (!BLO_library_path_explode(path, libname, &group, &name)) {
366  BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path);
367  return OPERATOR_CANCELLED;
368  }
369  if (!group) {
370  BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
371  return OPERATOR_CANCELLED;
372  }
373  if (BLI_path_cmp(BKE_main_blendfile_path(bmain), libname) == 0) {
374  BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", path);
375  return OPERATOR_CANCELLED;
376  }
377 
378  /* check if something is indicated for append/link */
379  prop = RNA_struct_find_property(op->ptr, "files");
380  if (prop) {
381  totfiles = RNA_property_collection_length(op->ptr, prop);
382  if (totfiles == 0) {
383  if (!name) {
384  BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
385  return OPERATOR_CANCELLED;
386  }
387  }
388  }
389  else if (!name) {
390  BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
391  return OPERATOR_CANCELLED;
392  }
393 
394  short flag = wm_link_append_flag(op);
395  const bool do_append = (flag & FILE_LINK) == 0;
396 
397  /* sanity checks for flag */
398  if (scene && scene->id.lib) {
399  BKE_reportf(op->reports,
400  RPT_WARNING,
401  "Scene '%s' is linked, instantiation of objects is disabled",
402  scene->id.name + 2);
404  scene = NULL;
405  }
406 
407  /* We need to add nothing from #eBLOLibLinkFlags to flag here. */
408 
409  /* from here down, no error returns */
410 
411  if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
413  }
414 
415  /* tag everything, all untagged data can be made local
416  * its also generally useful to know what is new
417  *
418  * take extra care BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, false) is called after! */
420 
421  /* We define our working data...
422  * Note that here, each item 'uses' one library, and only one. */
423  lapp_data = wm_link_append_data_new(flag);
424  if (totfiles != 0) {
426  int lib_idx = 0;
427 
428  RNA_BEGIN (op->ptr, itemptr, "files") {
429  RNA_string_get(&itemptr, "name", relname);
430 
431  BLI_join_dirfile(path, sizeof(path), root, relname);
432 
433  if (BLO_library_path_explode(path, libname, &group, &name)) {
434  if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) {
435  continue;
436  }
437 
438  if (!BLI_ghash_haskey(libraries, libname)) {
439  BLI_ghash_insert(libraries, BLI_strdup(libname), POINTER_FROM_INT(lib_idx));
440  lib_idx++;
441  wm_link_append_data_library_add(lapp_data, libname);
442  }
443  }
444  }
445  RNA_END;
446 
447  RNA_BEGIN (op->ptr, itemptr, "files") {
448  RNA_string_get(&itemptr, "name", relname);
449 
450  BLI_join_dirfile(path, sizeof(path), root, relname);
451 
452  if (BLO_library_path_explode(path, libname, &group, &name)) {
453  WMLinkAppendDataItem *item;
454 
455  if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) {
456  continue;
457  }
458 
459  lib_idx = POINTER_AS_INT(BLI_ghash_lookup(libraries, libname));
460 
462  lapp_data, name, BKE_idtype_idcode_from_name(group), NULL);
463  BLI_BITMAP_ENABLE(item->libraries, lib_idx);
464  }
465  }
466  RNA_END;
467 
468  BLI_ghash_free(libraries, MEM_freeN, NULL);
469  }
470  else {
471  WMLinkAppendDataItem *item;
472 
473  wm_link_append_data_library_add(lapp_data, libname);
474  item = wm_link_append_data_item_add(lapp_data, name, BKE_idtype_idcode_from_name(group), NULL);
475  BLI_BITMAP_ENABLE(item->libraries, 0);
476  }
477 
478  if (lapp_data->num_items == 0) {
479  /* Early out in case there is nothing to link. */
480  wm_link_append_data_free(lapp_data);
481  /* Clear pre existing tag. */
483  return OPERATOR_CANCELLED;
484  }
485 
486  /* XXX We'd need re-entrant locking on Main for this to work... */
487  /* BKE_main_lock(bmain); */
488 
489  wm_link_do(lapp_data, op->reports, bmain, scene, view_layer, CTX_wm_view3d(C));
490 
491  /* BKE_main_unlock(bmain); */
492 
493  /* mark all library linked objects to be updated */
496 
497  /* append, rather than linking */
498  if (do_append) {
499  const bool set_fake = RNA_boolean_get(op->ptr, "set_fake");
500  const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
501 
502  if (use_recursive) {
503  BKE_library_make_local(bmain, NULL, NULL, true, set_fake);
504  }
505  else {
506  LinkNode *itemlink;
507  GSet *done_libraries = BLI_gset_new_ex(
509 
510  for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
511  ID *new_id = ((WMLinkAppendDataItem *)(itemlink->link))->new_id;
512 
513  if (new_id && !BLI_gset_haskey(done_libraries, new_id->lib)) {
514  BKE_library_make_local(bmain, new_id->lib, NULL, true, set_fake);
515  BLI_gset_insert(done_libraries, new_id->lib);
516  }
517  }
518 
519  BLI_gset_free(done_libraries, NULL);
520  }
521  }
522 
523  wm_link_append_data_free(lapp_data);
524 
525  /* important we unset, otherwise these object wont
526  * link into other scenes from this blend file */
528 
529  /* TODO(sergey): Use proper flag for tagging here. */
530 
531  /* TODO(dalai): Temporary solution!
532  * Ideally we only need to tag the new objects themselves, not the scene.
533  * This way we'll avoid flush of collection properties
534  * to all objects and limit update to the particular object only.
535  * But afraid first we need to change collection evaluation in DEG
536  * according to depsgraph manifesto. */
537  DEG_id_tag_update(&scene->id, 0);
538 
539  /* recreate dependency graph to include new objects */
541 
542  /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
543  BLI_strncpy(G.lib, root, FILE_MAX);
544 
546 
547  return OPERATOR_FINISHED;
548 }
549 
551 {
552  PropertyRNA *prop;
553 
554  /* better not save _any_ settings for this operator */
555  /* properties */
556  prop = RNA_def_boolean(
557  ot->srna, "link", is_link, "Link", "Link the objects or data-blocks rather than appending");
559  prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects");
561  prop = RNA_def_boolean(ot->srna,
562  "active_collection",
563  true,
564  "Active Collection",
565  "Put new objects on the active collection");
567  prop = RNA_def_boolean(
568  ot->srna,
569  "instance_collections",
570  is_link,
571  "Instance Collections",
572  "Create instances for collections, rather than adding them directly to the scene");
574 
575  prop = RNA_def_boolean(
576  ot->srna,
577  "instance_object_data",
578  true,
579  "Instance Object Data",
580  "Create instances for object data which are not referenced by any objects");
582 }
583 
585 {
586  ot->name = "Link";
587  ot->idname = "WM_OT_link";
588  ot->description = "Link from a Library .blend file";
589 
593 
594  ot->flag |= OPTYPE_UNDO;
595 
598  FILE_LOADLIB,
604 
606 }
607 
609 {
610  ot->name = "Append";
611  ot->idname = "WM_OT_append";
612  ot->description = "Append from a Library .blend file";
613 
617 
618  ot->flag |= OPTYPE_UNDO;
619 
622  FILE_LOADLIB,
628 
631  "set_fake",
632  false,
633  "Fake User",
634  "Set \"Fake User\" for appended items (except objects and collections)");
636  ot->srna,
637  "use_recursive",
638  true,
639  "Localize All",
640  "Localize all appended data, including those indirectly linked from other libraries");
641 }
642 
645 /* -------------------------------------------------------------------- */
652  Scene *scene,
654  View3D *v3d,
655  const char *filepath,
656  const short id_code,
657  const char *id_name)
658 {
659  /* Tag everything so we can make local only the new datablock. */
661 
662  /* Define working data, with just the one item we want to append. */
664 
665  wm_link_append_data_library_add(lapp_data, filepath);
666  WMLinkAppendDataItem *item = wm_link_append_data_item_add(lapp_data, id_name, id_code, NULL);
667  BLI_BITMAP_ENABLE(item->libraries, 0);
668 
669  /* Link datablock. */
670  wm_link_do(lapp_data, NULL, bmain, scene, view_layer, v3d);
671 
672  /* Get linked datablock and free working data. */
673  ID *id = item->new_id;
674  wm_link_append_data_free(lapp_data);
675 
676  /* Make datablock local. */
677  BKE_library_make_local(bmain, NULL, NULL, true, false);
678 
679  /* Clear pre existing tag. */
681 
682  return id;
683 }
684 
687 /* -------------------------------------------------------------------- */
691 static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
692 {
693  Library *lib;
694  char lib_name[MAX_NAME];
695 
696  RNA_string_get(op->ptr, "library", lib_name);
698 
699  if (lib) {
700  if (lib->parent) {
701  BKE_reportf(op->reports,
703  "Cannot relocate indirectly linked library '%s'",
704  lib->filepath_abs);
705  return OPERATOR_CANCELLED;
706  }
707  RNA_string_set(op->ptr, "filepath", lib->filepath_abs);
708 
710 
711  return OPERATOR_RUNNING_MODAL;
712  }
713 
714  return OPERATOR_CANCELLED;
715 }
716 
718  ID *old_id,
719  ID *new_id,
720  ReportList *reports,
721  const bool do_reload,
722  const short remap_flags)
723 {
724  BLI_assert(old_id);
725  if (do_reload) {
726  /* Since we asked for placeholders in case of missing IDs,
727  * we expect to always get a valid one. */
728  BLI_assert(new_id);
729  }
730  if (new_id) {
731 #ifdef PRINT_DEBUG
732  printf("before remap of %s, old_id users: %d, new_id users: %d\n",
733  old_id->name,
734  old_id->us,
735  new_id->us);
736 #endif
737  BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
738 
739  if (old_id->flag & LIB_FAKEUSER) {
740  id_fake_user_clear(old_id);
741  id_fake_user_set(new_id);
742  }
743 
744 #ifdef PRINT_DEBUG
745  printf("after remap of %s, old_id users: %d, new_id users: %d\n",
746  old_id->name,
747  old_id->us,
748  new_id->us);
749 #endif
750 
751  /* In some cases, new_id might become direct link, remove parent of library in this case. */
752  if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
753  if (do_reload) {
754  BLI_assert_unreachable(); /* Should not happen in 'pure' reload case... */
755  }
756  new_id->lib->parent = NULL;
757  }
758  }
759 
760  if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
761  /* Note that this *should* not happen - but better be safe than sorry in this area,
762  * at least until we are 100% sure this cannot ever happen.
763  * Also, we can safely assume names were unique so far,
764  * so just replacing '.' by '~' should work,
765  * but this does not totally rules out the possibility of name collision. */
766  size_t len = strlen(old_id->name);
767  size_t dot_pos;
768  bool has_num = false;
769 
770  for (dot_pos = len; dot_pos--;) {
771  char c = old_id->name[dot_pos];
772  if (c == '.') {
773  break;
774  }
775  if (c < '0' || c > '9') {
776  has_num = false;
777  break;
778  }
779  has_num = true;
780  }
781 
782  if (has_num) {
783  old_id->name[dot_pos] = '~';
784  }
785  else {
786  len = MIN2(len, MAX_ID_NAME - 7);
787  BLI_strncpy(&old_id->name[len], "~000", 7);
788  }
789 
790  id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
791 
792  BKE_reportf(
793  reports,
794  RPT_WARNING,
795  "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
796  "old one (%d remaining users) had to be kept and was renamed to '%s'",
797  new_id->name,
798  old_id->us,
799  old_id->name);
800  }
801 }
802 
804  Library *library,
805  WMLinkAppendData *lapp_data,
806  ReportList *reports,
807  const bool do_reload)
808 {
809  ListBase *lbarray[INDEX_ID_MAX];
810  int lba_idx;
811 
812  LinkNode *itemlink;
813  int item_idx;
814 
815  /* Remove all IDs to be reloaded from Main. */
816  lba_idx = set_listbasepointers(bmain, lbarray);
817  while (lba_idx--) {
818  ID *id = lbarray[lba_idx]->first;
819  const short idcode = id ? GS(id->name) : 0;
820 
821  if (!id || !BKE_idtype_idcode_is_linkable(idcode)) {
822  /* No need to reload non-linkable datatypes,
823  * those will get relinked with their 'users ID'. */
824  continue;
825  }
826 
827  for (; id; id = id->next) {
828  if (id->lib == library) {
829  WMLinkAppendDataItem *item;
830 
831  /* We remove it from current Main, and add it to items to link... */
832  /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */
833  BLI_remlink(lbarray[lba_idx], id);
834  /* Usual special code for ShapeKeys snowflakes... */
835  Key *old_key = BKE_key_from_id(id);
836  if (old_key != NULL) {
837  BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
838  }
839 
840  item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
841  BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries);
842 
843 #ifdef PRINT_DEBUG
844  printf("\tdatablock to seek for: %s\n", id->name);
845 #endif
846  }
847  }
848  }
849 
850  if (lapp_data->num_items == 0) {
851  /* Early out in case there is nothing to do. */
852  return;
853  }
854 
856 
857  /* We do not want any instantiation here! */
858  wm_link_do(lapp_data, reports, bmain, NULL, NULL, NULL);
859 
861 
862  /* We add back old id to bmain.
863  * We need to do this in a first, separated loop, otherwise some of those may not be handled by
864  * ID remapping, which means they would still reference old data to be deleted... */
865  for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
866  item_idx++, itemlink = itemlink->next) {
867  WMLinkAppendDataItem *item = itemlink->link;
868  ID *old_id = item->customdata;
869 
870  BLI_assert(old_id);
871  BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
872 
873  /* Usual special code for ShapeKeys snowflakes... */
874  Key *old_key = BKE_key_from_id(old_id);
875  if (old_key != NULL) {
876  BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
877  }
878  }
879 
880  /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking
881  * code is wrong, we need to redo it here after adding them back to main. */
883 
884  /* Note that in reload case, we also want to replace indirect usages. */
885  const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
887  (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
888  for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
889  item_idx++, itemlink = itemlink->next) {
890  WMLinkAppendDataItem *item = itemlink->link;
891  ID *old_id = item->customdata;
892  ID *new_id = item->new_id;
893 
894  lib_relocate_do_remap(bmain, old_id, new_id, reports, do_reload, remap_flags);
895  if (new_id == NULL) {
896  continue;
897  }
898  /* Usual special code for ShapeKeys snowflakes... */
899  Key **old_key_p = BKE_key_from_id_p(old_id);
900  if (old_key_p == NULL) {
901  continue;
902  }
903  Key *old_key = *old_key_p;
904  Key *new_key = BKE_key_from_id(new_id);
905  if (old_key != NULL) {
906  *old_key_p = NULL;
907  id_us_min(&old_key->id);
908  lib_relocate_do_remap(bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags);
909  *old_key_p = old_key;
910  id_us_plus_no_lib(&old_key->id);
911  }
912  }
913 
915 
916  for (item_idx = 0, itemlink = lapp_data->items.list; itemlink;
917  item_idx++, itemlink = itemlink->next) {
918  WMLinkAppendDataItem *item = itemlink->link;
919  ID *old_id = item->customdata;
920 
921  if (old_id->us == 0) {
922  BKE_id_free(bmain, old_id);
923  }
924  }
925 
926  /* Some datablocks can get reloaded/replaced 'silently' because they are not linkable
927  * (shape keys e.g.), so we need another loop here to clear old ones if possible. */
928  lba_idx = set_listbasepointers(bmain, lbarray);
929  while (lba_idx--) {
930  ID *id, *id_next;
931  for (id = lbarray[lba_idx]->first; id; id = id_next) {
932  id_next = id->next;
933  /* XXX That check may be a bit to generic/permissive? */
934  if (id->lib && (id->flag & LIB_TAG_PRE_EXISTING) && id->us == 0) {
935  BKE_id_free(bmain, id);
936  }
937  }
938  }
939 
940  /* Get rid of no more used libraries... */
942  lba_idx = set_listbasepointers(bmain, lbarray);
943  while (lba_idx--) {
944  ID *id;
945  for (id = lbarray[lba_idx]->first; id; id = id->next) {
946  if (id->lib) {
947  id->lib->id.tag &= ~LIB_TAG_DOIT;
948  }
949  }
950  }
951  Library *lib, *lib_next;
952  for (lib = which_libbase(bmain, ID_LI)->first; lib; lib = lib_next) {
953  lib_next = lib->id.next;
954  if (lib->id.tag & LIB_TAG_DOIT) {
955  id_us_clear_real(&lib->id);
956  if (lib->id.us == 0) {
957  BKE_id_free(bmain, (ID *)lib);
958  }
959  }
960  }
961 
962  /* Update overrides of reloaded linked data-blocks.
963  * Note that this will not necessarily fully update the override, it might need to be manually
964  * 're-generated' depending on changes in linked data. */
965  ID *id;
967  if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
968  (id->tag & LIB_TAG_PRE_EXISTING) == 0) {
969  continue;
970  }
973  }
974  }
976 
978 
981 
982  /* important we unset, otherwise these object wont
983  * link into other scenes from this blend file */
985 
986  /* recreate dependency graph to include new objects */
988 }
989 
991 {
992  if (!BLO_has_bfile_extension(lib->filepath_abs)) {
993  BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath_abs);
994  return;
995  }
996 
997  if (!BLI_exists(lib->filepath_abs)) {
998  BKE_reportf(reports,
999  RPT_ERROR,
1000  "Trying to reload library '%s' from invalid path '%s'",
1001  lib->id.name,
1002  lib->filepath_abs);
1003  return;
1004  }
1005 
1008 
1009  wm_link_append_data_library_add(lapp_data, lib->filepath_abs);
1010 
1011  lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true);
1012 
1013  wm_link_append_data_free(lapp_data);
1014 
1016 }
1017 
1018 static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
1019 {
1020  Library *lib;
1021  char lib_name[MAX_NAME];
1022 
1023  RNA_string_get(op->ptr, "library", lib_name);
1025 
1026  if (lib) {
1027  Main *bmain = CTX_data_main(C);
1028  PropertyRNA *prop;
1029  WMLinkAppendData *lapp_data;
1030 
1031  char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
1032  short flag = 0;
1033 
1034  if (RNA_boolean_get(op->ptr, "relative_path")) {
1035  flag |= FILE_RELPATH;
1036  }
1037 
1038  if (lib->parent && !do_reload) {
1039  BKE_reportf(op->reports,
1041  "Cannot relocate indirectly linked library '%s'",
1042  lib->filepath_abs);
1043  return OPERATOR_CANCELLED;
1044  }
1045 
1046  RNA_string_get(op->ptr, "directory", root);
1047  RNA_string_get(op->ptr, "filename", libname);
1048 
1049  if (!BLO_has_bfile_extension(libname)) {
1050  BKE_report(op->reports, RPT_ERROR, "Not a library");
1051  return OPERATOR_CANCELLED;
1052  }
1053 
1054  BLI_join_dirfile(path, sizeof(path), root, libname);
1055 
1056  if (!BLI_exists(path)) {
1057  BKE_reportf(op->reports,
1059  "Trying to reload or relocate library '%s' to invalid path '%s'",
1060  lib->id.name,
1061  path);
1062  return OPERATOR_CANCELLED;
1063  }
1064 
1065  if (BLI_path_cmp(BKE_main_blendfile_path(bmain), path) == 0) {
1066  BKE_reportf(op->reports,
1068  "Cannot relocate library '%s' to current blend file '%s'",
1069  lib->id.name,
1070  path);
1071  return OPERATOR_CANCELLED;
1072  }
1073 
1074  if (BLI_path_cmp(lib->filepath_abs, path) == 0) {
1075 #ifdef PRINT_DEBUG
1076  printf("We are supposed to reload '%s' lib (%d)...\n", lib->filepath, lib->id.us);
1077 #endif
1078 
1079  do_reload = true;
1080 
1081  lapp_data = wm_link_append_data_new(flag);
1082  wm_link_append_data_library_add(lapp_data, path);
1083  }
1084  else {
1085  int totfiles = 0;
1086 
1087 #ifdef PRINT_DEBUG
1088  printf("We are supposed to relocate '%s' lib to new '%s' one...\n", lib->filepath, libname);
1089 #endif
1090 
1091  /* Check if something is indicated for relocate. */
1092  prop = RNA_struct_find_property(op->ptr, "files");
1093  if (prop) {
1094  totfiles = RNA_property_collection_length(op->ptr, prop);
1095  if (totfiles == 0) {
1096  if (!libname[0]) {
1097  BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
1098  return OPERATOR_CANCELLED;
1099  }
1100  }
1101  }
1102 
1103  lapp_data = wm_link_append_data_new(flag);
1104 
1105  if (totfiles) {
1106  RNA_BEGIN (op->ptr, itemptr, "files") {
1107  RNA_string_get(&itemptr, "name", relname);
1108 
1109  BLI_join_dirfile(path, sizeof(path), root, relname);
1110 
1111  if (BLI_path_cmp(path, lib->filepath_abs) == 0 || !BLO_has_bfile_extension(relname)) {
1112  continue;
1113  }
1114 
1115 #ifdef PRINT_DEBUG
1116  printf("\t candidate new lib to reload datablocks from: %s\n", path);
1117 #endif
1118  wm_link_append_data_library_add(lapp_data, path);
1119  }
1120  RNA_END;
1121  }
1122  else {
1123 #ifdef PRINT_DEBUG
1124  printf("\t candidate new lib to reload datablocks from: %s\n", path);
1125 #endif
1126  wm_link_append_data_library_add(lapp_data, path);
1127  }
1128  }
1129 
1130  if (do_reload) {
1132  }
1133 
1134  lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload);
1135 
1136  wm_link_append_data_free(lapp_data);
1137 
1138  /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
1139  BLI_strncpy(G.lib, root, FILE_MAX);
1140 
1142 
1143  return OPERATOR_FINISHED;
1144  }
1145 
1146  return OPERATOR_CANCELLED;
1147 }
1148 
1150 {
1151  return wm_lib_relocate_exec_do(C, op, false);
1152 }
1153 
1155 {
1156  PropertyRNA *prop;
1157 
1158  ot->name = "Relocate Library";
1159  ot->idname = "WM_OT_lib_relocate";
1160  ot->description = "Relocate the given library to one or several others";
1161 
1164 
1165  ot->flag |= OPTYPE_UNDO;
1166 
1167  prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to relocate");
1169 
1172  FILE_BLENDER,
1173  FILE_OPENFILE,
1178 }
1179 
1181 {
1182  return wm_lib_relocate_exec_do(C, op, true);
1183 }
1184 
1186 {
1187  PropertyRNA *prop;
1188 
1189  ot->name = "Reload Library";
1190  ot->idname = "WM_OT_lib_reload";
1191  ot->description = "Reload the given library";
1192 
1194 
1195  ot->flag |= OPTYPE_UNDO;
1196 
1197  prop = RNA_def_string(ot->srna, "library", NULL, MAX_NAME, "Library", "Library to reload");
1199 
1202  FILE_BLENDER,
1203  FILE_OPENFILE,
1208 }
1209 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
bool BKE_idtype_idcode_is_linkable(const short idcode)
Definition: idtype.c:232
short BKE_idtype_idcode_from_name(const char *idtype_name)
Definition: idtype.c:208
struct Key * BKE_key_from_id(struct ID *id)
Definition: key.c:1786
struct Key ** BKE_key_from_id_p(struct ID *id)
Definition: key.c:1761
void BKE_main_collection_sync(const struct Main *bmain)
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
Definition: layer.c:403
void id_us_min(struct ID *id)
Definition: lib_id.c:297
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
Definition: lib_id.c:923
void id_fake_user_set(struct ID *id)
Definition: lib_id.c:328
void BKE_main_lib_objects_recalc_all(struct Main *bmain)
Definition: lib_id.c:997
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_library_make_local(struct Main *bmain, const struct Library *lib, struct GHash *old_to_new_ids, const bool untagged_only, const bool set_fake)
void id_us_clear_real(struct ID *id)
Definition: lib_id.c:257
void id_us_plus_no_lib(struct ID *id)
Definition: lib_id.c:272
void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const int tag, const bool value)
Definition: lib_id.c:910
struct ID * BKE_libblock_find_name(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1333
void id_fake_user_clear(struct ID *id)
Definition: lib_id.c:336
void BKE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only)
Definition: lib_id.c:1773
void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint)
Definition: lib_id.c:1348
void BKE_lib_override_library_update(struct Main *bmain, struct ID *local)
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:55
@ ID_REMAP_SKIP_INDIRECT_USAGE
Definition: BKE_lib_remap.h:46
@ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE
Definition: BKE_lib_remap.h:76
void BKE_libblock_remap_locked(struct Main *bmain, void *old_idv, void *new_idv, const short remap_flags) ATTR_NONNULL(1
#define FOREACH_MAIN_ID_END
Definition: BKE_main.h:250
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
void BKE_main_unlock(struct Main *bmain)
Definition: main.c:207
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_main_lock(struct Main *bmain)
Definition: main.c:202
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition: BKE_main.h:244
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:447
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:439
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
Definition: BLI_assert.h:96
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW_MEMARENA(_mem, _tot)
Definition: BLI_bitmap.h:58
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition: bitmap.c:33
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:349
struct GSet GSet
Definition: BLI_ghash.h:189
bool BLI_ghashutil_strcmp(const void *a, const void *b)
unsigned int BLI_ghashutil_ptrhash(const void *key)
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:718
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:941
void BLI_gset_insert(GSet *gs, void *key)
Definition: BLI_ghash.c:1147
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
GSet * BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1117
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1216
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:168
#define FILE_MAX
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1737
bool BLI_path_parent_dir(char *path) ATTR_NONNULL()
Definition: path_util.c:708
#define FILE_MAXDIR
#define BLI_path_cmp
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define MIN2(a, b)
#define STREQ(a, b)
external readfile function prototypes.
struct ID * BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, const short idcode, const char *name, const struct LibraryLink_Params *params)
Definition: readfile.c:4989
@ BLO_LIBLINK_USE_PLACEHOLDERS
Definition: BLO_readfile.h:163
@ BLO_LIBLINK_FORCE_INDIRECT
Definition: BLO_readfile.h:165
void BLO_library_link_params_init_with_context(struct LibraryLink_Params *params, struct Main *bmain, const int flag, const int id_tag_extra, struct Scene *scene, struct ViewLayer *view_layer, const struct View3D *v3d)
Definition: readfile.c:5080
struct BlendHandle BlendHandle
Definition: BLO_readfile.h:49
#define BLO_EMBEDDED_STARTUP_BLEND
Definition: BLO_readfile.h:147
struct Main * BLO_library_link_begin(BlendHandle **bh, const char *filepath, const struct LibraryLink_Params *params)
Definition: readfile.c:5109
void BLO_library_link_end(struct Main *mainl, BlendHandle **bh, const struct LibraryLink_Params *params)
Definition: readfile.c:5258
BlendHandle * BLO_blendhandle_from_memory(const void *mem, int memsize)
Definition: readblenentry.c:87
BlendHandle * BLO_blendhandle_from_file(const char *filepath, struct ReportList *reports)
Definition: readblenentry.c:71
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
Definition: readfile.c:1701
bool BLO_has_bfile_extension(const char *str)
Definition: readfile.c:1684
void BLO_blendhandle_close(BlendHandle *bh)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
ID and Library types, which are fundamental for sdna.
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:438
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:524
@ LIB_TAG_PRE_EXISTING
Definition: DNA_ID.h:556
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
@ LIB_TAG_MISSING
Definition: DNA_ID.h:537
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define MAX_ID_NAME
Definition: DNA_ID.h:269
@ LIB_FAKEUSER
Definition: DNA_ID.h:477
@ INDEX_ID_MAX
Definition: DNA_ID.h:859
@ ID_LI
Definition: DNA_ID_enums.h:58
@ ID_WS
Definition: DNA_ID_enums.h:91
#define MAX_NAME
Definition: DNA_defs.h:62
@ FILE_SORT_DEFAULT
@ FILE_LOADLIB
@ FILE_BLENDER
@ FILE_TYPE_BLENDER
@ FILE_TYPE_FOLDER
@ FILE_TYPE_BLENDERLIB
@ FILE_OPENFILE
@ FILE_DEFAULTDISPLAY
@ FILE_ACTIVE_COLLECTION
@ FILE_RELPATH
@ FILE_AUTOSELECT
@ FILE_OBDATA_INSTANCE
@ FILE_LINK
@ FILE_COLLECTION_INSTANCE
#define FILE_MAX_LIBEXTRA
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ RPT_ERROR_INVALID_INPUT
char datatoc_startup_blend[]
int datatoc_startup_blend_size
void IMB_colormanagement_check_file_config(struct Main *bmain)
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
Definition: RNA_access.h:1248
#define RNA_END
Definition: RNA_access.h:1255
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
#define WM_FILESEL_DIRECTORY
Definition: WM_api.h:535
#define WM_FILESEL_SHOW_PROPS
Definition: WM_api.h:540
#define WM_FILESEL_RELPATH
Definition: WM_api.h:533
#define WM_FILESEL_FILEPATH
Definition: WM_api.h:537
#define WM_FILESEL_FILES
Definition: WM_api.h:538
#define WM_FILESEL_FILENAME
Definition: WM_api.h:536
#define NC_WINDOW
Definition: WM_types.h:277
@ OPTYPE_UNDO
Definition: WM_types.h:155
std::string id_name(void *id)
Scene scene
DRWShaderLibrary * lib
static FT_Library library
Definition: freetypefont.c:51
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static unsigned c
Definition: RandGen.cpp:97
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2331
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:6514
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:6685
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3903
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3675
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
struct ID * reference
Definition: DNA_ID.h:250
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
struct Library * lib
Definition: DNA_ID.h:277
int us
Definition: DNA_ID.h:293
IDOverrideLibrary * override_library
Definition: DNA_ID.h:317
short flag
Definition: DNA_ID.h:288
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
ID id
Definition: DNA_key_types.h:79
ID id
Definition: DNA_ID.h:349
struct Library * parent
Definition: DNA_ID.h:365
LinkNode * list
Definition: BLI_linklist.h:50
void * link
Definition: BLI_linklist.h:40
struct LinkNode * next
Definition: BLI_linklist.h:39
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
short subversionfile
Definition: BKE_main.h:119
short versionfile
Definition: BKE_main.h:119
struct Library * curlib
Definition: BKE_main.h:145
BLI_bitmap * libraries
LinkNodePair libraries
MemArena * memarena
LinkNodePair items
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
#define G(x, y, z)
uint len
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.c:3156
void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, short action, short flag, short display, short sort)
bool WM_operator_winactive(bContext *C)