Blender  V3.3
outliner_draw.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2004 Blender Foundation. All rights reserved. */
3 
8 #include "DNA_armature_types.h"
9 #include "DNA_collection_types.h"
10 #include "DNA_constraint_types.h"
12 #include "DNA_gpencil_types.h"
13 #include "DNA_light_types.h"
14 #include "DNA_lightprobe_types.h"
15 #include "DNA_object_force_types.h"
16 #include "DNA_object_types.h"
17 #include "DNA_scene_types.h"
18 #include "DNA_sequence_types.h"
19 #include "DNA_text_types.h"
20 
21 #include "BLI_blenlib.h"
22 #include "BLI_math.h"
23 #include "BLI_mempool.h"
24 #include "BLI_string_utils.h"
25 #include "BLI_utildefines.h"
26 
27 #include "BLT_translation.h"
28 
29 #include "BKE_armature.h"
30 #include "BKE_context.h"
31 #include "BKE_curve.h"
32 #include "BKE_deform.h"
33 #include "BKE_gpencil.h"
34 #include "BKE_idtype.h"
35 #include "BKE_layer.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_lib_override.h"
38 #include "BKE_library.h"
39 #include "BKE_main.h"
40 #include "BKE_main_namemap.h"
41 #include "BKE_modifier.h"
42 #include "BKE_node.h"
43 #include "BKE_object.h"
44 #include "BKE_particle.h"
45 #include "BKE_report.h"
46 
47 #include "DEG_depsgraph.h"
48 #include "DEG_depsgraph_build.h"
49 
50 #include "ED_armature.h"
51 #include "ED_fileselect.h"
52 #include "ED_outliner.h"
53 #include "ED_screen.h"
54 
55 #include "WM_api.h"
56 #include "WM_message.h"
57 #include "WM_types.h"
58 
59 #include "GPU_immediate.h"
60 #include "GPU_state.h"
61 
62 #include "UI_interface.h"
63 #include "UI_interface_icons.h"
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
66 
67 #include "RNA_access.h"
68 
69 #include "outliner_intern.hh"
70 #include "tree/tree_display.hh"
71 #include "tree/tree_element.hh"
72 #include "tree/tree_element_id.hh"
74 #include "tree/tree_element_rna.hh"
75 #include "tree/tree_iterator.hh"
76 
77 using namespace blender;
78 using namespace blender::ed::outliner;
79 
80 /* -------------------------------------------------------------------- */
84 static void outliner_tree_dimensions_impl(SpaceOutliner *space_outliner,
85  ListBase *lb,
86  int *width,
87  int *height)
88 {
89  LISTBASE_FOREACH (TreeElement *, te, lb) {
90  *width = MAX2(*width, te->xend);
91  if (height != nullptr) {
92  *height += UI_UNIT_Y;
93  }
94 
95  TreeStoreElem *tselem = TREESTORE(te);
96  if (TSELEM_OPEN(tselem, space_outliner)) {
97  outliner_tree_dimensions_impl(space_outliner, &te->subtree, width, height);
98  }
99  else {
100  outliner_tree_dimensions_impl(space_outliner, &te->subtree, width, nullptr);
101  }
102  }
103 }
104 
105 void outliner_tree_dimensions(SpaceOutliner *space_outliner, int *r_width, int *r_height)
106 {
107  *r_width = 0;
108  *r_height = 0;
109  outliner_tree_dimensions_impl(space_outliner, &space_outliner->tree, r_width, r_height);
110 }
111 
115 static bool is_object_data_in_editmode(const ID *id, const Object *obact)
116 {
117  if (id == nullptr) {
118  return false;
119  }
120 
121  const short id_type = GS(id->name);
122 
123  if (id_type == ID_GD && obact && obact->data == id) {
124  bGPdata *gpd = (bGPdata *)id;
125  return GPENCIL_EDIT_MODE(gpd);
126  }
127 
128  return ((obact && (obact->mode & OB_MODE_EDIT)) && (id && OB_DATA_SUPPORT_EDITMODE(id_type)) &&
129  (GS(((ID *)obact->data)->name) == id_type) && BKE_object_data_is_in_editmode(obact, id));
130 }
131 
134 /* -------------------------------------------------------------------- */
139  EditBone *ebone_parent,
140  int flag,
141  bool set_flag)
142 {
143  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
144  if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
145  if (set_flag) {
146  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
147  ebone->flag |= flag;
148  }
149  else {
150  ebone->flag &= ~flag;
151  }
152  }
153  }
154 }
155 
156 static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_flag)
157 {
158  LISTBASE_FOREACH (Bone *, bone, &bone_parent->childbase) {
159  if (set_flag) {
160  bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
161  bone->flag |= flag;
162  }
163  else {
164  bone->flag &= ~flag;
165  }
166  restrictbutton_recursive_bone(bone, flag, set_flag);
167  }
168 }
169 
170 static void restrictbutton_r_lay_fn(bContext *C, void *poin, void *UNUSED(poin2))
171 {
173 }
174 
175 static void restrictbutton_bone_visibility_fn(bContext *C, void *poin, void *UNUSED(poin2))
176 {
177  Bone *bone = (Bone *)poin;
178 
181  }
182 }
183 
184 static void restrictbutton_bone_select_fn(bContext *C, void *UNUSED(poin), void *poin2)
185 {
186  Bone *bone = (Bone *)poin2;
187  if (bone->flag & BONE_UNSELECTABLE) {
188  bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
189  }
190 
193  }
194 
196 }
197 
198 static void restrictbutton_ebone_select_fn(bContext *C, void *poin, void *poin2)
199 {
200  bArmature *arm = (bArmature *)poin;
201  EditBone *ebone = (EditBone *)poin2;
202 
203  if (ebone->flag & BONE_UNSELECTABLE) {
204  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
205  }
206 
209  arm, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0);
210  }
211 
213 }
214 
215 static void restrictbutton_ebone_visibility_fn(bContext *C, void *poin, void *poin2)
216 {
217  bArmature *arm = (bArmature *)poin;
218  EditBone *ebone = (EditBone *)poin2;
219  if (ebone->flag & BONE_HIDDEN_A) {
220  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
221  }
222 
224  restrictbutton_recursive_ebone(arm, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0);
225  }
226 
228 }
229 
230 static void restrictbutton_gp_layer_flag_fn(bContext *C, void *poin, void *UNUSED(poin2))
231 {
232  ID *id = (ID *)poin;
233 
236 }
237 
238 static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
239 {
240  ID *id = (ID *)poin;
241 
242  BLI_assert(id != nullptr);
243 
244  if (id->flag & LIB_FAKEUSER) {
245  id_us_plus(id);
246  }
247  else {
248  id_us_min(id);
249  }
250 }
251 
253  Base *base,
254  Object *ob,
255  const char *propname)
256 {
257  Main *bmain = CTX_data_main(C);
258  wmWindow *win = CTX_wm_window(C);
260  ViewLayer *view_layer = CTX_data_view_layer(C);
261  PointerRNA ptr;
262 
263  bool extend = (win->eventstate->modifier & KM_SHIFT);
264 
265  if (!extend) {
266  return;
267  }
268 
269  /* Create PointerRNA and PropertyRNA for either Object or Base. */
270  ID *id = ob ? &ob->id : &scene->id;
271  StructRNA *struct_rna = ob ? &RNA_Object : &RNA_ObjectBase;
272  void *data = ob ? (void *)ob : (void *)base;
273 
274  RNA_pointer_create(id, struct_rna, data, &ptr);
275  PropertyRNA *base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
276  const bool value = RNA_property_boolean_get(&ptr, base_or_object_prop);
277 
278  Object *ob_parent = ob ? ob : base->object;
279 
280  for (Object *ob_iter = reinterpret_cast<Object *>(bmain->objects.first); ob_iter;
281  ob_iter = reinterpret_cast<Object *>(ob_iter->id.next)) {
282  if (BKE_object_is_child_recursive(ob_parent, ob_iter)) {
283  if (ob) {
284  RNA_id_pointer_create(&ob_iter->id, &ptr);
286  }
287  else {
288  Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter);
289  /* Child can be in a collection excluded from viewlayer. */
290  if (base_iter == nullptr) {
291  continue;
292  }
293  RNA_pointer_create(&scene->id, &RNA_ObjectBase, base_iter, &ptr);
294  }
295  RNA_property_boolean_set(&ptr, base_or_object_prop, value);
296  }
297  }
298 
299  /* We don't call RNA_property_update() due to performance, so we batch update them. */
300  if (ob) {
303  }
304  else {
305  BKE_layer_collection_sync(scene, view_layer);
307  }
308 }
309 
313 static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
314 {
315  Object *ob = reinterpret_cast<Object *>(poin);
316  char *propname = reinterpret_cast<char *>(poin2);
317  outliner_object_set_flag_recursive_fn(C, nullptr, ob, propname);
318 }
319 
323 static void outliner__base_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
324 {
325  Base *base = reinterpret_cast<Base *>(poin);
326  char *propname = reinterpret_cast<char *>(poin2);
327  outliner_object_set_flag_recursive_fn(C, base, nullptr, propname);
328 }
329 
332  LayerCollection *layer_collection,
333  Collection *collection,
334  PointerRNA *ptr)
335 {
336  if (collection) {
337  RNA_id_pointer_create(&collection->id, ptr);
338  }
339  else {
340  RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, ptr);
341  }
342 }
343 
346  Scene *scene, ViewLayer *view_layer, Collection *collection, Object *ob, PointerRNA *ptr)
347 {
348  if (collection) {
350  }
351  else {
352  Base *base = BKE_view_layer_base_find(view_layer, ob);
353  RNA_pointer_create(&scene->id, &RNA_ObjectBase, base, ptr);
354  }
355 }
356 
357 /* NOTE: Collection is only valid when we want to change the collection data, otherwise we get it
358  * from layer collection. Layer collection is valid whenever we are looking at a view layer. */
360  ViewLayer *view_layer,
361  LayerCollection *layer_collection,
362  Collection *collection,
363  PropertyRNA *layer_or_collection_prop,
364  PropertyRNA *base_or_object_prop,
365  const bool value)
366 {
367  if (layer_collection && layer_collection->flag & LAYER_COLLECTION_EXCLUDE) {
368  return;
369  }
370  PointerRNA ptr;
371  outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
372  RNA_property_boolean_set(&ptr, layer_or_collection_prop, value);
373 
374  /* Set the same flag for the nested objects as well. */
375  if (base_or_object_prop) {
376  /* NOTE: We can't use BKE_collection_object_cache_get()
377  * otherwise we would not take collection exclusion into account. */
378  LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) {
379 
380  outliner_base_or_object_pointer_create(scene, view_layer, collection, cob->ob, &ptr);
381  RNA_property_boolean_set(&ptr, base_or_object_prop, value);
382 
383  if (collection) {
385  }
386  }
387  }
388 
389  /* Keep going recursively. */
390  ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
391  LISTBASE_FOREACH (Link *, link, lb) {
392  LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : nullptr;
393  Collection *collection_iter = layer_collection ?
394  (collection ? layer_collection_iter->collection : nullptr) :
395  ((CollectionChild *)link)->collection;
397  view_layer,
398  layer_collection_iter,
399  collection_iter,
400  layer_or_collection_prop,
401  base_or_object_prop,
402  value);
403  }
404 
405  if (collection) {
407  }
408 }
409 
421  const LayerCollection *layer_collection_cmp,
422  const Collection *collection_cmp,
423  const bool value_cmp,
424  const PropertyRNA *layer_or_collection_prop,
425  LayerCollection *layer_collection,
426  Collection *collection)
427 {
428  PointerRNA ptr;
429  outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
430  const bool value = RNA_property_boolean_get(&ptr, (PropertyRNA *)layer_or_collection_prop);
431  Collection *collection_ensure = collection ? collection : layer_collection->collection;
432  const Collection *collection_ensure_cmp = collection_cmp ? collection_cmp :
433  layer_collection_cmp->collection;
434 
435  if (collection_ensure->flag & COLLECTION_IS_MASTER) {
436  }
437  else if (collection_ensure == collection_ensure_cmp) {
438  }
439  else if (BKE_collection_has_collection(collection_ensure, (Collection *)collection_ensure_cmp) ||
440  BKE_collection_has_collection((Collection *)collection_ensure_cmp, collection_ensure)) {
441  /* This collection is either a parent or a child of the collection.
442  * We expect it to be set "visible" already. */
443  if (value != value_cmp) {
444  return false;
445  }
446  }
447  else {
448  /* This collection is neither a parent nor a child of the collection.
449  * We expect it to be "invisible". */
450  if (value == value_cmp) {
451  return false;
452  }
453  }
454 
455  /* Keep going recursively. */
456  ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
457  LISTBASE_FOREACH (Link *, link, lb) {
458  LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : nullptr;
459  Collection *collection_iter = layer_collection ?
460  (collection ? layer_collection_iter->collection : nullptr) :
461  ((CollectionChild *)link)->collection;
462  if (layer_collection_iter && layer_collection_iter->flag & LAYER_COLLECTION_EXCLUDE) {
463  continue;
464  }
466  layer_collection_cmp,
467  collection_cmp,
468  value_cmp,
469  layer_or_collection_prop,
470  layer_collection_iter,
471  collection_iter)) {
472  return false;
473  }
474  }
475 
476  return true;
477 }
478 
480  ViewLayer *view_layer,
481  LayerCollection *layer_collection,
482  Collection *collection,
483  PropertyRNA *layer_or_collection_prop,
484  const char *propname,
485  const bool value)
486 {
487  PointerRNA ptr;
488  const bool is_hide = strstr(propname, "hide_") != nullptr;
489 
490  LayerCollection *top_layer_collection = layer_collection ?
491  reinterpret_cast<LayerCollection *>(
492  view_layer->layer_collections.first) :
493  nullptr;
494  Collection *top_collection = collection ? scene->master_collection : nullptr;
495 
496  bool was_isolated = (value == is_hide);
497  was_isolated &= outliner_collection_is_isolated(scene,
498  layer_collection,
499  collection,
500  !is_hide,
501  layer_or_collection_prop,
502  top_layer_collection,
503  top_collection);
504 
505  if (was_isolated) {
506  const bool default_value = RNA_property_boolean_get_default(nullptr, layer_or_collection_prop);
507  /* Make every collection go back to its default "visibility" state. */
509  view_layer,
510  top_layer_collection,
511  top_collection,
512  layer_or_collection_prop,
513  nullptr,
514  default_value);
515  return;
516  }
517 
518  /* Make every collection "invisible". */
520  view_layer,
521  top_layer_collection,
522  top_collection,
523  layer_or_collection_prop,
524  nullptr,
525  is_hide);
526 
527  /* Make this collection and its children collections the only "visible". */
529  view_layer,
530  layer_collection,
531  collection,
532  layer_or_collection_prop,
533  nullptr,
534  !is_hide);
535 
536  /* Make this collection direct parents also "visible". */
537  if (layer_collection) {
538  LayerCollection *lc_parent = layer_collection;
539  LISTBASE_FOREACH (LayerCollection *, lc_iter, &top_layer_collection->layer_collections) {
540  if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
541  lc_parent = lc_iter;
542  break;
543  }
544  }
545 
546  while (lc_parent != layer_collection) {
548  scene, lc_parent, collection ? lc_parent->collection : nullptr, &ptr);
549  RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
550 
551  LISTBASE_FOREACH (LayerCollection *, lc_iter, &lc_parent->layer_collections) {
552  if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
553  lc_parent = lc_iter;
554  break;
555  }
556  }
557  }
558  }
559  else {
560  CollectionParent *parent;
561  Collection *child = collection;
562  while ((parent = reinterpret_cast<CollectionParent *>(child->parents.first))) {
563  if (parent->collection->flag & COLLECTION_IS_MASTER) {
564  break;
565  }
566  RNA_id_pointer_create(&parent->collection->id, &ptr);
567  RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
568  child = parent->collection;
569  }
570  }
571 }
572 
574  LayerCollection *layer_collection,
575  Collection *collection,
576  const char *propname)
577 {
578  Main *bmain = CTX_data_main(C);
579  wmWindow *win = CTX_wm_window(C);
581  ViewLayer *view_layer = CTX_data_view_layer(C);
582  PointerRNA ptr;
583 
584  bool do_isolate = (win->eventstate->modifier & KM_CTRL);
585  bool extend = (win->eventstate->modifier & KM_SHIFT);
586 
587  if (!ELEM(true, do_isolate, extend)) {
588  return;
589  }
590 
591  /* Create PointerRNA and PropertyRNA for either Collection or LayerCollection. */
592  ID *id = collection ? &collection->id : &scene->id;
593  StructRNA *struct_rna = collection ? &RNA_Collection : &RNA_LayerCollection;
594  void *data = collection ? (void *)collection : (void *)layer_collection;
595 
596  RNA_pointer_create(id, struct_rna, data, &ptr);
597  outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
598  PropertyRNA *layer_or_collection_prop = RNA_struct_type_find_property(struct_rna, propname);
599  const bool value = RNA_property_boolean_get(&ptr, layer_or_collection_prop);
600 
601  PropertyRNA *base_or_object_prop = nullptr;
602  if (layer_collection != nullptr) {
603  /* If we are toggling Layer collections we still want to change the properties of the base
604  * or the objects. If we have a matching property, toggle it as well, it can be NULL. */
605  struct_rna = collection ? &RNA_Object : &RNA_ObjectBase;
606  base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
607  }
608 
609  if (extend) {
611  view_layer,
612  layer_collection,
613  collection,
614  layer_or_collection_prop,
615  base_or_object_prop,
616  value);
617  }
618  else {
620  view_layer,
621  layer_collection,
622  collection,
623  layer_or_collection_prop,
624  propname,
625  value);
626  }
627 
628  /* We don't call RNA_property_update() due to performance, so we batch update them. */
631 }
632 
638  void *poin,
639  void *poin2)
640 {
641  LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>(poin);
642  char *propname = reinterpret_cast<char *>(poin2);
643  outliner_collection_set_flag_recursive_fn(C, layer_collection, nullptr, propname);
644 }
645 
650 static void view_layer__collection_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
651 {
652  LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>(poin);
653  char *propname = reinterpret_cast<char *>(poin2);
655  C, layer_collection, layer_collection->collection, propname);
656 }
657 
662 static void scenes__collection_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
663 {
664  Collection *collection = reinterpret_cast<Collection *>(poin);
665  char *propname = reinterpret_cast<char *>(poin2);
666  outliner_collection_set_flag_recursive_fn(C, nullptr, collection, propname);
667 }
668 
669 static void namebutton_fn(bContext *C, void *tsep, char *oldname)
670 {
671  Main *bmain = CTX_data_main(C);
672  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
673  struct wmMsgBus *mbus = CTX_wm_message_bus(C);
674  BLI_mempool *ts = space_outliner->treestore;
675  TreeStoreElem *tselem = reinterpret_cast<TreeStoreElem *>(tsep);
676 
677  if (ts && tselem) {
678  TreeElement *te = outliner_find_tree_element(&space_outliner->tree, tselem);
679 
680  if (tselem->type == TSE_SOME_ID) {
681  BKE_main_namemap_remove_name(bmain, tselem->id, oldname);
682  BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
683 
684  WM_msg_publish_rna_prop(mbus, tselem->id, tselem->id, ID, name);
685 
686  switch (GS(tselem->id->name)) {
687  case ID_MA:
689  break;
690  case ID_TE:
692  break;
693  case ID_IM:
694  WM_event_add_notifier(C, NC_IMAGE, nullptr);
695  break;
696  case ID_SCE:
697  WM_event_add_notifier(C, NC_SCENE, nullptr);
698  break;
699  case ID_OB: {
700  Object *ob = (Object *)tselem->id;
701  if (ob->type == OB_MBALL) {
703  }
704  break;
705  }
706  default:
707  break;
708  }
709  WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
710 
711  /* Check the library target exists */
712  if (te->idcode == ID_LI) {
713  Library *lib = (Library *)tselem->id;
714  char expanded[FILE_MAX];
715 
716  BKE_library_filepath_set(bmain, lib, lib->filepath);
717 
718  BLI_strncpy(expanded, lib->filepath, sizeof(expanded));
719  BLI_path_abs(expanded, BKE_main_blendfile_path(bmain));
720  if (!BLI_exists(expanded)) {
722  RPT_ERROR,
723  "Library path '%s' does not exist, correct this before saving",
724  expanded);
725  }
726  else if (lib->id.tag & LIB_TAG_MISSING) {
728  RPT_INFO,
729  "Library path '%s' is now valid, please reload the library",
730  expanded);
731  lib->id.tag &= ~LIB_TAG_MISSING;
732  }
733  }
734 
736  }
737  else {
738  switch (tselem->type) {
739  case TSE_DEFGROUP: {
740  Object *ob = (Object *)tselem->id;
741  bDeformGroup *vg = reinterpret_cast<bDeformGroup *>(te->directdata);
743  WM_msg_publish_rna_prop(mbus, &ob->id, vg, VertexGroup, name);
745  break;
746  }
747  case TSE_NLA_ACTION: {
748  bAction *act = (bAction *)tselem->id;
749  BKE_main_namemap_remove_name(bmain, &act->id, oldname);
751  WM_msg_publish_rna_prop(mbus, &act->id, &act->id, ID, name);
753  break;
754  }
755  case TSE_EBONE: {
756  bArmature *arm = (bArmature *)tselem->id;
757  if (arm->edbo) {
758  EditBone *ebone = reinterpret_cast<EditBone *>(te->directdata);
759  char newname[sizeof(ebone->name)];
760 
761  /* restore bone name */
762  BLI_strncpy(newname, ebone->name, sizeof(ebone->name));
763  BLI_strncpy(ebone->name, oldname, sizeof(ebone->name));
764  ED_armature_bone_rename(bmain, arm, oldname, newname);
765  WM_msg_publish_rna_prop(mbus, &arm->id, ebone, EditBone, name);
768  }
769  break;
770  }
771 
772  case TSE_BONE: {
773  TreeViewContext tvc;
775 
776  bArmature *arm = (bArmature *)tselem->id;
777  Bone *bone = reinterpret_cast<Bone *>(te->directdata);
778  char newname[sizeof(bone->name)];
779 
780  /* always make current object active */
781  tree_element_activate(C, &tvc, te, OL_SETSEL_NORMAL, true);
782 
783  /* restore bone name */
784  BLI_strncpy(newname, bone->name, sizeof(bone->name));
785  BLI_strncpy(bone->name, oldname, sizeof(bone->name));
786  ED_armature_bone_rename(bmain, arm, oldname, newname);
787  WM_msg_publish_rna_prop(mbus, &arm->id, bone, Bone, name);
790  break;
791  }
792  case TSE_POSE_CHANNEL: {
793  TreeViewContext tvc;
795 
796  Object *ob = (Object *)tselem->id;
797  bArmature *arm = (bArmature *)ob->data;
798  bPoseChannel *pchan = reinterpret_cast<bPoseChannel *>(te->directdata);
799  char newname[sizeof(pchan->name)];
800 
801  /* always make current pose-bone active */
802  tree_element_activate(C, &tvc, te, OL_SETSEL_NORMAL, true);
803 
804  BLI_assert(ob->type == OB_ARMATURE);
805 
806  /* restore bone name */
807  BLI_strncpy(newname, pchan->name, sizeof(pchan->name));
808  BLI_strncpy(pchan->name, oldname, sizeof(pchan->name));
810  bmain, reinterpret_cast<bArmature *>(ob->data), oldname, newname);
811  WM_msg_publish_rna_prop(mbus, &arm->id, pchan->bone, Bone, name);
815  break;
816  }
817  case TSE_POSEGRP: {
818  Object *ob = (Object *)tselem->id; /* id = object. */
819  bActionGroup *grp = reinterpret_cast<bActionGroup *>(te->directdata);
820 
822  grp,
824  '.',
825  offsetof(bActionGroup, name),
826  sizeof(grp->name));
827  WM_msg_publish_rna_prop(mbus, &ob->id, grp, ActionGroup, name);
830  break;
831  }
832  case TSE_GP_LAYER: {
833  bGPdata *gpd = (bGPdata *)tselem->id; /* id = GP Datablock */
834  bGPDlayer *gpl = reinterpret_cast<bGPDlayer *>(te->directdata);
835 
836  /* always make layer active */
838 
839  /* XXX: name needs translation stuff. */
841  &gpd->layers, gpl, "GP Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
842 
843  WM_msg_publish_rna_prop(mbus, &gpd->id, gpl, GPencilLayer, info);
847  break;
848  }
849  case TSE_R_LAYER: {
850  Scene *scene = (Scene *)tselem->id;
851  ViewLayer *view_layer = reinterpret_cast<ViewLayer *>(te->directdata);
852 
853  /* Restore old name. */
854  char newname[sizeof(view_layer->name)];
855  BLI_strncpy(newname, view_layer->name, sizeof(view_layer->name));
856  BLI_strncpy(view_layer->name, oldname, sizeof(view_layer->name));
857 
858  /* Rename, preserving animation and compositing data. */
859  BKE_view_layer_rename(bmain, scene, view_layer, newname);
860  WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, ViewLayer, name);
861  WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
863  break;
864  }
865  case TSE_LAYER_COLLECTION: {
866  /* The ID is a #Collection, not a #LayerCollection */
867  Collection *collection = (Collection *)tselem->id;
868  BKE_main_namemap_remove_name(bmain, &collection->id, oldname);
869  BLI_libblock_ensure_unique_name(bmain, collection->id.name);
870  WM_msg_publish_rna_prop(mbus, &collection->id, &collection->id, ID, name);
871  WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
873  break;
874  }
875  }
876  }
877  tselem->flag &= ~TSE_TEXTBUT;
878  }
879 }
880 
883 
884  PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
886  PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
887  PropertyRNA *layer_collection_exclude, *layer_collection_holdout,
888  *layer_collection_indirect_only, *layer_collection_hide_viewport;
889  PropertyRNA *modifier_show_viewport, *modifier_show_render;
892 };
893 
894 /* We don't care about the value of the property
895  * but whether the property should be active or grayed out. */
912 };
913 
915  PointerRNA *collection_ptr, RestrictProperties *props, RestrictPropertiesActive *props_active)
916 {
917  if (props_active->collection_hide_render) {
919  collection_ptr, props->collection_hide_render);
920  if (!props_active->collection_hide_render) {
921  props_active->layer_collection_holdout = false;
922  props_active->layer_collection_indirect_only = false;
923  props_active->object_hide_render = false;
924  props_active->modifier_show_render = false;
925  props_active->constraint_enable = false;
926  }
927  }
928 
929  if (props_active->collection_hide_viewport) {
931  collection_ptr, props->collection_hide_viewport);
932  if (!props_active->collection_hide_viewport) {
933  props_active->collection_hide_select = false;
934  props_active->object_hide_select = false;
935  props_active->layer_collection_hide_viewport = false;
936  props_active->object_hide_viewport = false;
937  props_active->base_hide_viewport = false;
938  props_active->modifier_show_viewport = false;
939  props_active->constraint_enable = false;
940  }
941  }
942 
943  if (props_active->collection_hide_select) {
945  collection_ptr, props->collection_hide_select);
946  if (!props_active->collection_hide_select) {
947  props_active->object_hide_select = false;
948  }
949  }
950 }
951 
953  PointerRNA *layer_collection_ptr,
954  PointerRNA *collection_ptr,
955  RestrictProperties *props,
956  RestrictPropertiesActive *props_active)
957 {
958  outliner_restrict_properties_enable_collection_set(collection_ptr, props, props_active);
959 
960  if (props_active->layer_collection_holdout) {
962  layer_collection_ptr, props->layer_collection_holdout);
963  }
964 
965  if (props_active->layer_collection_indirect_only) {
967  layer_collection_ptr, props->layer_collection_indirect_only);
968  }
969 
970  if (props_active->layer_collection_hide_viewport) {
972  layer_collection_ptr, props->layer_collection_hide_viewport);
973 
974  if (!props_active->layer_collection_hide_viewport) {
975  props_active->base_hide_viewport = false;
976  props_active->collection_hide_select = false;
977  props_active->object_hide_select = false;
978  }
979  }
980 
981  if (props_active->layer_collection_exclude) {
983  layer_collection_ptr, props->layer_collection_exclude);
984 
985  if (!props_active->layer_collection_exclude) {
986  props_active->collection_hide_viewport = false;
987  props_active->collection_hide_select = false;
988  props_active->collection_hide_render = false;
989  props_active->layer_collection_hide_viewport = false;
990  props_active->layer_collection_holdout = false;
991  props_active->layer_collection_indirect_only = false;
992  }
993  }
994 }
995 
997  TreeElement *te,
998  PointerRNA *collection_ptr,
999  PointerRNA *layer_collection_ptr,
1000  RestrictProperties *props,
1001  RestrictPropertiesActive *props_active)
1002 {
1003  TreeStoreElem *tselem = TREESTORE(te);
1004  LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
1005  reinterpret_cast<LayerCollection *>(te->directdata) :
1006  nullptr;
1008 
1009  if (collection->flag & COLLECTION_IS_MASTER) {
1010  return false;
1011  }
1012 
1013  /* Create the PointerRNA. */
1014  RNA_id_pointer_create(&collection->id, collection_ptr);
1015  if (layer_collection != nullptr) {
1016  RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, layer_collection_ptr);
1017  }
1018 
1019  /* Update the restriction column values for the collection children. */
1020  if (layer_collection) {
1022  layer_collection_ptr, collection_ptr, props, props_active);
1023  }
1024  else {
1025  outliner_restrict_properties_enable_collection_set(collection_ptr, props, props_active);
1026  }
1027  return true;
1028 }
1029 
1031  Scene *scene,
1032  ViewLayer *view_layer,
1033  ARegion *region,
1034  SpaceOutliner *space_outliner,
1035  ListBase *lb,
1036  RestrictPropertiesActive props_active_parent)
1037 {
1038  /* Get RNA properties (once for speed). */
1039  static RestrictProperties props = {false};
1040  if (!props.initialized) {
1041  props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
1042  props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
1043  props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
1044  props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport");
1046  "hide_viewport");
1047  props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
1048  props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
1049  props.layer_collection_exclude = RNA_struct_type_find_property(&RNA_LayerCollection,
1050  "exclude");
1051  props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection,
1052  "holdout");
1054  "indirect_only");
1056  "hide_viewport");
1057  props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
1058  props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
1059 
1060  props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute");
1061 
1062  props.bone_hide_viewport = RNA_struct_type_find_property(&RNA_Bone, "hide");
1063 
1064  props.initialized = true;
1065  }
1066 
1067  struct {
1068  int enable;
1069  int select;
1070  int hide;
1071  int viewport;
1072  int render;
1073  int indirect_only;
1074  int holdout;
1075  } restrict_offsets = {0};
1076  int restrict_column_offset = 0;
1077 
1078  /* This will determine the order of drawing from RIGHT to LEFT. */
1079  if (space_outliner->outlinevis == SO_VIEW_LAYER) {
1080  if (space_outliner->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
1081  restrict_offsets.indirect_only = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1082  }
1083  if (space_outliner->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
1084  restrict_offsets.holdout = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1085  }
1086  }
1087  if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) {
1088  restrict_offsets.render = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1089  }
1090  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1091  restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1092  }
1093  if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
1094  restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1095  }
1096  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1097  restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1098  }
1099  if (space_outliner->outlinevis == SO_VIEW_LAYER &&
1100  space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) {
1101  restrict_offsets.enable = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
1102  }
1103 
1104  BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) ==
1105  outliner_right_columns_width(space_outliner));
1106 
1107  /* Create buttons. */
1108  uiBut *bt;
1109 
1110  LISTBASE_FOREACH (TreeElement *, te, lb) {
1111  TreeStoreElem *tselem = TREESTORE(te);
1112  RestrictPropertiesActive props_active = props_active_parent;
1113 
1114  if (te->ys + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && te->ys <= region->v2d.cur.ymax) {
1115  if (tselem->type == TSE_R_LAYER &&
1116  ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) {
1117  if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) {
1118  /* View layer render toggle. */
1119  ViewLayer *layer = reinterpret_cast<ViewLayer *>(te->directdata);
1120 
1121  bt = uiDefIconButBitS(block,
1124  0,
1125  ICON_RESTRICT_RENDER_OFF,
1126  (int)(region->v2d.cur.xmax - restrict_offsets.render),
1127  te->ys,
1128  UI_UNIT_X,
1129  UI_UNIT_Y,
1130  &layer->flag,
1131  0,
1132  0,
1133  0,
1134  0,
1135  TIP_("Use view layer for rendering"));
1136  UI_but_func_set(bt, restrictbutton_r_lay_fn, tselem->id, nullptr);
1139  }
1140  }
1141  else if (((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) &&
1142  (te->flag & TE_CHILD_NOT_IN_COLLECTION)) {
1143  /* Don't show restrict columns for children that are not directly inside the collection. */
1144  }
1145  else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
1146  PointerRNA ptr;
1147  Object *ob = (Object *)tselem->id;
1148  RNA_id_pointer_create(&ob->id, &ptr);
1149 
1150  if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
1151  Base *base = (te->directdata) ? (Base *)te->directdata :
1152  BKE_view_layer_base_find(view_layer, ob);
1153  if (base) {
1154  PointerRNA base_ptr;
1155  RNA_pointer_create(&scene->id, &RNA_ObjectBase, base, &base_ptr);
1156  bt = uiDefIconButR_prop(block,
1158  0,
1159  0,
1160  (int)(region->v2d.cur.xmax - restrict_offsets.hide),
1161  te->ys,
1162  UI_UNIT_X,
1163  UI_UNIT_Y,
1164  &base_ptr,
1165  props.base_hide_viewport,
1166  -1,
1167  0,
1168  0,
1169  0,
1170  0,
1171  TIP_("Temporarily hide in viewport\n"
1172  "* Shift to set children"));
1174  bt, outliner__base_set_flag_recursive_fn, base, (void *)"hide_viewport");
1176  if (!props_active.base_hide_viewport) {
1178  }
1179  }
1180  }
1181 
1182  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1183  bt = uiDefIconButR_prop(block,
1185  0,
1186  0,
1187  (int)(region->v2d.cur.xmax - restrict_offsets.select),
1188  te->ys,
1189  UI_UNIT_X,
1190  UI_UNIT_Y,
1191  &ptr,
1192  props.object_hide_select,
1193  -1,
1194  0,
1195  0,
1196  -1,
1197  -1,
1198  TIP_("Disable selection in viewport\n"
1199  "* Shift to set children"));
1200  UI_but_func_set(bt, outliner__object_set_flag_recursive_fn, ob, (char *)"hide_select");
1202  if (!props_active.object_hide_select) {
1204  }
1205  }
1206 
1207  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1208  bt = uiDefIconButR_prop(block,
1210  0,
1211  0,
1212  (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
1213  te->ys,
1214  UI_UNIT_X,
1215  UI_UNIT_Y,
1216  &ptr,
1217  props.object_hide_viewport,
1218  -1,
1219  0,
1220  0,
1221  -1,
1222  -1,
1223  TIP_("Globally disable in viewports\n"
1224  "* Shift to set children"));
1225  UI_but_func_set(bt, outliner__object_set_flag_recursive_fn, ob, (void *)"hide_viewport");
1227  if (!props_active.object_hide_viewport) {
1229  }
1230  }
1231 
1232  if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) {
1233  bt = uiDefIconButR_prop(block,
1235  0,
1236  0,
1237  (int)(region->v2d.cur.xmax - restrict_offsets.render),
1238  te->ys,
1239  UI_UNIT_X,
1240  UI_UNIT_Y,
1241  &ptr,
1242  props.object_hide_render,
1243  -1,
1244  0,
1245  0,
1246  -1,
1247  -1,
1248  TIP_("Globally disable in renders\n"
1249  "* Shift to set children"));
1250  UI_but_func_set(bt, outliner__object_set_flag_recursive_fn, ob, (char *)"hide_render");
1252  if (!props_active.object_hide_render) {
1254  }
1255  }
1256  }
1257  else if (tselem->type == TSE_CONSTRAINT) {
1258  bConstraint *con = (bConstraint *)te->directdata;
1259 
1260  PointerRNA ptr;
1261  RNA_pointer_create(tselem->id, &RNA_Constraint, con, &ptr);
1262 
1263  if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
1264  bt = uiDefIconButR_prop(block,
1266  0,
1267  0,
1268  (int)(region->v2d.cur.xmax - restrict_offsets.hide),
1269  te->ys,
1270  UI_UNIT_X,
1271  UI_UNIT_Y,
1272  &ptr,
1273  props.constraint_enable,
1274  -1,
1275  0,
1276  0,
1277  -1,
1278  -1,
1279  nullptr);
1281  if (!props_active.constraint_enable) {
1283  }
1284  }
1285  }
1286  else if (tselem->type == TSE_MODIFIER) {
1287  ModifierData *md = (ModifierData *)te->directdata;
1288 
1289  PointerRNA ptr;
1290  RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
1291 
1292  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1293  bt = uiDefIconButR_prop(block,
1295  0,
1296  0,
1297  (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
1298  te->ys,
1299  UI_UNIT_X,
1300  UI_UNIT_Y,
1301  &ptr,
1302  props.modifier_show_viewport,
1303  -1,
1304  0,
1305  0,
1306  -1,
1307  -1,
1308  nullptr);
1310  if (!props_active.modifier_show_viewport) {
1312  }
1313  }
1314 
1315  if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) {
1316  bt = uiDefIconButR_prop(block,
1318  0,
1319  0,
1320  (int)(region->v2d.cur.xmax - restrict_offsets.render),
1321  te->ys,
1322  UI_UNIT_X,
1323  UI_UNIT_Y,
1324  &ptr,
1325  props.modifier_show_render,
1326  -1,
1327  0,
1328  0,
1329  -1,
1330  -1,
1331  nullptr);
1333  if (!props_active.modifier_show_render) {
1335  }
1336  }
1337  }
1338  else if (tselem->type == TSE_POSE_CHANNEL) {
1339  PointerRNA ptr;
1340  bPoseChannel *pchan = (bPoseChannel *)te->directdata;
1341  Bone *bone = pchan->bone;
1342  Object *ob = (Object *)tselem->id;
1343  bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
1344 
1345  RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr);
1346 
1347  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1348  bt = uiDefIconButR_prop(block,
1350  0,
1351  0,
1352  (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
1353  te->ys,
1354  UI_UNIT_X,
1355  UI_UNIT_Y,
1356  &ptr,
1357  props.bone_hide_viewport,
1358  -1,
1359  0,
1360  0,
1361  -1,
1362  -1,
1363  TIP_("Restrict visibility in the 3D View\n"
1364  "* Shift to set children"));
1368  }
1369 
1370  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1371  bt = uiDefIconButBitI(block,
1374  0,
1375  ICON_RESTRICT_SELECT_OFF,
1376  (int)(region->v2d.cur.xmax - restrict_offsets.select),
1377  te->ys,
1378  UI_UNIT_X,
1379  UI_UNIT_Y,
1380  &(bone->flag),
1381  0,
1382  0,
1383  0,
1384  0,
1385  TIP_("Restrict selection in the 3D View\n"
1386  "* Shift to set children"));
1387  UI_but_func_set(bt, restrictbutton_bone_select_fn, ob->data, bone);
1390  }
1391  }
1392  else if (tselem->type == TSE_EBONE) {
1393  bArmature *arm = (bArmature *)tselem->id;
1394  EditBone *ebone = (EditBone *)te->directdata;
1395 
1396  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1397  bt = uiDefIconButBitI(block,
1399  BONE_HIDDEN_A,
1400  0,
1401  ICON_RESTRICT_VIEW_OFF,
1402  (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
1403  te->ys,
1404  UI_UNIT_X,
1405  UI_UNIT_Y,
1406  &(ebone->flag),
1407  0,
1408  0,
1409  0,
1410  0,
1411  TIP_("Restrict visibility in the 3D View\n"
1412  "* Shift to set children"));
1416  }
1417 
1418  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1419  bt = uiDefIconButBitI(block,
1422  0,
1423  ICON_RESTRICT_SELECT_OFF,
1424  (int)(region->v2d.cur.xmax - restrict_offsets.select),
1425  te->ys,
1426  UI_UNIT_X,
1427  UI_UNIT_Y,
1428  &(ebone->flag),
1429  0,
1430  0,
1431  0,
1432  0,
1433  TIP_("Restrict selection in the 3D View\n"
1434  "* Shift to set children"));
1438  }
1439  }
1440  else if (tselem->type == TSE_GP_LAYER) {
1441  ID *id = tselem->id;
1442  bGPDlayer *gpl = (bGPDlayer *)te->directdata;
1443 
1444  if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
1445  bt = uiDefIconButBitS(block,
1447  GP_LAYER_HIDE,
1448  0,
1449  ICON_HIDE_OFF,
1450  (int)(region->v2d.cur.xmax - restrict_offsets.hide),
1451  te->ys,
1452  UI_UNIT_X,
1453  UI_UNIT_Y,
1454  &gpl->flag,
1455  0,
1456  0,
1457  0,
1458  0,
1459  TIP_("Restrict visibility in the 3D View"));
1463  }
1464 
1465  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1466  bt = uiDefIconButBitS(block,
1469  0,
1470  ICON_UNLOCKED,
1471  (int)(region->v2d.cur.xmax - restrict_offsets.select),
1472  te->ys,
1473  UI_UNIT_X,
1474  UI_UNIT_Y,
1475  &gpl->flag,
1476  0,
1477  0,
1478  0,
1479  0,
1480  TIP_("Restrict editing of strokes and keyframes in this layer"));
1483  }
1484  }
1485  else if (outliner_is_collection_tree_element(te)) {
1486  PointerRNA collection_ptr;
1487  PointerRNA layer_collection_ptr;
1488 
1490  scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active)) {
1491 
1492  LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
1493  reinterpret_cast<LayerCollection *>(
1494  te->directdata) :
1495  nullptr;
1497 
1498  if (layer_collection != nullptr) {
1499  if (space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) {
1500  bt = uiDefIconButR_prop(block,
1502  0,
1503  0,
1504  (int)(region->v2d.cur.xmax) - restrict_offsets.enable,
1505  te->ys,
1506  UI_UNIT_X,
1507  UI_UNIT_Y,
1508  &layer_collection_ptr,
1510  -1,
1511  0,
1512  0,
1513  0,
1514  0,
1515  nullptr);
1517  }
1518 
1519  if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
1520  bt = uiDefIconButR_prop(block,
1522  0,
1523  0,
1524  (int)(region->v2d.cur.xmax - restrict_offsets.hide),
1525  te->ys,
1526  UI_UNIT_X,
1527  UI_UNIT_Y,
1528  &layer_collection_ptr,
1530  -1,
1531  0,
1532  0,
1533  0,
1534  0,
1535  TIP_("Temporarily hide in viewport\n"
1536  "* Ctrl to isolate collection\n"
1537  "* Shift to set inside collections and objects"));
1538  UI_but_func_set(bt,
1540  layer_collection,
1541  (char *)"hide_viewport");
1543  if (!props_active.layer_collection_hide_viewport) {
1545  }
1546  }
1547 
1548  if (space_outliner->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
1549  bt = uiDefIconButR_prop(block,
1551  0,
1552  0,
1553  (int)(region->v2d.cur.xmax - restrict_offsets.holdout),
1554  te->ys,
1555  UI_UNIT_X,
1556  UI_UNIT_Y,
1557  &layer_collection_ptr,
1559  -1,
1560  0,
1561  0,
1562  0,
1563  0,
1564  TIP_("Mask out objects in collection from view layer\n"
1565  "* Ctrl to isolate collection\n"
1566  "* Shift to set inside collections"));
1567  UI_but_func_set(bt,
1569  layer_collection,
1570  (char *)"holdout");
1572  if (!props_active.layer_collection_holdout) {
1574  }
1575  }
1576 
1577  if (space_outliner->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
1578  bt = uiDefIconButR_prop(
1579  block,
1581  0,
1582  0,
1583  (int)(region->v2d.cur.xmax - restrict_offsets.indirect_only),
1584  te->ys,
1585  UI_UNIT_X,
1586  UI_UNIT_Y,
1587  &layer_collection_ptr,
1589  -1,
1590  0,
1591  0,
1592  0,
1593  0,
1594  TIP_("Objects in collection only contribute indirectly (through shadows and "
1595  "reflections) in the view layer\n"
1596  "* Ctrl to isolate collection\n"
1597  "* Shift to set inside collections"));
1598  UI_but_func_set(bt,
1600  layer_collection,
1601  (char *)"indirect_only");
1603  if (props_active.layer_collection_holdout ||
1604  !props_active.layer_collection_indirect_only) {
1606  }
1607  }
1608  }
1609 
1610  if (space_outliner->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
1611  bt = uiDefIconButR_prop(block,
1613  0,
1614  0,
1615  (int)(region->v2d.cur.xmax - restrict_offsets.viewport),
1616  te->ys,
1617  UI_UNIT_X,
1618  UI_UNIT_Y,
1619  &collection_ptr,
1621  -1,
1622  0,
1623  0,
1624  0,
1625  0,
1626  TIP_("Globally disable in viewports\n"
1627  "* Ctrl to isolate collection\n"
1628  "* Shift to set inside collections and objects"));
1629  if (layer_collection != nullptr) {
1630  UI_but_func_set(bt,
1632  layer_collection,
1633  (char *)"hide_viewport");
1634  }
1635  else {
1636  UI_but_func_set(bt,
1638  collection,
1639  (char *)"hide_viewport");
1640  }
1642  if (!props_active.collection_hide_viewport) {
1644  }
1645  }
1646 
1647  if (space_outliner->show_restrict_flags & SO_RESTRICT_RENDER) {
1648  bt = uiDefIconButR_prop(block,
1650  0,
1651  0,
1652  (int)(region->v2d.cur.xmax - restrict_offsets.render),
1653  te->ys,
1654  UI_UNIT_X,
1655  UI_UNIT_Y,
1656  &collection_ptr,
1657  props.collection_hide_render,
1658  -1,
1659  0,
1660  0,
1661  0,
1662  0,
1663  TIP_("Globally disable in renders\n"
1664  "* Ctrl to isolate collection\n"
1665  "* Shift to set inside collections and objects"));
1666  if (layer_collection != nullptr) {
1667  UI_but_func_set(bt,
1669  layer_collection,
1670  (char *)"hide_render");
1671  }
1672  else {
1674  bt, scenes__collection_set_flag_recursive_fn, collection, (char *)"hide_render");
1675  }
1677  if (!props_active.collection_hide_render) {
1679  }
1680  }
1681 
1682  if (space_outliner->show_restrict_flags & SO_RESTRICT_SELECT) {
1683  bt = uiDefIconButR_prop(block,
1685  0,
1686  0,
1687  (int)(region->v2d.cur.xmax - restrict_offsets.select),
1688  te->ys,
1689  UI_UNIT_X,
1690  UI_UNIT_Y,
1691  &collection_ptr,
1692  props.collection_hide_select,
1693  -1,
1694  0,
1695  0,
1696  0,
1697  0,
1698  TIP_("Disable selection in viewport\n"
1699  "* Ctrl to isolate collection\n"
1700  "* Shift to set inside collections and objects"));
1701  if (layer_collection != nullptr) {
1702  UI_but_func_set(bt,
1704  layer_collection,
1705  (char *)"hide_select");
1706  }
1707  else {
1709  bt, scenes__collection_set_flag_recursive_fn, collection, (char *)"hide_select");
1710  }
1712  if (!props_active.collection_hide_select) {
1714  }
1715  }
1716  }
1717  }
1718  }
1719  else if (outliner_is_collection_tree_element(te)) {
1720  PointerRNA collection_ptr;
1721  PointerRNA layer_collection_ptr;
1723  scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active);
1724  }
1725 
1726  if (TSELEM_OPEN(tselem, space_outliner)) {
1728  block, scene, view_layer, region, space_outliner, &te->subtree, props_active);
1729  }
1730  }
1731 }
1732 
1733 static void outliner_draw_userbuts(uiBlock *block,
1734  const ARegion *region,
1735  const SpaceOutliner *space_outliner)
1736 {
1737  tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
1738  if (!outliner_is_element_in_view(te, &region->v2d)) {
1739  return;
1740  }
1741 
1742  const TreeStoreElem *tselem = TREESTORE(te);
1743  if (tselem->type != TSE_SOME_ID) {
1744  return;
1745  }
1746 
1747  uiBut *bt;
1748  ID *id = tselem->id;
1749  const char *tip = nullptr;
1750  char buf[16] = "";
1751  int but_flag = UI_BUT_DRAG_LOCK;
1752 
1753  if (ID_IS_LINKED(id)) {
1754  but_flag |= UI_BUT_DISABLED;
1755  }
1756 
1758  bt = uiDefBut(block,
1759  UI_BTYPE_BUT,
1760  1,
1761  buf,
1762  (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
1763  te->ys,
1764  UI_UNIT_X,
1765  UI_UNIT_Y,
1766  nullptr,
1767  0.0,
1768  0.0,
1769  0,
1770  0,
1771  TIP_("Number of users of this data-block"));
1772  UI_but_flag_enable(bt, but_flag);
1773 
1774  if (id->flag & LIB_FAKEUSER) {
1775  tip = TIP_("Data-block will be retained using a fake user");
1776  }
1777  else {
1778  tip = TIP_("Data-block has no users and will be deleted");
1779  }
1780  bt = uiDefIconButBitS(block,
1782  LIB_FAKEUSER,
1783  1,
1784  ICON_FAKE_USER_OFF,
1785  (int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
1786  te->ys,
1787  UI_UNIT_X,
1788  UI_UNIT_Y,
1789  &id->flag,
1790  0,
1791  0,
1792  0,
1793  0,
1794  tip);
1796  UI_but_flag_enable(bt, but_flag);
1797  });
1798 }
1799 
1801  const ARegion *region,
1802  const SpaceOutliner *space_outliner,
1803  const ListBase *lb,
1804  const int x)
1805 {
1806  const float pad_x = 2.0f * UI_DPI_FAC;
1807  const float pad_y = 0.5f * U.pixelsize;
1808  const float item_max_width = round_fl_to_int(OL_RNA_COL_SIZEX - 2 * pad_x);
1809  const float item_height = round_fl_to_int(UI_UNIT_Y - 2.0f * pad_y);
1810 
1811  LISTBASE_FOREACH (const TreeElement *, te, lb) {
1812  const TreeStoreElem *tselem = TREESTORE(te);
1813  if (TSELEM_OPEN(tselem, space_outliner)) {
1814  outliner_draw_overrides_rna_buts(block, region, space_outliner, &te->subtree, x);
1815  }
1816 
1817  if (!outliner_is_element_in_view(te, &region->v2d)) {
1818  continue;
1819  }
1820  TreeElementOverridesProperty *override_elem = tree_element_cast<TreeElementOverridesProperty>(
1821  te);
1822  if (!override_elem) {
1823  continue;
1824  }
1825 
1826  if (!override_elem->is_rna_path_valid) {
1827  uiBut *but = uiDefBut(block,
1829  0,
1830  override_elem->rna_path.c_str(),
1831  x + pad_x,
1832  te->ys + pad_y,
1833  item_max_width,
1834  item_height,
1835  nullptr,
1836  0.0f,
1837  0.0f,
1838  0.0f,
1839  0.0f,
1840  "");
1842  continue;
1843  }
1844 
1845  if (const TreeElementOverridesPropertyOperation *override_op_elem =
1846  tree_element_cast<TreeElementOverridesPropertyOperation>(te)) {
1847  StringRefNull op_label = override_op_elem->getOverrideOperationLabel();
1848  uiDefBut(block,
1850  0,
1851  op_label.c_str(),
1852  x + pad_x,
1853  te->ys + pad_y,
1854  item_max_width,
1855  item_height,
1856  nullptr,
1857  0,
1858  0,
1859  0,
1860  0,
1861  "");
1862  continue;
1863  }
1864 
1865  PointerRNA *ptr = &override_elem->override_rna_ptr;
1866  PropertyRNA *prop = &override_elem->override_rna_prop;
1867  const PropertyType prop_type = RNA_property_type(prop);
1868 
1869  uiBut *auto_but = uiDefAutoButR(block,
1870  ptr,
1871  prop,
1872  -1,
1873  (prop_type == PROP_ENUM) ? nullptr : "",
1874  ICON_NONE,
1875  x + pad_x,
1876  te->ys + pad_y,
1877  item_max_width,
1878  item_height);
1879  /* Added the button successfully, nothing else to do. Otherwise, cases for multiple buttons
1880  * need to be handled. */
1881  if (auto_but) {
1882  continue;
1883  }
1884 
1885  if (!auto_but) {
1886  /* TODO what if the array is longer, and doesn't fit nicely? What about multi-dimension
1887  * arrays? */
1889  block, ptr, prop, ICON_NONE, x + pad_x, te->ys + pad_y, item_max_width, item_height);
1890  }
1891  }
1892 }
1893 
1895 {
1896  const PointerRNA *idptr_a = UI_but_context_ptr_get(a, "id", &RNA_ID);
1897  const PointerRNA *idptr_b = UI_but_context_ptr_get(b, "id", &RNA_ID);
1898  if (!idptr_a || !idptr_b) {
1899  return false;
1900  }
1901  const ID *id_a = (const ID *)idptr_a->data;
1902  const ID *id_b = (const ID *)idptr_b->data;
1903 
1904  /* Using session UUID to compare is safer than using the pointer. */
1905  return id_a->session_uuid == id_b->session_uuid;
1906 }
1907 
1909  uiBlock *block,
1910  const ARegion *region,
1911  const SpaceOutliner *space_outliner,
1912  const ListBase *lb,
1913  const int x)
1914 {
1915  LISTBASE_FOREACH (const TreeElement *, te, lb) {
1916  const TreeStoreElem *tselem = TREESTORE(te);
1917  if (TSELEM_OPEN(tselem, space_outliner)) {
1918  outliner_draw_overrides_restrictbuts(bmain, block, region, space_outliner, &te->subtree, x);
1919  }
1920 
1921  if (!outliner_is_element_in_view(te, &region->v2d)) {
1922  continue;
1923  }
1924  TreeElementID *te_id = tree_element_cast<TreeElementID>(te);
1925  if (!te_id) {
1926  continue;
1927  }
1928 
1929  ID &id = te_id->get_ID();
1931 
1932  if (ID_IS_LINKED(&id)) {
1933  continue;
1934  }
1935 
1936  const bool is_system_override = BKE_lib_override_library_is_system_defined(bmain, &id);
1937  const BIFIconID icon = is_system_override ? ICON_LIBRARY_DATA_OVERRIDE_NONEDITABLE :
1938  ICON_LIBRARY_DATA_OVERRIDE;
1939  uiBut *but = uiDefIconButO(block,
1940  UI_BTYPE_BUT,
1941  "ED_OT_lib_id_override_editable_toggle",
1943  icon,
1944  x,
1945  te->ys,
1946  UI_UNIT_X,
1947  UI_UNIT_Y,
1948  "");
1949  PointerRNA idptr;
1950  RNA_id_pointer_create(&id, &idptr);
1951  UI_but_context_ptr_set(block, but, "id", &idptr);
1954  }
1955 }
1956 
1957 static void outliner_draw_separator(ARegion *region, const int x)
1958 {
1959  View2D *v2d = &region->v2d;
1960 
1961  GPU_line_width(1.0f);
1962 
1966 
1968 
1969  immVertex2f(pos, x, v2d->cur.ymax);
1970  immVertex2f(pos, x, v2d->cur.ymin);
1971 
1972  immEnd();
1973 
1974  immUnbindProgram();
1975 }
1976 
1977 static void outliner_draw_rnabuts(uiBlock *block,
1978  ARegion *region,
1979  SpaceOutliner *space_outliner,
1980  int sizex)
1981 {
1982  PointerRNA ptr;
1983  PropertyRNA *prop;
1984 
1985  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
1986  TreeStoreElem *tselem = TREESTORE(te);
1987 
1988  if (!outliner_is_element_in_view(te, &region->v2d)) {
1989  return;
1990  }
1991 
1992  if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) {
1993  ptr = te_rna_prop->getPointerRNA();
1994  prop = te_rna_prop->getPropertyRNA();
1995 
1996  if (!TSELEM_OPEN(tselem, space_outliner)) {
1997  if (RNA_property_type(prop) == PROP_POINTER) {
1998  uiBut *but = uiDefAutoButR(block,
1999  &ptr,
2000  prop,
2001  -1,
2002  "",
2003  ICON_NONE,
2004  sizex,
2005  te->ys,
2007  UI_UNIT_Y - 1);
2009  }
2010  else if (RNA_property_type(prop) == PROP_ENUM) {
2011  uiDefAutoButR(block,
2012  &ptr,
2013  prop,
2014  -1,
2015  nullptr,
2016  ICON_NONE,
2017  sizex,
2018  te->ys,
2020  UI_UNIT_Y - 1);
2021  }
2022  else {
2023  uiDefAutoButR(block,
2024  &ptr,
2025  prop,
2026  -1,
2027  "",
2028  ICON_NONE,
2029  sizex,
2030  te->ys,
2032  UI_UNIT_Y - 1);
2033  }
2034  }
2035  }
2036  else if (TreeElementRNAArrayElement *te_rna_array_elem =
2037  tree_element_cast<TreeElementRNAArrayElement>(te)) {
2038  ptr = te_rna_array_elem->getPointerRNA();
2039  prop = te_rna_array_elem->getPropertyRNA();
2040 
2041  uiDefAutoButR(block,
2042  &ptr,
2043  prop,
2044  te->index,
2045  "",
2046  ICON_NONE,
2047  sizex,
2048  te->ys,
2050  UI_UNIT_Y - 1);
2051  }
2052  });
2053 }
2054 
2055 static void outliner_buttons(const bContext *C,
2056  uiBlock *block,
2057  ARegion *region,
2058  const float restrict_column_width,
2059  TreeElement *te)
2060 {
2061  uiBut *bt;
2062  TreeStoreElem *tselem;
2063  int spx, dx, len;
2064 
2065  tselem = TREESTORE(te);
2066 
2067  BLI_assert(tselem->flag & TSE_TEXTBUT);
2068  /* If we add support to rename Sequence, need change this. */
2069 
2070  if (tselem->type == TSE_EBONE) {
2071  len = sizeof(((EditBone *)nullptr)->name);
2072  }
2073  else if (tselem->type == TSE_MODIFIER) {
2074  len = sizeof(((ModifierData *)nullptr)->name);
2075  }
2076  else if (tselem->id && GS(tselem->id->name) == ID_LI) {
2077  len = sizeof(((Library *)nullptr)->filepath);
2078  }
2079  else {
2080  len = MAX_ID_NAME - 2;
2081  }
2082 
2083  spx = te->xs + 1.8f * UI_UNIT_X;
2084  dx = region->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
2085 
2086  bt = uiDefBut(block,
2087  UI_BTYPE_TEXT,
2088  OL_NAMEBUTTON,
2089  "",
2090  spx,
2091  te->ys,
2092  dx,
2093  UI_UNIT_Y - 1,
2094  (void *)te->name,
2095  1.0,
2096  (float)len,
2097  0,
2098  0,
2099  "");
2101 
2102  /* Returns false if button got removed. */
2103  if (false == UI_but_active_only(C, region, block, bt)) {
2104  tselem->flag &= ~TSE_TEXTBUT;
2105 
2106  /* Bad! (notifier within draw) without this, we don't get a refresh. */
2108  }
2109 }
2110 
2111 static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED(arg2))
2112 {
2113  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2114  TreeStoreElem *tselem = (TreeStoreElem *)tselem_poin;
2115  TreeViewContext tvc;
2117 
2118  TreeElement *te = outliner_find_tree_element(&space_outliner->tree, tselem);
2119  if (!te) {
2120  return;
2121  }
2122 
2123  /* Check that the item is actually an object. */
2124  BLI_assert(tselem->id != nullptr && GS(tselem->id->name) == ID_OB);
2125 
2126  Object *ob = (Object *)tselem->id;
2127  const bool object_data_shared = (ob->data == tvc.obact->data);
2128 
2129  wmWindow *win = CTX_wm_window(C);
2130  const bool do_extend = (win->eventstate->modifier & KM_CTRL) && !object_data_shared;
2131  outliner_item_mode_toggle(C, &tvc, te, do_extend);
2132 }
2133 
2134 /* Draw icons for adding and removing objects from the current interaction mode. */
2136  TreeViewContext *tvc,
2137  TreeElement *te,
2138  const bool lock_object_modes)
2139 {
2140  TreeStoreElem *tselem = TREESTORE(te);
2141  if ((tselem->type != TSE_SOME_ID) || (te->idcode != ID_OB)) {
2142  return;
2143  }
2144 
2145  Object *ob = (Object *)tselem->id;
2146  Object *ob_active = tvc->obact;
2147 
2148  /* Not all objects support particle systems. */
2149  if (ob_active->mode == OB_MODE_PARTICLE_EDIT && !psys_get_current(ob)) {
2150  return;
2151  }
2152 
2153  /* Only for objects with the same type. */
2154  if (ob->type != ob_active->type) {
2155  return;
2156  }
2157 
2158  bool draw_active_icon = ob->mode == ob_active->mode;
2159 
2160  /* When not locking object modes, objects can remain in non-object modes. For modes that do not
2161  * allow multi-object editing, these other objects should still show be viewed as not in the
2162  * mode. Otherwise multiple objects show the same mode icon in the outliner even though only
2163  * one object is actually editable in the mode. */
2164  if (!lock_object_modes && ob != ob_active && !(tvc->ob_edit || tvc->ob_pose)) {
2165  draw_active_icon = false;
2166  }
2167 
2168  const bool object_data_shared = (ob->data == ob_active->data);
2169  draw_active_icon = draw_active_icon || object_data_shared;
2170 
2171  int icon;
2172  const char *tip;
2173  if (draw_active_icon) {
2174  icon = UI_icon_from_object_mode(ob_active->mode);
2175  tip = object_data_shared ? TIP_("Change the object in the current mode") :
2176  TIP_("Remove from the current mode");
2177  }
2178  else {
2179  icon = ICON_DOT;
2180  tip = TIP_(
2181  "Change the object in the current mode\n"
2182  "* Ctrl to add to the current mode");
2183  }
2185  uiBut *but = uiDefIconBut(block,
2187  0,
2188  icon,
2189  0,
2190  te->ys,
2191  UI_UNIT_X,
2192  UI_UNIT_Y,
2193  nullptr,
2194  0.0,
2195  0.0,
2196  0.0,
2197  0.0,
2198  tip);
2199  UI_but_func_set(but, outliner_mode_toggle_fn, tselem, nullptr);
2201  /* Mode toggling handles its own undo state because undo steps need to be grouped. */
2203 
2204  if (ID_IS_LINKED(&ob->id) ||
2207  UI_but_disable(but, TIP_("Can't edit library or non-editable override data"));
2208  }
2209 }
2210 
2212  TreeViewContext *tvc,
2213  SpaceOutliner *space_outliner)
2214 {
2215  const bool lock_object_modes = tvc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK;
2216 
2217  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
2218  if (tvc->obact && tvc->obact->mode != OB_MODE_OBJECT) {
2219  outliner_draw_mode_column_toggle(block, tvc, te, lock_object_modes);
2220  }
2221  });
2222 }
2223 
2225 {
2226  LISTBASE_FOREACH (const TreeElement *, sub_te, &parent_te->subtree) {
2227  const AbstractTreeElement *abstract_te = tree_element_cast<AbstractTreeElement>(sub_te);
2228  StringRefNull warning_msg = abstract_te ? abstract_te->getWarning() : "";
2229 
2230  if (!warning_msg.is_empty()) {
2231  return warning_msg;
2232  }
2233 
2234  warning_msg = outliner_draw_get_warning_tree_element_subtree(sub_te);
2235  if (!warning_msg.is_empty()) {
2236  return warning_msg;
2237  }
2238  }
2239 
2240  return "";
2241 }
2242 
2244  const TreeElement *te)
2245 {
2246  const AbstractTreeElement *abstract_te = tree_element_cast<AbstractTreeElement>(te);
2247  const StringRefNull warning_msg = abstract_te ? abstract_te->getWarning() : "";
2248 
2249  if (!warning_msg.is_empty()) {
2250  return warning_msg;
2251  }
2252 
2253  /* If given element has no warning, recursively try to display the first sub-element's warning.
2254  */
2255  if (!TSELEM_OPEN(te->store_elem, &space_outliner)) {
2257  }
2258 
2259  return "";
2260 }
2261 
2263  const SpaceOutliner *space_outliner,
2264  StringRefNull warning_msg,
2265  const bool use_mode_column,
2266  const int te_ys)
2267 {
2268  /* Move the warnings a unit left in view layer mode. */
2269  const short mode_column_offset = (use_mode_column && (space_outliner->outlinevis == SO_SCENES)) ?
2270  UI_UNIT_X :
2271  0;
2272 
2274  uiBut *but = uiDefIconBut(block,
2276  0,
2277  ICON_ERROR,
2278  mode_column_offset,
2279  te_ys,
2280  UI_UNIT_X,
2281  UI_UNIT_Y,
2282  nullptr,
2283  0.0,
2284  0.0,
2285  0.0,
2286  0.0,
2287  warning_msg.c_str());
2288  /* No need for undo here, this is a pure info widget. */
2290 }
2291 
2293  const SpaceOutliner *space_outliner,
2294  const bool use_mode_column)
2295 {
2296  tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
2297  /* Get warning for this element, or if there is none and the element is collapsed, the first
2298  * warning in the collapsed sub-tree. */
2299  StringRefNull warning_msg = outliner_draw_get_warning_tree_element(*space_outliner, te);
2300 
2301  if (!warning_msg.is_empty()) {
2303  block, space_outliner, warning_msg, use_mode_column, te->ys);
2304  }
2305  });
2306 }
2307 
2310 /* -------------------------------------------------------------------- */
2315 {
2316  if (GS(id->name) == ID_OB) {
2317  const Object *ob = (Object *)id;
2318  switch (ob->type) {
2319  case OB_LAMP:
2320  return ICON_OUTLINER_OB_LIGHT;
2321  case OB_MESH:
2322  return ICON_OUTLINER_OB_MESH;
2323  case OB_CAMERA:
2324  return ICON_OUTLINER_OB_CAMERA;
2325  case OB_CURVES_LEGACY:
2326  return ICON_OUTLINER_OB_CURVE;
2327  case OB_MBALL:
2328  return ICON_OUTLINER_OB_META;
2329  case OB_LATTICE:
2330  return ICON_OUTLINER_OB_LATTICE;
2331  case OB_ARMATURE:
2332  return ICON_OUTLINER_OB_ARMATURE;
2333  case OB_FONT:
2334  return ICON_OUTLINER_OB_FONT;
2335  case OB_SURF:
2336  return ICON_OUTLINER_OB_SURFACE;
2337  case OB_SPEAKER:
2338  return ICON_OUTLINER_OB_SPEAKER;
2339  case OB_LIGHTPROBE:
2340  return ICON_OUTLINER_OB_LIGHTPROBE;
2341  case OB_CURVES:
2342  return ICON_OUTLINER_OB_CURVES;
2343  case OB_POINTCLOUD:
2344  return ICON_OUTLINER_OB_POINTCLOUD;
2345  case OB_VOLUME:
2346  return ICON_OUTLINER_OB_VOLUME;
2347  case OB_EMPTY:
2348  if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
2349  return ICON_OUTLINER_OB_GROUP_INSTANCE;
2350  }
2351  else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
2352  return ICON_OUTLINER_OB_IMAGE;
2353  }
2354  else if (ob->pd && ob->pd->forcefield) {
2355  return ICON_OUTLINER_OB_FORCE_FIELD;
2356  }
2357  else {
2358  return ICON_OUTLINER_OB_EMPTY;
2359  }
2360  case OB_GPENCIL:
2361  return ICON_OUTLINER_OB_GREASEPENCIL;
2362  }
2363 
2364  return ICON_NONE;
2365  }
2366 
2367  /* TODO(sergey): Casting to short here just to handle ID_NLA which is
2368  * NOT inside of IDType enum.
2369  */
2370  switch ((short)GS(id->name)) {
2371  case ID_SCE:
2372  return ICON_SCENE_DATA;
2373  case ID_ME:
2374  return ICON_OUTLINER_DATA_MESH;
2375  case ID_CU_LEGACY: {
2376  const Curve *cu = (Curve *)id;
2377  const short obtype = BKE_curve_type_get(cu);
2378 
2379  switch (obtype) {
2380  case OB_FONT:
2381  return ICON_OUTLINER_DATA_FONT;
2382  case OB_SURF:
2383  return ICON_OUTLINER_DATA_SURFACE;
2384  default:
2385  return ICON_OUTLINER_DATA_CURVE;
2386  }
2387  break;
2388  }
2389  case ID_MB:
2390  return ICON_OUTLINER_DATA_META;
2391  case ID_LT:
2392  return ICON_OUTLINER_DATA_LATTICE;
2393  case ID_LA: {
2394  const Light *la = (Light *)id;
2395  switch (la->type) {
2396  case LA_LOCAL:
2397  return ICON_LIGHT_POINT;
2398  case LA_SUN:
2399  return ICON_LIGHT_SUN;
2400  case LA_SPOT:
2401  return ICON_LIGHT_SPOT;
2402  case LA_AREA:
2403  return ICON_LIGHT_AREA;
2404  default:
2405  return ICON_OUTLINER_DATA_LIGHT;
2406  }
2407  }
2408  case ID_MA:
2409  return ICON_MATERIAL_DATA;
2410  case ID_TE:
2411  return ICON_TEXTURE_DATA;
2412  case ID_IM:
2413  return ICON_IMAGE_DATA;
2414  case ID_SPK:
2415  case ID_SO:
2416  return ICON_OUTLINER_DATA_SPEAKER;
2417  case ID_AR:
2418  return ICON_OUTLINER_DATA_ARMATURE;
2419  case ID_CA:
2420  return ICON_OUTLINER_DATA_CAMERA;
2421  case ID_KE:
2422  return ICON_SHAPEKEY_DATA;
2423  case ID_WO:
2424  return ICON_WORLD_DATA;
2425  case ID_AC:
2426  return ICON_ACTION;
2427  case ID_NLA:
2428  return ICON_NLA;
2429  case ID_TXT: {
2430  const Text *text = (Text *)id;
2431  if (text->filepath == nullptr || (text->flags & TXT_ISMEM)) {
2432  return ICON_FILE_TEXT;
2433  }
2434  /* Helps distinguish text-based formats like the file-browser does. */
2435  return (BIFIconID)ED_file_extension_icon(text->filepath);
2436  }
2437  case ID_GR:
2438  return ICON_OUTLINER_COLLECTION;
2439  case ID_CV:
2440  return ICON_OUTLINER_DATA_CURVES;
2441  case ID_PT:
2442  return ICON_OUTLINER_DATA_POINTCLOUD;
2443  case ID_VO:
2444  return ICON_OUTLINER_DATA_VOLUME;
2445  case ID_LI:
2446  if (id->tag & LIB_TAG_MISSING) {
2447  return ICON_LIBRARY_DATA_BROKEN;
2448  }
2449  else if (((Library *)id)->parent) {
2450  return ICON_LIBRARY_DATA_INDIRECT;
2451  }
2452  else {
2453  return ICON_LIBRARY_DATA_DIRECT;
2454  }
2455  case ID_LS:
2456  return ICON_LINE_DATA;
2457  case ID_GD:
2458  return ICON_OUTLINER_DATA_GREASEPENCIL;
2459  case ID_LP: {
2460  const LightProbe *lp = (LightProbe *)id;
2461  switch (lp->type) {
2462  case LIGHTPROBE_TYPE_CUBE:
2463  return ICON_LIGHTPROBE_CUBEMAP;
2465  return ICON_LIGHTPROBE_PLANAR;
2466  case LIGHTPROBE_TYPE_GRID:
2467  return ICON_LIGHTPROBE_GRID;
2468  default:
2469  return ICON_LIGHTPROBE_CUBEMAP;
2470  }
2471  }
2472  case ID_BR:
2473  return ICON_BRUSH_DATA;
2474  case ID_SCR:
2475  case ID_WS:
2476  return ICON_WORKSPACE;
2477  case ID_MSK:
2478  return ICON_MOD_MASK;
2479  case ID_NT: {
2480  const bNodeTree *ntree = (bNodeTree *)id;
2481  const bNodeTreeType *ntreetype = ntree->typeinfo;
2482  return (BIFIconID)ntreetype->ui_icon;
2483  }
2484  case ID_MC:
2485  return ICON_SEQUENCE;
2486  case ID_PC:
2487  return ICON_CURVE_BEZCURVE;
2488  case ID_SIM:
2489  /* TODO: Use correct icon. */
2490  return ICON_PHYSICS;
2491  default:
2492  return ICON_NONE;
2493  }
2494 }
2495 
2497 {
2498  TreeElementIcon data = {nullptr};
2499 
2500  if (tselem->type != TSE_SOME_ID) {
2501  switch (tselem->type) {
2502  case TSE_ANIM_DATA:
2503  data.icon = ICON_ANIM_DATA; /* XXX */
2504  break;
2505  case TSE_NLA:
2506  data.icon = ICON_NLA;
2507  break;
2508  case TSE_NLA_TRACK:
2509  data.icon = ICON_NLA; /* XXX */
2510  break;
2511  case TSE_NLA_ACTION:
2512  data.icon = ICON_ACTION;
2513  break;
2514  case TSE_DRIVER_BASE:
2515  data.icon = ICON_DRIVER;
2516  break;
2517  case TSE_DEFGROUP_BASE:
2518  data.icon = ICON_GROUP_VERTEX;
2519  break;
2520  case TSE_DEFGROUP:
2521  data.icon = ICON_GROUP_VERTEX;
2522  break;
2523  case TSE_BONE:
2524  case TSE_EBONE:
2525  data.icon = ICON_BONE_DATA;
2526  break;
2527  case TSE_CONSTRAINT_BASE:
2528  data.icon = ICON_CONSTRAINT;
2529  data.drag_id = tselem->id;
2530  break;
2531  case TSE_CONSTRAINT: {
2532  bConstraint *con = reinterpret_cast<bConstraint *>(te->directdata);
2533  data.drag_id = tselem->id;
2534  switch ((eBConstraint_Types)con->type) {
2536  data.icon = ICON_CON_CAMERASOLVER;
2537  break;
2539  data.icon = ICON_CON_FOLLOWTRACK;
2540  break;
2542  data.icon = ICON_CON_OBJECTSOLVER;
2543  break;
2545  data.icon = ICON_CON_LOCLIKE;
2546  break;
2548  data.icon = ICON_CON_ROTLIKE;
2549  break;
2551  data.icon = ICON_CON_SIZELIKE;
2552  break;
2554  data.icon = ICON_CON_TRANSLIKE;
2555  break;
2557  data.icon = ICON_CON_DISTLIMIT;
2558  break;
2560  data.icon = ICON_CON_LOCLIMIT;
2561  break;
2563  data.icon = ICON_CON_ROTLIMIT;
2564  break;
2566  data.icon = ICON_CON_SIZELIMIT;
2567  break;
2569  data.icon = ICON_CON_SAMEVOL;
2570  break;
2572  data.icon = ICON_CON_TRANSFORM;
2573  break;
2575  data.icon = ICON_CON_TRANSFORM_CACHE;
2576  break;
2578  data.icon = ICON_CON_CLAMPTO;
2579  break;
2581  data.icon = ICON_CON_TRACKTO;
2582  break;
2584  data.icon = ICON_CON_KINEMATIC;
2585  break;
2587  data.icon = ICON_CON_LOCKTRACK;
2588  break;
2590  data.icon = ICON_CON_SPLINEIK;
2591  break;
2593  data.icon = ICON_CON_STRETCHTO;
2594  break;
2596  data.icon = ICON_CON_TRACKTO;
2597  break;
2599  data.icon = ICON_CON_ACTION;
2600  break;
2602  data.icon = ICON_CON_ARMATURE;
2603  break;
2605  data.icon = ICON_CON_CHILDOF;
2606  break;
2608  data.icon = ICON_CON_FLOOR;
2609  break;
2611  data.icon = ICON_CON_FOLLOWPATH;
2612  break;
2613  case CONSTRAINT_TYPE_PIVOT:
2614  data.icon = ICON_CON_PIVOT;
2615  break;
2617  data.icon = ICON_CON_SHRINKWRAP;
2618  break;
2619 
2620  default:
2621  data.icon = ICON_DOT;
2622  break;
2623  }
2624  break;
2625  }
2626  case TSE_MODIFIER_BASE:
2627  data.icon = ICON_MODIFIER_DATA;
2628  data.drag_id = tselem->id;
2629  break;
2631  TreeElementOverridesBase *base_te = tree_element_cast<TreeElementOverridesBase>(te);
2632  data.icon = tree_element_get_icon_from_id(&base_te->id);
2633  break;
2634  }
2635  case TSE_LIBRARY_OVERRIDE:
2636  data.icon = ICON_LIBRARY_DATA_OVERRIDE;
2637  break;
2638  case TSE_LINKED_OB:
2639  data.icon = ICON_OBJECT_DATA;
2640  break;
2641  case TSE_LINKED_PSYS:
2642  data.icon = ICON_PARTICLES;
2643  break;
2644  case TSE_MODIFIER: {
2645  Object *ob = (Object *)tselem->id;
2646  data.drag_id = tselem->id;
2647 
2648  if (ob->type != OB_GPENCIL) {
2649  ModifierData *md = reinterpret_cast<ModifierData *>(
2650  BLI_findlink(&ob->modifiers, tselem->nr));
2651  const ModifierTypeInfo *modifier_type = reinterpret_cast<const ModifierTypeInfo *>(
2653  if (modifier_type != nullptr) {
2654  data.icon = modifier_type->icon;
2655  }
2656  else {
2657  data.icon = ICON_DOT;
2658  }
2659  }
2660  else {
2661  /* grease pencil modifiers */
2662  GpencilModifierData *md = reinterpret_cast<GpencilModifierData *>(
2663  BLI_findlink(&ob->greasepencil_modifiers, tselem->nr));
2664  switch ((GpencilModifierType)md->type) {
2666  data.icon = ICON_MOD_NOISE;
2667  break;
2669  data.icon = ICON_MOD_SUBSURF;
2670  break;
2672  data.icon = ICON_MOD_THICKNESS;
2673  break;
2675  data.icon = ICON_MOD_TINT;
2676  break;
2678  data.icon = ICON_MOD_ARRAY;
2679  break;
2681  data.icon = ICON_MOD_BUILD;
2682  break;
2684  data.icon = ICON_MOD_MASK;
2685  break;
2687  data.icon = ICON_MOD_HUE_SATURATION;
2688  break;
2690  data.icon = ICON_MOD_LATTICE;
2691  break;
2693  data.icon = ICON_MOD_MIRROR;
2694  break;
2696  data.icon = ICON_MOD_SIMPLIFY;
2697  break;
2699  data.icon = ICON_MOD_SMOOTH;
2700  break;
2702  data.icon = ICON_HOOK;
2703  break;
2705  data.icon = ICON_MOD_OFFSET;
2706  break;
2708  data.icon = ICON_MOD_ARMATURE;
2709  break;
2711  data.icon = ICON_GP_MULTIFRAME_EDITING;
2712  break;
2714  data.icon = ICON_MOD_TIME;
2715  break;
2717  data.icon = ICON_TEXTURE;
2718  break;
2720  data.icon = ICON_MOD_VERTEX_WEIGHT;
2721  break;
2723  data.icon = ICON_MOD_VERTEX_WEIGHT;
2724  break;
2726  data.icon = ICON_MOD_SHRINKWRAP;
2727  break;
2728 
2729  /* Default */
2730  default:
2731  data.icon = ICON_DOT;
2732  break;
2733  }
2734  }
2735  break;
2736  }
2737  case TSE_POSE_BASE:
2738  data.icon = ICON_ARMATURE_DATA;
2739  break;
2740  case TSE_POSE_CHANNEL:
2741  data.icon = ICON_BONE_DATA;
2742  break;
2743  case TSE_R_LAYER_BASE:
2744  data.icon = ICON_RENDERLAYERS;
2745  break;
2747  data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
2748  break;
2749  case TSE_R_LAYER:
2750  data.icon = ICON_RENDER_RESULT;
2751  break;
2752  case TSE_POSEGRP_BASE:
2753  case TSE_POSEGRP:
2754  data.icon = ICON_GROUP_BONE;
2755  break;
2756  case TSE_SEQUENCE:
2757  switch (te->idcode) {
2758  case SEQ_TYPE_SCENE:
2759  data.icon = ICON_SCENE_DATA;
2760  break;
2761  case SEQ_TYPE_MOVIECLIP:
2762  data.icon = ICON_TRACKER;
2763  break;
2764  case SEQ_TYPE_MASK:
2765  data.icon = ICON_MOD_MASK;
2766  break;
2767  case SEQ_TYPE_MOVIE:
2768  data.icon = ICON_FILE_MOVIE;
2769  break;
2770  case SEQ_TYPE_SOUND_RAM:
2771  data.icon = ICON_SOUND;
2772  break;
2773  case SEQ_TYPE_IMAGE:
2774  data.icon = ICON_FILE_IMAGE;
2775  break;
2776  case SEQ_TYPE_COLOR:
2777  case SEQ_TYPE_ADJUSTMENT:
2778  data.icon = ICON_COLOR;
2779  break;
2780  case SEQ_TYPE_TEXT:
2781  data.icon = ICON_FONT_DATA;
2782  break;
2783  case SEQ_TYPE_ADD:
2784  case SEQ_TYPE_SUB:
2785  case SEQ_TYPE_MUL:
2786  case SEQ_TYPE_OVERDROP:
2787  case SEQ_TYPE_ALPHAOVER:
2788  case SEQ_TYPE_ALPHAUNDER:
2789  case SEQ_TYPE_COLORMIX:
2790  case SEQ_TYPE_MULTICAM:
2791  case SEQ_TYPE_TRANSFORM:
2792  case SEQ_TYPE_SPEED:
2793  case SEQ_TYPE_GLOW:
2795  data.icon = ICON_SHADERFX;
2796  break;
2797  case SEQ_TYPE_CROSS:
2798  case SEQ_TYPE_GAMCROSS:
2799  case SEQ_TYPE_WIPE:
2800  data.icon = ICON_ARROW_LEFTRIGHT;
2801  break;
2802  case SEQ_TYPE_META:
2803  data.icon = ICON_SEQ_STRIP_META;
2804  break;
2805  default:
2806  data.icon = ICON_DOT;
2807  break;
2808  }
2809  break;
2810  case TSE_SEQ_STRIP:
2811  data.icon = ICON_LIBRARY_DATA_DIRECT;
2812  break;
2813  case TSE_SEQUENCE_DUP:
2814  data.icon = ICON_SEQ_STRIP_DUPLICATE;
2815  break;
2816  case TSE_RNA_STRUCT: {
2817  const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te);
2818  const PointerRNA &ptr = te_rna_struct->getPointerRNA();
2819 
2820  if (RNA_struct_is_ID(ptr.type)) {
2821  data.drag_id = reinterpret_cast<ID *>(ptr.data);
2822  data.icon = RNA_struct_ui_icon(ptr.type);
2823  }
2824  else {
2825  data.icon = RNA_struct_ui_icon(ptr.type);
2826  }
2827  break;
2828  }
2829  case TSE_LAYER_COLLECTION:
2831  case TSE_VIEW_COLLECTION_BASE: {
2833  if (collection && !(collection->flag & COLLECTION_IS_MASTER)) {
2834  data.drag_id = tselem->id;
2835  data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : nullptr;
2836  }
2837 
2838  data.icon = ICON_OUTLINER_COLLECTION;
2839  break;
2840  }
2841  case TSE_GP_LAYER: {
2842  data.icon = ICON_OUTLINER_DATA_GP_LAYER;
2843  break;
2844  }
2846  case TSE_GPENCIL_EFFECT:
2847  data.drag_id = tselem->id;
2848  data.icon = ICON_SHADERFX;
2849  break;
2850  default:
2851  data.icon = ICON_DOT;
2852  break;
2853  }
2854  }
2855  else if (tselem->id) {
2856  data.drag_id = tselem->id;
2857  data.drag_parent = (data.drag_id && te->parent) ? TREESTORE(te->parent)->id : nullptr;
2858  data.icon = tree_element_get_icon_from_id(tselem->id);
2859  }
2860 
2861  if (!te->abstract_element) {
2862  /* Pass */
2863  }
2864  else if (auto icon = te->abstract_element->getIcon()) {
2865  data.icon = *icon;
2866  }
2867 
2868  return data;
2869 }
2870 
2874 static bool tselem_draw_icon(uiBlock *block,
2875  int xmax,
2876  float x,
2877  float y,
2878  TreeStoreElem *tselem,
2879  TreeElement *te,
2880  float alpha,
2881  const bool is_clickable)
2882 {
2884  if (data.icon == 0) {
2885  return false;
2886  }
2887 
2888  const bool is_collection = outliner_is_collection_tree_element(te);
2889 
2890  /* Collection colors and icons covered by restrict buttons. */
2891  if (!is_clickable || x >= xmax || is_collection) {
2892  /* Placement of icons, copied from interface_widgets.c */
2893  float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
2894  x += 2.0f * aspect;
2895  y += 2.0f * aspect;
2896 
2897  if (is_collection) {
2899  if (collection->color_tag != COLLECTION_COLOR_NONE) {
2900  bTheme *btheme = UI_GetTheme();
2902  y,
2903  data.icon,
2904  U.inv_dpi_fac,
2905  alpha,
2906  0.0f,
2907  btheme->collection_color[collection->color_tag].color,
2908  true);
2909  return true;
2910  }
2911  }
2912 
2913  /* Reduce alpha to match icon buttons */
2914  alpha *= 0.8f;
2915 
2916  /* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */
2917  uchar color[4];
2918  if (UI_icon_get_theme_color(data.icon, color)) {
2919  UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
2920  }
2921  else {
2922  UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false);
2923  }
2924  }
2925  else {
2926  uiDefIconBut(block,
2928  0,
2929  data.icon,
2930  x,
2931  y,
2932  UI_UNIT_X,
2933  UI_UNIT_Y,
2934  nullptr,
2935  0.0,
2936  0.0,
2937  1.0,
2938  alpha,
2939  (data.drag_id && ID_IS_LINKED(data.drag_id)) ? data.drag_id->lib->filepath : "");
2940  }
2941 
2942  return true;
2943 }
2944 
2949 static void outliner_draw_iconrow_number(const uiFontStyle *fstyle,
2950  int offsx,
2951  int ys,
2952  const int num_elements)
2953 {
2954  const float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
2955  float ufac = 0.25f * UI_UNIT_X;
2956  float offset_x = (float)offsx + UI_UNIT_X * 0.35f;
2957  rctf rect{};
2958  BLI_rctf_init(&rect,
2959  offset_x + ufac,
2960  offset_x + UI_UNIT_X - ufac,
2961  (float)ys - UI_UNIT_Y * 0.2f + ufac,
2962  (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac);
2963 
2965  UI_draw_roundbox_aa(&rect, true, (float)UI_UNIT_Y / 2.0f - ufac, color);
2966 
2967  /* Now the numbers. */
2968  uchar text_col[4];
2969 
2970  UI_GetThemeColor3ubv(TH_TEXT_HI, text_col);
2971  text_col[3] = 255;
2972 
2973  uiFontStyle fstyle_small = *fstyle;
2974  fstyle_small.points *= 0.8f;
2975 
2976  /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
2977  int num_digits = 4;
2978  char number_text[4] = "+99";
2979  if (num_elements < 100) {
2980  BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
2981  num_digits = num_elements < 10 ? 1 : 2;
2982  }
2983  UI_fontstyle_draw_simple(&fstyle_small,
2984  (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
2985  (float)ys - UI_UNIT_Y * 0.095f + ufac,
2986  number_text,
2987  text_col);
2988  UI_fontstyle_set(fstyle);
2989  GPU_blend(GPU_BLEND_ALPHA); /* Roundbox and text drawing disables. */
2990 }
2991 
2992 static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
2993 {
2994  float text[4];
2996 
2997  copy_v3_v3(icon_color, text);
2998  icon_color[3] = 0.4f;
2999  copy_v3_v3(icon_border, text);
3000  icon_border[3] = 0.2f;
3001 }
3002 
3003 /* Draw a rounded rectangle behind icons of active elements. */
3004 static void outliner_draw_active_indicator(const float minx,
3005  const float miny,
3006  const float maxx,
3007  const float maxy,
3008  const float icon_color[4],
3009  const float icon_border[4])
3010 {
3011  const float ufac = UI_UNIT_X / 20.0f;
3012  const float radius = UI_UNIT_Y / 4.0f;
3013  rctf rect{};
3014  BLI_rctf_init(&rect, minx, maxx, miny + ufac, maxy - ufac);
3015 
3017  UI_draw_roundbox_aa(&rect, true, radius, icon_color);
3018  UI_draw_roundbox_aa(&rect, false, radius, icon_border);
3019  GPU_blend(GPU_BLEND_ALPHA); /* Roundbox disables. */
3020 }
3021 
3023  TreeElement *te,
3024  const uiFontStyle *fstyle,
3025  int xmax,
3026  int *offsx,
3027  int ys,
3028  float alpha_fac,
3029  const eOLDrawState active,
3030  const int num_elements)
3031 {
3032  TreeStoreElem *tselem = TREESTORE(te);
3033 
3034  if (active != OL_DRAWSEL_NONE) {
3035  float icon_color[4], icon_border[4];
3036  outliner_icon_background_colors(icon_color, icon_border);
3037  if (active == OL_DRAWSEL_ACTIVE) {
3039  icon_border[3] = 0.3f;
3040  }
3041 
3042  outliner_draw_active_indicator((float)*offsx,
3043  (float)ys,
3044  (float)*offsx + UI_UNIT_X,
3045  (float)ys + UI_UNIT_Y,
3046  icon_color,
3047  icon_border);
3048  }
3049 
3050  if (tselem->flag & TSE_HIGHLIGHTED_ICON) {
3051  alpha_fac += 0.5;
3052  }
3053  tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, alpha_fac, false);
3054  te->xs = *offsx;
3055  te->ys = ys;
3056  te->xend = (short)*offsx + UI_UNIT_X;
3057 
3058  if (num_elements > 1) {
3059  outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements);
3060  te->flag |= TE_ICONROW_MERGED;
3061  }
3062  else {
3063  te->flag |= TE_ICONROW;
3064  }
3065 
3066  (*offsx) += UI_UNIT_X;
3067 }
3068 
3070 {
3071  TreeStoreElem *tselem = TREESTORE(te);
3072 
3073  const int id_index = (tselem->type == TSE_SOME_ID) ? BKE_idtype_idcode_to_index(te->idcode) :
3074  INDEX_ID_GR;
3075  if (id_index < INDEX_ID_OB) {
3076  return id_index;
3077  }
3078  if (id_index == INDEX_ID_OB) {
3079  const Object *ob = (Object *)tselem->id;
3080  return INDEX_ID_OB + ob->type;
3081  }
3082  return id_index + OB_TYPE_MAX;
3083 }
3084 
3087  int num_elements[INDEX_ID_MAX + OB_TYPE_MAX];
3089 };
3090 
3092  uiBlock *block,
3093  const uiFontStyle *fstyle,
3094  const TreeViewContext *tvc,
3095  SpaceOutliner *space_outliner,
3096  ListBase *lb,
3097  int level,
3098  int xmax,
3099  int *offsx,
3100  int ys,
3101  float alpha_fac,
3102  bool in_bone_hierarchy,
3103  MergedIconRow *merged)
3104 {
3106 
3107  LISTBASE_FOREACH (TreeElement *, te, lb) {
3108  TreeStoreElem *tselem = TREESTORE(te);
3109  te->flag &= ~(TE_ICONROW | TE_ICONROW_MERGED);
3110 
3111  /* object hierarchy always, further constrained on level */
3112  /* Bones are also hierarchies and get a merged count, but we only start recursing into them if
3113  * an they are at the root level of a collapsed subtree (e.g. not "hidden" in a collapsed
3114  * collection). */
3115  const bool is_bone = ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL);
3116  if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) ||
3117  (in_bone_hierarchy && is_bone)) {
3118  /* active blocks get white circle */
3119  if (tselem->type == TSE_SOME_ID) {
3120  if (te->idcode == ID_OB) {
3121  active = (tvc->obact == (Object *)tselem->id) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
3122  }
3123  else if (is_object_data_in_editmode(tselem->id, tvc->obact)) {
3125  }
3126  else {
3127  active = tree_element_active_state_get(tvc, te, tselem);
3128  }
3129  }
3130  else {
3131  active = tree_element_type_active_state_get(C, tvc, te, tselem);
3132  }
3133 
3134  if (!ELEM(tselem->type,
3135  TSE_ID_BASE,
3136  TSE_SOME_ID,
3138  TSE_R_LAYER,
3139  TSE_GP_LAYER,
3143  TSE_BONE,
3144  TSE_EBONE,
3146  TSE_POSEGRP,
3147  TSE_DEFGROUP)) {
3148  outliner_draw_iconrow_doit(block, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
3149  }
3150  else {
3151  const int index = tree_element_id_type_to_index(te);
3152  merged->num_elements[index]++;
3153  if ((merged->tree_element[index] == nullptr) || (active > merged->active[index])) {
3154  merged->tree_element[index] = te;
3155  }
3156  merged->active[index] = MAX2(active, merged->active[index]);
3157  }
3158  }
3159 
3160  /* TSE_R_LAYER tree element always has same amount of branches, so don't draw. */
3161  /* Also only recurse into bone hierarchies if a direct child of the collapsed element to merge
3162  * into. */
3163  const bool is_root_level_bone = is_bone && (level == 0);
3164  in_bone_hierarchy |= is_root_level_bone;
3166  in_bone_hierarchy) {
3168  block,
3169  fstyle,
3170  tvc,
3171  space_outliner,
3172  &te->subtree,
3173  level + 1,
3174  xmax,
3175  offsx,
3176  ys,
3177  alpha_fac,
3178  in_bone_hierarchy,
3179  merged);
3180  }
3181  }
3182 
3183  if (level == 0) {
3184  for (int i = 0; i < INDEX_ID_MAX; i++) {
3185  const int num_subtypes = (i == INDEX_ID_OB) ? OB_TYPE_MAX : 1;
3186  /* See tree_element_id_type_to_index for the index logic. */
3187  int index_base = i;
3188  if (i > INDEX_ID_OB) {
3189  index_base += OB_TYPE_MAX;
3190  }
3191  for (int j = 0; j < num_subtypes; j++) {
3192  const int index = index_base + j;
3193  if (merged->num_elements[index] != 0) {
3195  merged->tree_element[index],
3196  fstyle,
3197  xmax,
3198  offsx,
3199  ys,
3200  alpha_fac,
3201  merged->active[index],
3202  merged->num_elements[index]);
3203  }
3204  }
3205  }
3206  }
3207 }
3208 
3209 /* closed tree element */
3211 {
3212  tree_iterator::all(te->subtree, [&](TreeElement *te) {
3213  /* closed items may be displayed in row of parent, don't change their coordinate! */
3214  if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) {
3215  te->xs = 0;
3216  te->ys = 0;
3217  te->xend = 0;
3218  }
3219  });
3220 }
3221 
3223  const TreeElement *te,
3224  const TreeStoreElem *tselem)
3225 {
3226  if (tselem->type == TSE_SOME_ID) {
3227  switch (te->idcode) {
3228  case ID_OB: {
3229  const Object *ob = (const Object *)tselem->id;
3230  /* Lookup in view layer is logically const as it only checks a cache. */
3231  const Base *base = (te->directdata) ? (const Base *)te->directdata :
3233  (ViewLayer *)tvc->view_layer, (Object *)ob);
3234  const bool is_visible = (base != nullptr) && (base->flag & BASE_VISIBLE_VIEWLAYER);
3235  if (!is_visible) {
3236  return true;
3237  }
3238  }
3239  }
3240  }
3241  switch (tselem->type) {
3242  case TSE_LAYER_COLLECTION: {
3243  const LayerCollection *layer_collection = (const LayerCollection *)te->directdata;
3244  const bool is_visible = layer_collection->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER;
3245  const bool is_excluded = layer_collection->flag & LAYER_COLLECTION_EXCLUDE;
3246  return !is_visible || is_excluded;
3247  }
3248  }
3249 
3250  if (te->flag & TE_CHILD_NOT_IN_COLLECTION) {
3251  return true;
3252  }
3253 
3254  return false;
3255 }
3256 
3258  uiBlock *block,
3259  const uiFontStyle *fstyle,
3260  const TreeViewContext *tvc,
3261  ARegion *region,
3262  SpaceOutliner *space_outliner,
3263  TreeElement *te,
3264  bool draw_grayed_out,
3265  int startx,
3266  int *starty,
3267  const float restrict_column_width,
3268  TreeElement **te_edit)
3269 {
3270  TreeStoreElem *tselem = TREESTORE(te);
3271  float ufac = UI_UNIT_X / 20.0f;
3272  int offsx = 0;
3274  uchar text_color[4];
3275  UI_GetThemeColor4ubv(TH_TEXT, text_color);
3276  float icon_bgcolor[4], icon_border[4];
3277  outliner_icon_background_colors(icon_bgcolor, icon_border);
3278 
3279  if (*starty + 2 * UI_UNIT_Y >= region->v2d.cur.ymin && *starty <= region->v2d.cur.ymax) {
3280  const float alpha_fac = element_should_draw_faded(tvc, te, tselem) ? 0.5f : 1.0f;
3281  int xmax = region->v2d.cur.xmax;
3282 
3283  if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == nullptr)) {
3284  *te_edit = te;
3285  }
3286 
3287  /* Icons can be UI buts, we don't want it to overlap with restrict. */
3288  if (restrict_column_width > 0) {
3289  xmax -= restrict_column_width + UI_UNIT_X;
3290  }
3291 
3293 
3294  /* Colors for active/selected data. */
3295  if (tselem->type == TSE_SOME_ID) {
3296  if (te->idcode == ID_OB) {
3297  Object *ob = (Object *)tselem->id;
3298  Base *base = (te->directdata) ? (Base *)te->directdata :
3300  const bool is_selected = (base != nullptr) && ((base->flag & BASE_SELECTED) != 0);
3301 
3302  if (ob == tvc->obact) {
3304  }
3305 
3306  if (is_selected) {
3307  if (ob == tvc->obact) {
3308  /* Active selected object. */
3310  text_color[3] = 255;
3311  }
3312  else {
3313  /* Other selected objects. */
3315  text_color[3] = 255;
3316  }
3317  }
3318  }
3319  else if (is_object_data_in_editmode(tselem->id, tvc->obact)) {
3320  /* Objects being edited. */
3321  UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_bgcolor);
3322  icon_border[3] = 0.3f;
3324  }
3325  else {
3326  if (tree_element_active_state_get(tvc, te, tselem)) {
3327  /* Active items like camera or material. */
3328  icon_bgcolor[3] = 0.2f;
3330  }
3331  }
3332  }
3333  else {
3334  active = tree_element_type_active_state_get(C, tvc, te, tselem);
3335  }
3336 
3337  /* Active circle. */
3338  if (active != OL_DRAWSEL_NONE) {
3339  outliner_draw_active_indicator((float)startx + offsx + UI_UNIT_X,
3340  (float)*starty,
3341  (float)startx + offsx + 2.0f * UI_UNIT_X,
3342  (float)*starty + UI_UNIT_Y,
3343  icon_bgcolor,
3344  icon_border);
3345 
3346  te->flag |= TE_ACTIVE; /* For lookup in display hierarchies. */
3347  }
3348 
3349  if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
3350  /* Scene collection in view layer can't expand/collapse. */
3351  }
3352  else if (te->subtree.first || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) ||
3353  (te->flag & TE_PRETEND_HAS_CHILDREN)) {
3354  /* Open/close icon, only when sub-levels, except for scene. */
3355  int icon_x = startx;
3356 
3357  /* Icons a bit higher. */
3358  if (TSELEM_OPEN(tselem, space_outliner)) {
3359  UI_icon_draw_alpha((float)icon_x + 2 * ufac,
3360  (float)*starty + 1 * ufac,
3361  ICON_DISCLOSURE_TRI_DOWN,
3362  alpha_fac);
3363  }
3364  else {
3365  UI_icon_draw_alpha((float)icon_x + 2 * ufac,
3366  (float)*starty + 1 * ufac,
3367  ICON_DISCLOSURE_TRI_RIGHT,
3368  alpha_fac);
3369  }
3370  }
3371  offsx += UI_UNIT_X;
3372 
3373  /* Data-type icon. */
3375  tselem_draw_icon(block,
3376  xmax,
3377  (float)startx + offsx,
3378  (float)*starty,
3379  tselem,
3380  te,
3381  (tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac,
3382  true)) {
3383  offsx += UI_UNIT_X + 4 * ufac;
3384  }
3385  else {
3386  offsx += 2 * ufac;
3387  }
3388 
3389  const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te);
3390  if (ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION) ||
3391  (te_rna_struct && RNA_struct_is_ID(te_rna_struct->getPointerRNA().type))) {
3392  const BIFIconID lib_icon = (BIFIconID)UI_icon_from_library(tselem->id);
3393  if (lib_icon != ICON_NONE) {
3395  (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, lib_icon, alpha_fac);
3396  offsx += UI_UNIT_X + 4 * ufac;
3397  }
3398  }
3400 
3401  /* Name. */
3402  if ((tselem->flag & TSE_TEXTBUT) == 0) {
3403  if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
3404  UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_color);
3405  text_color[3] = 255;
3406  }
3407  text_color[3] *= alpha_fac;
3408  UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_color);
3409  }
3410 
3411  offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
3412 
3413  /* Closed item, we draw the icons, not when it's a scene, or master-server list though. */
3414  if (!TSELEM_OPEN(tselem, space_outliner)) {
3415  if (te->subtree.first) {
3416  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_SCE)) {
3417  /* Pass. */
3418  }
3419  /* this tree element always has same amount of branches, so don't draw */
3420  else if (tselem->type != TSE_R_LAYER) {
3421  int tempx = startx + offsx;
3422 
3424 
3425  MergedIconRow merged{};
3427  block,
3428  fstyle,
3429  tvc,
3430  space_outliner,
3431  &te->subtree,
3432  0,
3433  xmax,
3434  &tempx,
3435  *starty,
3436  alpha_fac,
3437  false,
3438  &merged);
3439 
3441  }
3442  }
3443  }
3444  }
3445  /* Store coord and continue, we need coordinates for elements outside view too. */
3446  te->xs = startx;
3447  te->ys = *starty;
3448  te->xend = startx + offsx;
3449 
3450  if (TSELEM_OPEN(tselem, space_outliner)) {
3451  *starty -= UI_UNIT_Y;
3452 
3453  LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
3454  /* Check if element needs to be drawn grayed out, but also gray out
3455  * children of a grayed out parent (pass on draw_grayed_out to children). */
3456  bool draw_children_grayed_out = draw_grayed_out || (ten->flag & TE_DRAGGING);
3458  block,
3459  fstyle,
3460  tvc,
3461  region,
3462  space_outliner,
3463  ten,
3464  draw_children_grayed_out,
3465  startx + UI_UNIT_X,
3466  starty,
3467  restrict_column_width,
3468  te_edit);
3469  }
3470  }
3471  else {
3473  *starty -= UI_UNIT_Y;
3474  }
3475 }
3476 
3478 {
3479  LISTBASE_FOREACH (TreeElement *, te, lb) {
3480  TreeStoreElem *tselem = TREESTORE(te);
3481  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
3482  return true;
3483  }
3484  }
3485  return false;
3486 }
3487 
3489  const uint pos, const int x, const int y1, const int y2, const bool draw_dashed)
3490 {
3491  /* Small vertical padding. */
3492  const short line_padding = UI_UNIT_Y / 4.0f;
3493 
3494  /* >= is 1.0 for un-dashed lines. */
3495  immUniform1f("dash_factor", draw_dashed ? 0.5f : 1.0f);
3496 
3498  /* Intentionally draw from top to bottom, so collapsing a child item doesn't make the dashes
3499  * appear to move. */
3500  immVertex2f(pos, x, y2 + line_padding);
3501  immVertex2f(pos, x, y1 - line_padding);
3502  immEnd();
3503 }
3504 
3506  SpaceOutliner *space_outliner,
3507  ListBase *lb,
3508  int startx,
3509  const uchar col[4],
3510  bool draw_grayed_out,
3511  int *starty)
3512 {
3513  bTheme *btheme = UI_GetTheme();
3514  int y = *starty;
3515 
3516  /* Draw vertical lines between collections */
3517  bool draw_hierarchy_line;
3518  bool is_object_line;
3519  LISTBASE_FOREACH (TreeElement *, te, lb) {
3520  TreeStoreElem *tselem = TREESTORE(te);
3521  draw_hierarchy_line = false;
3522  is_object_line = false;
3523  *starty -= UI_UNIT_Y;
3524  short color_tag = COLLECTION_COLOR_NONE;
3525 
3526  /* Only draw hierarchy lines for expanded collections and objects with children. */
3527  if (TSELEM_OPEN(tselem, space_outliner) && !BLI_listbase_is_empty(&te->subtree)) {
3528  if (tselem->type == TSE_LAYER_COLLECTION) {
3529  draw_hierarchy_line = true;
3530 
3532  color_tag = collection->color_tag;
3533 
3534  y = *starty;
3535  }
3536  else if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
3537  if (subtree_contains_object(&te->subtree)) {
3538  draw_hierarchy_line = true;
3539  is_object_line = true;
3540  y = *starty;
3541  }
3542  }
3543 
3545  pos, space_outliner, &te->subtree, startx + UI_UNIT_X, col, draw_grayed_out, starty);
3546  }
3547 
3548  if (draw_hierarchy_line) {
3549  if (color_tag != COLLECTION_COLOR_NONE) {
3550  immUniformColor4ubv(btheme->collection_color[color_tag].color);
3551  }
3552  else {
3554  }
3555 
3556  outliner_draw_hierarchy_line(pos, startx, y, *starty, is_object_line);
3557  }
3558  }
3559 }
3560 
3561 static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner,
3562  ListBase *lb,
3563  int startx,
3564  int *starty)
3565 {
3568  uchar col[4];
3569 
3571 
3572  float viewport_size[4];
3573  GPU_viewport_size_get_f(viewport_size);
3574  immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
3575  immUniform1i("colors_len", 0); /* "simple" mode */
3576  immUniform1f("dash_width", 8.0f);
3578  col[3] = 255;
3579 
3580  GPU_line_width(1.0f);
3582  outliner_draw_hierarchy_lines_recursive(pos, space_outliner, lb, startx, col, false, starty);
3584 
3585  immUnbindProgram();
3586 }
3587 
3589  SpaceOutliner *space_outliner,
3590  ListBase *lb,
3591  int *starty)
3592 {
3593  LISTBASE_FOREACH (TreeElement *, te, lb) {
3594  TreeStoreElem *tselem = TREESTORE(te);
3595 
3596  /* Selection status. */
3597  if (TSELEM_OPEN(tselem, space_outliner)) {
3598  if (tselem->type == TSE_RNA_STRUCT) {
3602  immThemeColorShadeAlpha(TH_BACK, -15, -200);
3603  immRecti(pos, 0, *starty + 1, (int)region->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
3604  immUnbindProgram();
3605  }
3606  }
3607 
3608  *starty -= UI_UNIT_Y;
3609  if (TSELEM_OPEN(tselem, space_outliner)) {
3610  outliner_draw_struct_marks(region, space_outliner, &te->subtree, starty);
3611  if (tselem->type == TSE_RNA_STRUCT) {
3615  immThemeColorShadeAlpha(TH_BACK, -15, -200);
3616 
3618  immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
3619  immVertex2f(pos, region->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
3620  immEnd();
3621 
3622  immUnbindProgram();
3623  }
3624  }
3625  }
3626 }
3627 
3629  const ARegion *region,
3630  const SpaceOutliner *space_outliner,
3631  const float col_selection[4],
3632  const float col_active[4],
3633  const float col_highlight[4],
3634  const float col_searchmatch[4],
3635  int start_x,
3636  int *io_start_y)
3637 {
3638  const bool is_searching = (SEARCHING_OUTLINER(space_outliner) ||
3639  (space_outliner->outlinevis == SO_DATA_API &&
3640  space_outliner->search_string[0] != 0));
3641 
3642  tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
3643  const TreeStoreElem *tselem = TREESTORE(te);
3644  const int start_y = *io_start_y;
3645 
3646  /* Selection status. */
3647  if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
3648  immUniformColor4fv(col_active);
3649  immRecti(pos, 0, start_y, (int)region->v2d.cur.xmax, start_y + UI_UNIT_Y);
3650  }
3651  else if (tselem->flag & TSE_SELECTED) {
3652  immUniformColor4fv(col_selection);
3653  immRecti(pos, 0, start_y, (int)region->v2d.cur.xmax, start_y + UI_UNIT_Y);
3654  }
3655 
3656  /* Highlights. */
3657  if (tselem->flag & (TSE_DRAG_ANY | TSE_HIGHLIGHTED | TSE_SEARCHMATCH)) {
3658  const int end_x = (int)region->v2d.cur.xmax;
3659 
3660  if (tselem->flag & TSE_DRAG_ANY) {
3661  /* Drag and drop highlight. */
3662  float col[4];
3664 
3665  if (tselem->flag & TSE_DRAG_BEFORE) {
3667  immRecti(pos,
3668  start_x,
3669  start_y + UI_UNIT_Y - U.pixelsize,
3670  end_x,
3671  start_y + UI_UNIT_Y + U.pixelsize);
3672  }
3673  else if (tselem->flag & TSE_DRAG_AFTER) {
3675  immRecti(pos, start_x, start_y - U.pixelsize, end_x, start_y + U.pixelsize);
3676  }
3677  else {
3678  immUniformColor3fvAlpha(col, col[3] * 0.5f);
3679  immRecti(pos, start_x, start_y, end_x, start_y + UI_UNIT_Y);
3680  }
3681  }
3682  else {
3683  if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
3684  /* Search match highlights. We don't expand items when searching in the data-blocks,
3685  * but we still want to highlight any filter matches. */
3686  immUniformColor4fv(col_searchmatch);
3687  immRecti(pos, start_x, start_y, end_x, start_y + UI_UNIT_Y);
3688  }
3689  else if (tselem->flag & TSE_HIGHLIGHTED) {
3690  /* Mouse hover highlight. */
3691  immUniformColor4fv(col_highlight);
3692  immRecti(pos, 0, start_y, end_x, start_y + UI_UNIT_Y);
3693  }
3694  }
3695  }
3696 
3697  *io_start_y -= UI_UNIT_Y;
3698  });
3699 }
3700 
3701 static void outliner_draw_highlights(ARegion *region,
3702  SpaceOutliner *space_outliner,
3703  int startx,
3704  int *starty)
3705 {
3706  const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
3707  float col_selection[4], col_active[4], col_searchmatch[4];
3708 
3709  UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
3710  col_selection[3] = 1.0f; /* No alpha. */
3712  col_active[3] = 1.0f; /* No alpha. */
3713  UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
3714  col_searchmatch[3] = 0.5f;
3715 
3721  region,
3722  space_outliner,
3723  col_selection,
3724  col_active,
3725  col_highlight,
3726  col_searchmatch,
3727  startx,
3728  starty);
3729  immUnbindProgram();
3731 }
3732 
3734  uiBlock *block,
3735  const TreeViewContext *tvc,
3736  ARegion *region,
3737  SpaceOutliner *space_outliner,
3738  const float right_column_width,
3739  const bool use_mode_column,
3740  const bool use_warning_column,
3741  TreeElement **te_edit)
3742 {
3743  const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
3744  int starty, startx;
3745 
3746  /* Move the tree a unit left in view layer mode */
3747  short columns_offset = (use_mode_column && (space_outliner->outlinevis == SO_SCENES)) ?
3748  UI_UNIT_X :
3749  0;
3750  if (!use_mode_column && (space_outliner->outlinevis == SO_VIEW_LAYER)) {
3751  columns_offset -= UI_UNIT_X;
3752  }
3753 
3754  if (use_warning_column) {
3755  columns_offset += UI_UNIT_X;
3756  }
3757 
3758  GPU_blend(GPU_BLEND_ALPHA); /* Only once. */
3759 
3760  if (space_outliner->outlinevis == SO_DATA_API) {
3761  /* struct marks */
3762  starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
3763  outliner_draw_struct_marks(region, space_outliner, &space_outliner->tree, &starty);
3764  }
3765 
3766  /* Draw highlights before hierarchy. */
3767  starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
3768  startx = 0;
3769  outliner_draw_highlights(region, space_outliner, startx, &starty);
3770 
3771  /* Set scissor so tree elements or lines can't overlap restriction icons. */
3772  int scissor[4] = {0};
3773  if (right_column_width > 0.0f) {
3774  int mask_x = BLI_rcti_size_x(&region->v2d.mask) - (int)right_column_width + 1;
3775  CLAMP_MIN(mask_x, 0);
3776 
3777  GPU_scissor_get(scissor);
3778  GPU_scissor(0, 0, mask_x, region->winy);
3779  }
3780 
3781  /* Draw hierarchy lines for collections and object children. */
3782  starty = (int)region->v2d.tot.ymax - OL_Y_OFFSET;
3783  startx = columns_offset + UI_UNIT_X / 2 - (U.pixelsize + 1) / 2;
3784  outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty);
3785 
3786  /* Items themselves. */
3787  starty = (int)region->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
3788  startx = columns_offset;
3789  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
3791  block,
3792  fstyle,
3793  tvc,
3794  region,
3795  space_outliner,
3796  te,
3797  (te->flag & TE_DRAGGING) != 0,
3798  startx,
3799  &starty,
3800  right_column_width,
3801  te_edit);
3802  }
3803 
3804  if (right_column_width > 0.0f) {
3805  /* Reset scissor. */
3806  GPU_scissor(UNPACK4(scissor));
3807  }
3808 }
3809 
3810 static void outliner_back(ARegion *region)
3811 {
3812  int ystart;
3813 
3814  ystart = (int)region->v2d.tot.ymax;
3815  ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
3816 
3819 
3821 
3822  float col_alternating[4];
3823  UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating);
3824  immUniformThemeColorBlend(TH_BACK, TH_ROW_ALTERNATE, col_alternating[3]);
3825 
3826  const float x1 = 0.0f, x2 = region->v2d.cur.xmax;
3827  float y1 = ystart, y2;
3828  int tot = (int)floor(ystart - region->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
3829 
3830  if (tot > 0) {
3831  immBegin(GPU_PRIM_TRIS, 6 * tot);
3832  while (tot--) {
3833  y1 -= 2 * UI_UNIT_Y;
3834  y2 = y1 + UI_UNIT_Y;
3835  immVertex2f(pos, x1, y1);
3836  immVertex2f(pos, x2, y1);
3837  immVertex2f(pos, x2, y2);
3838 
3839  immVertex2f(pos, x1, y1);
3840  immVertex2f(pos, x2, y2);
3841  immVertex2f(pos, x1, y2);
3842  }
3843  immEnd();
3844  }
3845  immUnbindProgram();
3846 }
3847 
3848 static int outliner_data_api_buttons_start_x(int max_tree_width)
3849 {
3850  return max_ii(OL_RNA_COLX, max_tree_width + OL_RNA_COL_SPACEX);
3851 }
3852 
3853 static int outliner_width(SpaceOutliner *space_outliner,
3854  int max_tree_width,
3855  float right_column_width)
3856 {
3857  if (space_outliner->outlinevis == SO_DATA_API) {
3858  return outliner_data_api_buttons_start_x(max_tree_width) + OL_RNA_COL_SIZEX + 10 * UI_DPI_FAC;
3859  }
3860  return max_tree_width + right_column_width;
3861 }
3862 
3864  SpaceOutliner *space_outliner,
3865  int tree_width,
3866  int tree_height,
3867  float right_column_width)
3868 {
3869  int sizex = outliner_width(space_outliner, tree_width, right_column_width);
3870  int sizey = tree_height;
3871 
3872  /* Extend size to allow for horizontal scrollbar and extra offset. */
3873  sizey += V2D_SCROLL_HEIGHT + OL_Y_OFFSET;
3874 
3875  UI_view2d_totRect_set(&region->v2d, sizex, sizey);
3876 }
3877 
3880 /* -------------------------------------------------------------------- */
3886 void draw_outliner(const bContext *C)
3887 {
3888  Main *mainvar = CTX_data_main(C);
3889  ARegion *region = CTX_wm_region(C);
3890  View2D *v2d = &region->v2d;
3891  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
3892  uiBlock *block;
3893  TreeElement *te_edit = nullptr;
3894 
3895  TreeViewContext tvc;
3897 
3898  outliner_build_tree(mainvar, tvc.scene, tvc.view_layer, space_outliner, region); /* Always. */
3899 
3900  /* If global sync select is dirty, flag other outliners. */
3903  }
3904 
3905  /* Sync selection state from view layer. */
3906  if (!ELEM(space_outliner->outlinevis,
3907  SO_LIBRARIES,
3909  SO_DATA_API,
3910  SO_ID_ORPHANS) &&
3911  space_outliner->flag & SO_SYNC_SELECT) {
3912  outliner_sync_selection(C, space_outliner);
3913  }
3914 
3915  /* Force display to pixel coords. */
3916  v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y);
3917  /* Set matrix for 2D-view controls. */
3918  UI_view2d_view_ortho(v2d);
3919 
3920  /* Only show mode column in View Layers and Scenes view. */
3921  const bool use_mode_column = outliner_shows_mode_column(*space_outliner);
3922  const bool use_warning_column = outliner_has_element_warnings(*space_outliner);
3923 
3924  /* Draw outliner stuff (background, hierarchy lines and names). */
3925  const float right_column_width = outliner_right_columns_width(space_outliner);
3926  outliner_back(region);
3927  block = UI_block_begin(C, region, __func__, UI_EMBOSS);
3929  block,
3930  &tvc,
3931  region,
3932  space_outliner,
3933  right_column_width,
3934  use_mode_column,
3935  use_warning_column,
3936  &te_edit);
3937 
3938  /* Compute outliner dimensions after it has been drawn. */
3939  int tree_width, tree_height;
3940  outliner_tree_dimensions(space_outliner, &tree_width, &tree_height);
3941 
3942  /* Default to no emboss for outliner UI. */
3944 
3945  if (space_outliner->outlinevis == SO_DATA_API) {
3946  int buttons_start_x = outliner_data_api_buttons_start_x(tree_width);
3947  /* draw rna buttons */
3948  outliner_draw_separator(region, buttons_start_x);
3949  outliner_draw_separator(region, buttons_start_x + OL_RNA_COL_SIZEX);
3950 
3952  outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x);
3954  }
3955  else if (space_outliner->outlinevis == SO_ID_ORPHANS) {
3956  /* draw user toggle columns */
3957  outliner_draw_userbuts(block, region, space_outliner);
3958  }
3959  else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
3960  const int x = region->v2d.cur.xmax - right_column_width;
3961  outliner_draw_separator(region, x);
3965  outliner_draw_overrides_rna_buts(block, region, space_outliner, &space_outliner->tree, x);
3967  }
3968  else if (space_outliner->lib_override_view_mode == SO_LIB_OVERRIDE_VIEW_HIERARCHIES) {
3970  mainvar, block, region, space_outliner, &space_outliner->tree, x);
3971  }
3972  }
3973  else if (right_column_width > 0.0f) {
3974  /* draw restriction columns */
3975  RestrictPropertiesActive props_active;
3976  memset(&props_active, 1, sizeof(RestrictPropertiesActive));
3978  tvc.scene,
3979  tvc.view_layer,
3980  region,
3981  space_outliner,
3982  &space_outliner->tree,
3983  props_active);
3984  }
3985 
3986  /* Draw mode icons */
3987  if (use_mode_column) {
3988  outliner_draw_mode_column(block, &tvc, space_outliner);
3989  }
3990 
3991  /* Draw warning icons */
3992  if (use_warning_column) {
3993  outliner_draw_warning_column(block, space_outliner, use_mode_column);
3994  }
3995 
3997 
3998  /* Draw edit buttons if necessary. */
3999  if (te_edit) {
4000  outliner_buttons(C, block, region, right_column_width, te_edit);
4001  }
4002 
4003  UI_block_end(C, block);
4004  UI_block_draw(C, block);
4005 
4006  /* Update total viewable region. */
4008  region, space_outliner, tree_width, tree_height, right_column_width);
4009 }
4010 
typedef float(TangentPoint)[2]
bool BKE_collection_has_collection(const struct Collection *parent, const struct Collection *collection)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
Definition: context.c:860
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:775
struct wmMsgBus * CTX_wm_message_bus(const bContext *C)
Definition: context.c:770
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
short BKE_curve_type_get(const struct Curve *cu)
support for deformation groups and hooks.
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob)
Definition: deform.c:692
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
Definition: gpencil.c:1601
int BKE_idtype_idcode_to_index(short idcode)
Definition: idtype.c:324
void BKE_view_layer_rename(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, const char *name)
Definition: layer.c:534
bool BKE_layer_collection_has_layer_collection(struct LayerCollection *lc_parent, struct LayerCollection *lc_child)
Definition: layer.c:1470
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer)
void BKE_main_collection_sync_remap(const struct Main *bmain)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL()
Definition: lib_id.c:1813
bool BKE_lib_override_library_is_system_defined(const struct Main *bmain, const struct ID *id)
void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const char *filepath)
Definition: library.c:112
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_main_namemap_remove_name(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL()
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_child_recursive(const struct Object *ob_parent, const struct Object *ob_child)
bool BKE_object_data_is_in_editmode(const struct Object *ob, const struct ID *id)
struct ParticleSystem * psys_get_current(struct Object *ob)
Definition: particle.c:634
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:46
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
MINLINE int max_ii(int a, int b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define FILE_MAX
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:407
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL()
Definition: string.c:1114
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNPACK4(a)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define CLAMP_MIN(a, b)
#define BLT_I18NCONTEXT_ID_ACTION
#define TIP_(msgid)
#define CTX_DATA_(context, msgid)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ID_RECALC_BASE_FLAGS
Definition: DNA_ID.h:821
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:581
@ INDEX_ID_GR
Definition: DNA_ID.h:1040
@ INDEX_ID_OB
Definition: DNA_ID.h:1039
@ INDEX_ID_MAX
Definition: DNA_ID.h:1058
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define MAX_ID_NAME
Definition: DNA_ID.h:337
@ LIB_TAG_MISSING
Definition: DNA_ID.h:690
@ LIB_FAKEUSER
Definition: DNA_ID.h:630
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED
Definition: DNA_ID.h:327
@ ID_CA
Definition: DNA_ID_enums.h:56
@ ID_AR
Definition: DNA_ID_enums.h:66
@ ID_MC
Definition: DNA_ID_enums.h:73
@ ID_LI
Definition: DNA_ID_enums.h:46
@ ID_TE
Definition: DNA_ID_enums.h:52
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_VO
Definition: DNA_ID_enums.h:83
@ ID_WS
Definition: DNA_ID_enums.h:79
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_LA
Definition: DNA_ID_enums.h:55
@ ID_KE
Definition: DNA_ID_enums.h:58
@ ID_TXT
Definition: DNA_ID_enums.h:62
@ ID_SO
Definition: DNA_ID_enums.h:64
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_LS
Definition: DNA_ID_enums.h:75
@ ID_MSK
Definition: DNA_ID_enums.h:74
@ ID_GD
Definition: DNA_ID_enums.h:71
@ ID_CV
Definition: DNA_ID_enums.h:81
@ ID_BR
Definition: DNA_ID_enums.h:69
@ ID_LP
Definition: DNA_ID_enums.h:80
@ ID_WO
Definition: DNA_ID_enums.h:59
@ ID_SIM
Definition: DNA_ID_enums.h:84
@ ID_MA
Definition: DNA_ID_enums.h:51
@ ID_AC
Definition: DNA_ID_enums.h:67
@ ID_SCR
Definition: DNA_ID_enums.h:60
@ ID_CU_LEGACY
Definition: DNA_ID_enums.h:49
@ ID_ME
Definition: DNA_ID_enums.h:48
@ ID_GR
Definition: DNA_ID_enums.h:65
@ ID_SPK
Definition: DNA_ID_enums.h:63
@ ID_MB
Definition: DNA_ID_enums.h:50
@ ID_LT
Definition: DNA_ID_enums.h:54
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ID_PT
Definition: DNA_ID_enums.h:82
@ ID_PC
Definition: DNA_ID_enums.h:77
#define ID_NLA
Definition: DNA_ID_enums.h:100
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_UNSELECTABLE
@ BONE_HIDDEN_A
@ BONE_HIDDEN_P
@ BONE_TIPSEL
Object groups, one object can be in many groups at once.
@ COLLECTION_IS_MASTER
@ COLLECTION_COLOR_NONE
eBConstraint_Types
@ CONSTRAINT_TYPE_TRACKTO
@ CONSTRAINT_TYPE_PIVOT
@ CONSTRAINT_TYPE_CHILDOF
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_LOCLIKE
@ CONSTRAINT_TYPE_SHRINKWRAP
@ CONSTRAINT_TYPE_MINMAX
@ CONSTRAINT_TYPE_ROTLIMIT
@ CONSTRAINT_TYPE_CAMERASOLVER
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_DISTLIMIT
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_LOCLIMIT
@ CONSTRAINT_TYPE_CLAMPTO
@ CONSTRAINT_TYPE_LOCKTRACK
@ CONSTRAINT_TYPE_SIZELIMIT
@ CONSTRAINT_TYPE_ACTION
@ CONSTRAINT_TYPE_FOLLOWPATH
@ CONSTRAINT_TYPE_STRETCHTO
@ CONSTRAINT_TYPE_SIZELIKE
@ CONSTRAINT_TYPE_SAMEVOL
@ CONSTRAINT_TYPE_DAMPTRACK
@ CONSTRAINT_TYPE_TRANSFORM_CACHE
@ eGpencilModifierType_Array
@ eGpencilModifierType_Noise
@ eGpencilModifierType_Mirror
@ eGpencilModifierType_Color
@ eGpencilModifierType_Multiply
@ eGpencilModifierType_Texture
@ eGpencilModifierType_Subdiv
@ eGpencilModifierType_Lattice
@ eGpencilModifierType_Opacity
@ eGpencilModifierType_Hook
@ eGpencilModifierType_Simplify
@ eGpencilModifierType_Shrinkwrap
@ eGpencilModifierType_WeightProximity
@ eGpencilModifierType_Armature
@ eGpencilModifierType_WeightAngle
@ eGpencilModifierType_Smooth
@ eGpencilModifierType_Tint
@ eGpencilModifierType_Time
@ eGpencilModifierType_Thick
@ eGpencilModifierType_Build
@ eGpencilModifierType_Offset
#define GPENCIL_EDIT_MODE(gpd)
@ GP_LAYER_LOCKED
@ GP_LAYER_HIDE
@ LAYER_COLLECTION_EXCLUDE
@ BASE_VISIBLE_VIEWLAYER
@ BASE_SELECTED
@ VIEW_LAYER_RENDER
@ LAYER_COLLECTION_VISIBLE_VIEW_LAYER
#define LA_AREA
#define LA_SPOT
#define LA_SUN
#define LA_LOCAL
@ LIGHTPROBE_TYPE_CUBE
@ LIGHTPROBE_TYPE_PLANAR
@ LIGHTPROBE_TYPE_GRID
ModifierType
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ OB_EMPTY_IMAGE
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_TYPE_MAX
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_GPENCIL
@ OB_LIGHTPROBE
#define OB_DATA_SUPPORT_EDITMODE(_type)
@ OB_DUPLICOLLECTION
@ TSE_POSE_CHANNEL
@ TSE_CONSTRAINT_BASE
@ TSE_LIBRARY_OVERRIDE_OPERATION
@ TSE_MODIFIER_BASE
@ TSE_GP_LAYER
@ TSE_SEQUENCE_DUP
@ TSE_RNA_ARRAY_ELEM
@ TSE_SEQUENCE
@ TSE_GPENCIL_EFFECT
@ TSE_POSEGRP_BASE
@ TSE_VIEW_COLLECTION_BASE
@ TSE_ANIM_DATA
@ TSE_LIBRARY_OVERRIDE
@ TSE_RNA_PROPERTY
@ TSE_LIBRARY_OVERRIDE_BASE
@ TSE_EBONE
@ TSE_NLA_TRACK
@ TSE_BONE
@ TSE_LINKED_PSYS
@ TSE_DEFGROUP_BASE
@ TSE_CONSTRAINT
@ TSE_SCENE_COLLECTION_BASE
@ TSE_SCENE_OBJECTS_BASE
@ TSE_R_LAYER_BASE
@ TSE_LAYER_COLLECTION
@ TSE_SEQ_STRIP
@ TSE_GPENCIL_EFFECT_BASE
@ TSE_LINKED_OB
@ TSE_NLA
@ TSE_ID_BASE
@ TSE_SOME_ID
@ TSE_DRIVER_BASE
@ TSE_NLA_ACTION
@ TSE_MODIFIER
@ TSE_POSEGRP
@ TSE_R_LAYER
@ TSE_RNA_STRUCT
@ TSE_POSE_BASE
@ TSE_DEFGROUP
@ TSE_DRAG_AFTER
@ TSE_SELECTED
@ TSE_HIGHLIGHTED_ICON
@ TSE_HIGHLIGHTED
@ TSE_SEARCHMATCH
@ TSE_DRAG_BEFORE
@ TSE_DRAG_ANY
@ TSE_ACTIVE
@ TSE_TEXTBUT
@ SCE_OBJECT_MODE_LOCK
@ SEQ_TYPE_TRANSFORM
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_CROSS
@ SEQ_TYPE_GLOW
@ SEQ_TYPE_COLORMIX
@ SEQ_TYPE_WIPE
@ SEQ_TYPE_META
@ SEQ_TYPE_OVERDROP
@ SEQ_TYPE_ALPHAUNDER
@ SEQ_TYPE_SCENE
@ SEQ_TYPE_GAMCROSS
@ SEQ_TYPE_MULTICAM
@ SEQ_TYPE_MOVIECLIP
@ SEQ_TYPE_MUL
@ SEQ_TYPE_GAUSSIAN_BLUR
@ SEQ_TYPE_ADD
@ SEQ_TYPE_ALPHAOVER
@ SEQ_TYPE_TEXT
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_SUB
@ SEQ_TYPE_SPEED
@ SEQ_TYPE_COLOR
@ SEQ_TYPE_MOVIE
@ SEQ_TYPE_MASK
@ SEQ_TYPE_ADJUSTMENT
@ SO_LIB_OVERRIDE_VIEW_HIERARCHIES
@ SO_LIB_OVERRIDE_VIEW_PROPERTIES
@ SO_RESTRICT_HIDE
@ SO_RESTRICT_RENDER
@ SO_RESTRICT_INDIRECT_ONLY
@ SO_RESTRICT_VIEWPORT
@ SO_RESTRICT_ENABLE
@ SO_RESTRICT_HOLDOUT
@ SO_RESTRICT_SELECT
@ SO_SYNC_SELECT
@ SO_OVERRIDES_LIBRARY
@ SO_DATA_API
@ SO_LIBRARIES
@ SO_VIEW_LAYER
@ SO_SCENES
@ SO_ID_ORPHANS
@ TXT_ISMEM
@ V2D_PIXELOFS_X
@ V2D_PIXELOFS_Y
int ED_file_extension_icon(const char *path)
Definition: filelist.c:2837
void ED_outliner_select_sync_flag_outliners(const struct bContext *C)
bool ED_outliner_select_sync_is_dirty(const struct bContext *C)
void immUniformColor4ubv(const unsigned char rgba[4])
void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
void immUniform2f(const char *name, float x, float y)
void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
void immUniformColor4fv(const float rgba[4])
void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
GPUVertFormat * immVertexFormat(void)
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void immEnd(void)
void immRecti(uint pos, int x1, int y1, int x2, int y2)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:21
@ GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR
Definition: GPU_shader.h:349
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_line_width(float width)
Definition: gpu_state.cc:158
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:185
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:254
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_I32
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
PropertyType
Definition: RNA_types.h:58
@ PROP_ENUM
Definition: RNA_types.h:63
@ PROP_POINTER
Definition: RNA_types.h:64
#define C
Definition: RandGen.cpp:25
@ UI_BUT_ICON_REVERSE
Definition: UI_interface.h:294
void UI_but_flag_disable(uiBut *but, int flag)
Definition: interface.cc:5863
void UI_but_disable(uiBut *but, const char *disabled_hint)
Definition: interface.cc:5883
#define UI_UNIT_Y
@ UI_BUT_DRAG_LOCK
Definition: UI_interface.h:194
@ UI_BUT_REDALERT
Definition: UI_interface.h:201
@ UI_BUT_UNDO
Definition: UI_interface.h:205
@ UI_BUT_DISABLED
Definition: UI_interface.h:196
@ UI_BUT_INACTIVE
Definition: UI_interface.h:203
@ UI_EMBOSS
Definition: UI_interface.h:108
@ UI_EMBOSS_NONE_OR_STATUS
Definition: UI_interface.h:116
void UI_fontstyle_set(const struct uiFontStyle *fs)
uiBut * uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5336
const struct PointerRNA * UI_but_context_ptr_get(const uiBut *but, const char *name, const StructRNA *type CPP_ARG_DEFAULT(nullptr))
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:4806
uiBut * uiDefAutoButR(uiBlock *block, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, const char *name, int icon, int x, int y, int width, int height)
uiBut * uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5570
void UI_fontstyle_draw_simple(const struct uiFontStyle *fs, float x, float y, const char *str, const uchar col[4])
void UI_but_drawflag_enable(uiBut *but, int flag)
Definition: interface.cc:5873
void uiDefAutoButsArrayR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const int icon, const int x, const int y, const int tot_width, const int height)
void UI_draw_roundbox_corner_set(int type)
void UI_but_func_identity_compare_set(uiBut *but, uiButIdentityCompareFunc cmp_fn)
uiBut * uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5484
void UI_block_end(const struct bContext *C, uiBlock *block)
void UI_block_emboss_set(uiBlock *block, eUIEmbossType emboss)
Definition: interface.cc:3629
void UI_block_draw(const struct bContext *C, struct uiBlock *block)
bool UI_but_active_only(const struct bContext *C, struct ARegion *region, uiBlock *block, uiBut *but)
void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1)
Definition: interface.cc:5983
#define UI_DPI_FAC
Definition: UI_interface.h:305
void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
Definition: interface.cc:6000
void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4])
@ UI_CNR_ALL
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
#define UI_FSTYLE_WIDGET
#define UI_UNIT_X
void UI_block_flag_enable(uiBlock *block, int flag)
Definition: interface.cc:5848
uiBut * uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:5422
@ UI_BTYPE_BUT
Definition: UI_interface.h:330
@ UI_BTYPE_TEXT
Definition: UI_interface.h:332
@ UI_BTYPE_LABEL
Definition: UI_interface.h:354
@ UI_BTYPE_ICON_TOGGLE_N
Definition: UI_interface.h:343
@ UI_BTYPE_ICON_TOGGLE
Definition: UI_interface.h:342
void UI_but_context_ptr_set(uiBlock *block, uiBut *but, const char *name, const struct PointerRNA *ptr)
void UI_but_flag_enable(uiBut *but, int flag)
Definition: interface.cc:5858
int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
uiBut * uiDefIconButO(uiBlock *block, int type, const char *opname, wmOperatorCallContext opcontext, int icon, int x, int y, short width, short height, const char *tip)
Definition: interface.cc:5608
@ UI_BLOCK_NO_DRAW_OVERRIDDEN_STATE
Definition: UI_interface.h:162
#define ICON_DEFAULT_HEIGHT
bool UI_icon_get_theme_color(int icon_id, unsigned char color[4])
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
void UI_icon_draw_ex(float x, float y, int icon_id, float aspect, float alpha, float desaturate, const uchar mono_color[4], bool mono_border)
int UI_icon_from_library(const struct ID *id)
int UI_icon_from_object_mode(int mode)
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3])
Definition: resources.c:1100
BIFIconID
Definition: UI_resources.h:18
@ TH_SELECT_ACTIVE
Definition: UI_resources.h:258
@ TH_ROW_ALTERNATE
Definition: UI_resources.h:262
@ TH_SELECT_HIGHLIGHT
Definition: UI_resources.h:257
@ TH_ACTIVE_OBJECT
Definition: UI_resources.h:260
@ TH_BACK
Definition: UI_resources.h:39
@ TH_EDITED_OBJECT
Definition: UI_resources.h:261
@ TH_SELECTED_OBJECT
Definition: UI_resources.h:259
@ TH_MATCH
Definition: UI_resources.h:256
@ TH_TEXT
Definition: UI_resources.h:42
@ TH_TEXT_HI
Definition: UI_resources.h:43
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
Definition: resources.c:1323
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1067
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1173
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4])
Definition: resources.c:1331
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
Definition: resources.c:1352
#define V2D_SCROLL_HEIGHT
Definition: UI_view2d.h:54
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height)
Definition: view2d.cc:1022
#define V2D_SCROLL_WIDTH
Definition: UI_view2d.h:55
void UI_view2d_view_ortho(const struct View2D *v2d)
#define NC_ID
Definition: WM_types.h:345
#define ND_DATA
Definition: WM_types.h:456
#define ND_RENDER_OPTIONS
Definition: WM_types.h:383
#define NC_SCENE
Definition: WM_types.h:328
#define ND_POSE
Definition: WM_types.h:407
#define NA_EDITED
Definition: WM_types.h:523
#define NC_MATERIAL
Definition: WM_types.h:330
#define NC_IMAGE
Definition: WM_types.h:334
#define NC_GPENCIL
Definition: WM_types.h:349
#define NC_TEXTURE
Definition: WM_types.h:331
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
@ KM_CTRL
Definition: WM_types.h:239
@ KM_SHIFT
Definition: WM_types.h:238
#define NA_RENAME
Definition: WM_types.h:527
#define NC_OBJECT
Definition: WM_types.h:329
#define NC_SPACE
Definition: WM_types.h:342
#define NA_SELECTED
Definition: WM_types.h:528
#define ND_SPACE_OUTLINER
Definition: WM_types.h:470
void ED_armature_bone_rename(Main *bmain, bArmature *arm, const char *oldnamep, const char *newnamep)
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
unsigned int U
Definition: btGjkEpa3.h:78
constexpr bool is_empty() const
constexpr const char * c_str() const
virtual StringRefNull getWarning() const
Scene scene
int len
Definition: draw_manager.c:108
bNodeTree * ntree
DRWShaderLibrary * lib
uint pos
uint col
#define GS(x)
Definition: iris.c:225
format
Definition: logImageCore.h:38
static unsigned a[3]
Definition: RandGen.cpp:78
bool active
all scheduled work for the GPU.
void all_open(const SpaceOutliner &space_outliner, const VisitorFn visitor)
void all(const SpaceOutliner &space_outliner, const VisitorFn visitor)
T floor(const T &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
Collection * outliner_collection_from_tree_element(const TreeElement *te)
bool outliner_is_collection_tree_element(const TreeElement *te)
static void scenes__collection_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
static void outliner_draw_hierarchy_lines_recursive(uint pos, SpaceOutliner *space_outliner, ListBase *lb, int startx, const uchar col[4], bool draw_grayed_out, int *starty)
static void outliner_draw_overrides_rna_buts(uiBlock *block, const ARegion *region, const SpaceOutliner *space_outliner, const ListBase *lb, const int x)
static void outliner_update_viewable_area(ARegion *region, SpaceOutliner *space_outliner, int tree_width, int tree_height, float right_column_width)
static void outliner_draw_userbuts(uiBlock *block, const ARegion *region, const SpaceOutliner *space_outliner)
static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *region, SpaceOutliner *space_outliner, ListBase *lb, RestrictPropertiesActive props_active_parent)
static void outliner_draw_mode_column(uiBlock *block, TreeViewContext *tvc, SpaceOutliner *space_outliner)
static void outliner_draw_warning_column(uiBlock *block, const SpaceOutliner *space_outliner, const bool use_mode_column)
static void outliner_restrict_properties_enable_collection_set(PointerRNA *collection_ptr, RestrictProperties *props, RestrictPropertiesActive *props_active)
static StringRefNull outliner_draw_get_warning_tree_element(const SpaceOutliner &space_outliner, const TreeElement *te)
static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
static void outliner_draw_active_indicator(const float minx, const float miny, const float maxx, const float maxy, const float icon_color[4], const float icon_border[4])
static void outliner_back(ARegion *region)
static void restrictbutton_ebone_select_fn(bContext *C, void *poin, void *poin2)
static BIFIconID tree_element_get_icon_from_id(const ID *id)
static int outliner_data_api_buttons_start_x(int max_tree_width)
static void outliner_draw_highlights(uint pos, const ARegion *region, const SpaceOutliner *space_outliner, const float col_selection[4], const float col_active[4], const float col_highlight[4], const float col_searchmatch[4], int start_x, int *io_start_y)
static bool element_should_draw_faded(const TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
static void outliner_set_subtree_coords(const TreeElement *te)
static void outliner_collection_set_flag_recursive_fn(bContext *C, LayerCollection *layer_collection, Collection *collection, const char *propname)
static void outliner__base_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
static void outliner_draw_tree_element(bContext *C, uiBlock *block, const uiFontStyle *fstyle, const TreeViewContext *tvc, ARegion *region, SpaceOutliner *space_outliner, TreeElement *te, bool draw_grayed_out, int startx, int *starty, const float restrict_column_width, TreeElement **te_edit)
static bool subtree_contains_object(ListBase *lb)
static void outliner_draw_struct_marks(ARegion *region, SpaceOutliner *space_outliner, ListBase *lb, int *starty)
static void outliner_draw_hierarchy_line(const uint pos, const int x, const int y1, const int y2, const bool draw_dashed)
static StringRefNull outliner_draw_get_warning_tree_element_subtree(const TreeElement *parent_te)
static void outliner_draw_iconrow_number(const uiFontStyle *fstyle, int offsx, int ys, const int num_elements)
int tree_element_id_type_to_index(TreeElement *te)
static void outliner_restrict_properties_enable_layer_collection_set(PointerRNA *layer_collection_ptr, PointerRNA *collection_ptr, RestrictProperties *props, RestrictPropertiesActive *props_active)
static void outliner_draw_iconrow(bContext *C, uiBlock *block, const uiFontStyle *fstyle, const TreeViewContext *tvc, SpaceOutliner *space_outliner, ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac, bool in_bone_hierarchy, MergedIconRow *merged)
static bool outliner_restrict_properties_collection_set(Scene *scene, TreeElement *te, PointerRNA *collection_ptr, PointerRNA *layer_collection_ptr, RestrictProperties *props, RestrictPropertiesActive *props_active)
static void outliner_base_or_object_pointer_create(Scene *scene, ViewLayer *view_layer, Collection *collection, Object *ob, PointerRNA *ptr)
static int outliner_width(SpaceOutliner *space_outliner, int max_tree_width, float right_column_width)
static bool outliner_but_identity_cmp_context_id_fn(const uiBut *a, const uiBut *b)
static void restrictbutton_recursive_ebone(bArmature *arm, EditBone *ebone_parent, int flag, bool set_flag)
static void outliner_draw_rnabuts(uiBlock *block, ARegion *region, SpaceOutliner *space_outliner, int sizex)
static void outliner_tree_dimensions_impl(SpaceOutliner *space_outliner, ListBase *lb, int *width, int *height)
static void outliner_object_set_flag_recursive_fn(bContext *C, Base *base, Object *ob, const char *propname)
static bool outliner_collection_is_isolated(Scene *scene, const LayerCollection *layer_collection_cmp, const Collection *collection_cmp, const bool value_cmp, const PropertyRNA *layer_or_collection_prop, LayerCollection *layer_collection, Collection *collection)
void outliner_tree_dimensions(SpaceOutliner *space_outliner, int *r_width, int *r_height)
static void restrictbutton_gp_layer_flag_fn(bContext *C, void *poin, void *UNUSED(poin2))
static void outliner_draw_separator(ARegion *region, const int x)
static void outliner_collection_set_flag_recursive(Scene *scene, ViewLayer *view_layer, LayerCollection *layer_collection, Collection *collection, PropertyRNA *layer_or_collection_prop, PropertyRNA *base_or_object_prop, const bool value)
static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED(arg2))
static void restrictbutton_ebone_visibility_fn(bContext *C, void *poin, void *poin2)
static void outliner_draw_mode_column_toggle(uiBlock *block, TreeViewContext *tvc, TreeElement *te, const bool lock_object_modes)
static void outliner_draw_hierarchy_lines(SpaceOutliner *space_outliner, ListBase *lb, int startx, int *starty)
TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
static void view_layer__layer_collection_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
static void restrictbutton_bone_visibility_fn(bContext *C, void *poin, void *UNUSED(poin2))
static void outliner_draw_overrides_restrictbuts(Main *bmain, uiBlock *block, const ARegion *region, const SpaceOutliner *space_outliner, const ListBase *lb, const int x)
static void restrictbutton_r_lay_fn(bContext *C, void *poin, void *UNUSED(poin2))
static void outliner_layer_or_collection_pointer_create(Scene *scene, LayerCollection *layer_collection, Collection *collection, PointerRNA *ptr)
static void view_layer__collection_set_flag_recursive_fn(bContext *C, void *poin, void *poin2)
static bool tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha, const bool is_clickable)
void outliner_collection_isolate_flag(Scene *scene, ViewLayer *view_layer, LayerCollection *layer_collection, Collection *collection, PropertyRNA *layer_or_collection_prop, const char *propname, const bool value)
void draw_outliner(const bContext *C)
static void restrictbutton_bone_select_fn(bContext *C, void *UNUSED(poin), void *poin2)
static void outliner_draw_warning_tree_element(uiBlock *block, const SpaceOutliner *space_outliner, StringRefNull warning_msg, const bool use_mode_column, const int te_ys)
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
static void outliner_draw_tree(bContext *C, uiBlock *block, const TreeViewContext *tvc, ARegion *region, SpaceOutliner *space_outliner, const float right_column_width, const bool use_mode_column, const bool use_warning_column, TreeElement **te_edit)
static bool is_object_data_in_editmode(const ID *id, const Object *obact)
static void namebutton_fn(bContext *C, void *tsep, char *oldname)
static void outliner_draw_iconrow_doit(uiBlock *block, TreeElement *te, const uiFontStyle *fstyle, int xmax, int *offsx, int ys, float alpha_fac, const eOLDrawState active, const int num_elements)
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *region, const float restrict_column_width, TreeElement *te)
static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_flag)
#define SEARCHING_OUTLINER(sov)
#define OL_RNA_COL_SPACEX
void outliner_viewcontext_init(const struct bContext *C, TreeViewContext *tvc)
eOLDrawState tree_element_active_state_get(const TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
#define OL_RNA_COLX
@ TE_CHILD_NOT_IN_COLLECTION
@ TE_ICONROW_MERGED
@ TE_ICONROW
@ TE_PRETEND_HAS_CHILDREN
@ TE_ACTIVE
@ TE_DRAGGING
#define OL_Y_OFFSET
@ OL_SETSEL_NORMAL
float outliner_right_columns_width(const struct SpaceOutliner *space_outliner)
TreeElement * outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
void tree_element_activate(struct bContext *C, const TreeViewContext *tvc, TreeElement *te, eOLSetState set, bool handle_all_types)
void outliner_sync_selection(const struct bContext *C, struct SpaceOutliner *space_outliner)
void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct ViewLayer *view_layer, struct SpaceOutliner *space_outliner, struct ARegion *region)
eOLDrawState
@ OL_DRAWSEL_ACTIVE
@ OL_DRAWSEL_NORMAL
@ OL_DRAWSEL_NONE
bool outliner_has_element_warnings(const SpaceOutliner &space_outliner)
#define OL_NAMEBUTTON
void outliner_item_mode_toggle(struct bContext *C, TreeViewContext *tvc, TreeElement *te, bool do_extend)
#define TREESTORE(a)
bool outliner_is_element_in_view(const TreeElement *te, const struct View2D *v2d)
#define OL_RNA_COL_SIZEX
#define OL_TOG_USER_BUTS_STATUS
bool outliner_shows_mode_column(const SpaceOutliner &space_outliner)
#define OL_TOG_USER_BUTS_USERS
#define TSELEM_OPEN(telm, sv)
eOLDrawState tree_element_type_active_state_get(const struct bContext *C, const struct TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:655
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
bool RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
Definition: rna_access.c:2379
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2153
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
Definition: rna_access.c:806
int RNA_struct_ui_icon(const StructRNA *type)
Definition: rna_access.c:601
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
Definition: rna_access.c:2180
struct Object * object
ListBase childbase
struct Collection * collection
char name[64]
Definition: BKE_armature.h:43
unsigned int flag
Definition: DNA_ID.h:312
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
int us
Definition: DNA_ID.h:388
IDOverrideLibrary * override_library
Definition: DNA_ID.h:412
short flag
Definition: DNA_ID.h:383
unsigned int session_uuid
Definition: DNA_ID.h:407
char name[66]
Definition: DNA_ID.h:378
ListBase layer_collections
struct Collection * collection
short type
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase objects
Definition: BKE_main.h:170
TreeElement * tree_element[INDEX_ID_MAX+OB_TYPE_MAX]
int num_elements[INDEX_ID_MAX+OB_TYPE_MAX]
eOLDrawState active[INDEX_ID_MAX+OB_TYPE_MAX]
short transflag
struct Collection * instance_collection
struct bPose * pose
ListBase modifiers
ListBase greasepencil_modifiers
struct PartDeflect * pd
char empty_drawtype
void * data
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
PropertyRNA * layer_collection_holdout
PropertyRNA * object_hide_viewport
PropertyRNA * modifier_show_viewport
PropertyRNA * collection_hide_viewport
PropertyRNA * layer_collection_hide_viewport
PropertyRNA * bone_hide_viewport
PropertyRNA * modifier_show_render
PropertyRNA * layer_collection_exclude
PropertyRNA * base_hide_viewport
PropertyRNA * object_hide_render
PropertyRNA * object_hide_select
PropertyRNA * constraint_enable
PropertyRNA * collection_hide_select
PropertyRNA * collection_hide_render
PropertyRNA * layer_collection_indirect_only
struct Collection * master_collection
struct ToolSettings * toolsettings
char search_string[64]
short lib_override_view_mode
struct BLI_mempool * treestore
int flags
char * filepath
unsigned char color[4]
struct TreeElement * parent
std::unique_ptr< outliner::AbstractTreeElement > abstract_element
ListBase subtree
TreeStoreElem * store_elem
const char * name
struct Scene * scene
struct ViewLayer * view_layer
short flag
ListBase layer_collections
ListBase * edbo
ListBase layers
struct bNodeTreeType * typeinfo
struct Bone * bone
ListBase agroups
ThemeCollectionColor collection_color[8]
float xmax
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
uint8_t modifier
Definition: WM_types.h:693
struct wmEvent * eventstate
Establish and manage Outliner trees for different display modes.
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)