Blender  V3.3
tree_display_libraries.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_listbase.h"
9 
10 #include "BKE_collection.h"
11 #include "BKE_main.h"
12 
13 #include "DNA_collection_types.h"
14 #include "DNA_space_types.h"
15 
16 #include "BLT_translation.h"
17 
18 #include "../outliner_intern.hh"
19 #include "common.hh"
20 #include "tree_display.hh"
21 #include "tree_element.hh"
22 
23 namespace blender::ed::outliner {
24 
25 template<typename T> using List = ListBaseWrapper<T>;
26 
28  : AbstractTreeDisplay(space_outliner)
29 {
30 }
31 
33 {
34  ListBase tree = {nullptr};
35 
36  {
37  /* current file first - mainvar provides tselem with unique pointer - not used */
38  TreeElement *ten = add_library_contents(*source_data.bmain, tree, nullptr);
39  TreeStoreElem *tselem;
40 
41  if (ten) {
42  tselem = TREESTORE(ten);
43  if (!tselem->used) {
44  tselem->flag &= ~TSE_CLOSED;
45  }
46  }
47  }
48 
49  for (ID *id : List<ID>(source_data.bmain->libraries)) {
50  Library *lib = reinterpret_cast<Library *>(id);
51  TreeElement *ten = add_library_contents(*source_data.bmain, tree, lib);
52  /* NULL-check matters, due to filtering there may not be a new element. */
53  if (ten) {
54  lib->id.newid = (ID *)ten;
55  }
56  }
57 
58  /* make hierarchy */
59  for (TreeElement *ten : List<TreeElement>(tree)) {
60  if (ten == tree.first) {
61  /* First item is main, skip. */
62  continue;
63  }
64 
65  TreeStoreElem *tselem = TREESTORE(ten);
66  Library *lib = (Library *)tselem->id;
67  BLI_assert(!lib || (GS(lib->id.name) == ID_LI));
68  if (!lib || !lib->parent) {
69  continue;
70  }
71 
72  TreeElement *parent = (TreeElement *)lib->parent->id.newid;
73 
74  if (tselem->id->tag & LIB_TAG_INDIRECT) {
75  /* Only remove from 'first level' if lib is not also directly used. */
76  BLI_remlink(&tree, ten);
77  BLI_addtail(&parent->subtree, ten);
78  ten->parent = parent;
79  }
80  else {
81  /* Else, make a new copy of the libtree for our parent. */
82  TreeElement *dupten = add_library_contents(*source_data.bmain, parent->subtree, lib);
83  if (dupten) {
84  dupten->parent = parent;
85  }
86  }
87  }
88  /* restore newid pointers */
89  for (ID *library_id : List<ID>(source_data.bmain->libraries)) {
90  library_id->newid = nullptr;
91  }
92 
93  return tree;
94 }
95 
96 TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, ListBase &lb, Library *lib)
97 {
98  const short filter_id_type = id_filter_get();
99 
100  ListBase *lbarray[INDEX_ID_MAX];
101  int tot;
102  if (filter_id_type) {
103  lbarray[0] = which_libbase(&mainvar, space_outliner_.filter_id_type);
104  tot = 1;
105  }
106  else {
107  tot = set_listbasepointers(&mainvar, lbarray);
108  }
109 
110  TreeElement *tenlib = nullptr;
111  for (int a = 0; a < tot; a++) {
112  if (!lbarray[a] || !lbarray[a]->first) {
113  continue;
114  }
115 
116  ID *id = static_cast<ID *>(lbarray[a]->first);
117  const bool is_library = (GS(id->name) == ID_LI) && (lib != nullptr);
118 
119  /* Don't show deprecated types. */
120  if (ID_TYPE_IS_DEPRECATED(GS(id->name))) {
121  continue;
122  }
123 
124  /* check if there's data in current lib */
125  for (ID *id_iter : List<ID>(lbarray[a])) {
126  if (id_iter->lib == lib) {
127  id = id_iter;
128  break;
129  }
130  }
131 
132  /* We always want to create an entry for libraries, even if/when we have no more IDs from them.
133  * This invalid state is important to show to user as well. */
134  if (id != nullptr || is_library) {
135  if (!tenlib) {
136  /* Create library tree element on demand, depending if there are any data-blocks. */
137  if (lib) {
138  tenlib = outliner_add_element(&space_outliner_, &lb, lib, nullptr, TSE_SOME_ID, 0);
139  }
140  else {
141  tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0);
142  tenlib->name = IFACE_("Current File");
143  }
144  }
145 
146  /* Create data-block list parent element on demand. */
147  if (id != nullptr) {
148  TreeElement *ten;
149 
150  if (filter_id_type) {
151  ten = tenlib;
152  }
153  else {
154  ten = outliner_add_element(
155  &space_outliner_, &tenlib->subtree, lib, nullptr, TSE_ID_BASE, a);
156  ten->directdata = lbarray[a];
158  }
159 
160  for (ID *id : List<ID>(lbarray[a])) {
161  if (library_id_filter_poll(lib, id)) {
163  }
164  }
165  }
166  }
167  }
168 
169  return tenlib;
170 }
171 
172 short TreeDisplayLibraries::id_filter_get() const
173 {
176  }
177  return 0;
178 }
179 
180 bool TreeDisplayLibraries::library_id_filter_poll(const Library *lib, ID *id) const
181 {
182  if (id->lib != lib) {
183  return false;
184  }
185 
186  if (id_filter_get() == ID_GR) {
187  /* Don't show child collections of non-scene master collection,
188  * they are already shown as children. */
189  Collection *collection = (Collection *)id;
190  bool has_non_scene_parent = false;
191 
192  for (CollectionParent *cparent : List<CollectionParent>(collection->parents)) {
193  if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
194  has_non_scene_parent = true;
195  }
196  }
197 
198  if (has_non_scene_parent) {
199  return false;
200  }
201  }
202 
203  return true;
204 }
205 
206 } // namespace blender::ed::outliner
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
Definition: main.c:654
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:567
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
#define IFACE_(msgid)
@ INDEX_ID_MAX
Definition: DNA_ID.h:1058
#define ID_TYPE_IS_DEPRECATED(id_type)
Definition: DNA_ID.h:608
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:677
@ ID_LI
Definition: DNA_ID_enums.h:46
@ ID_GR
Definition: DNA_ID_enums.h:65
Object groups, one object can be in many groups at once.
@ COLLECTION_IS_MASTER
@ TSE_ID_BASE
@ TSE_SOME_ID
@ TSE_CLOSED
@ SO_FILTER_ID_TYPE
Base Class For Tree-Displays.
Definition: tree_display.hh:62
ListBase buildTree(const TreeSourceData &source_data) override
TreeDisplayLibraries(SpaceOutliner &space_outliner)
const char * outliner_idcode_to_plural(short idcode)
Definition: common.cc:28
void * tree
DRWShaderLibrary * lib
#define GS(x)
Definition: iris.c:225
static unsigned a[3]
Definition: RandGen.cpp:78
TreeElement * outliner_add_element(SpaceOutliner *space_outliner, ListBase *lb, void *idv, TreeElement *parent, short type, short index, const bool expand)
#define TREESTORE(a)
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
struct Library * lib
Definition: DNA_ID.h:372
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase libraries
Definition: BKE_main.h:169
struct TreeElement * parent
ListBase subtree
const char * name
The data to build the tree from.
Definition: tree_display.hh:43
Establish and manage Outliner trees for different display modes.