Blender  V3.3
outliner_select.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 <cstdlib>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_armature_types.h"
13 #include "DNA_collection_types.h"
15 #include "DNA_gpencil_types.h"
16 #include "DNA_modifier_types.h"
17 #include "DNA_object_types.h"
18 #include "DNA_scene_types.h"
19 #include "DNA_sequence_types.h"
20 #include "DNA_shader_fx_types.h"
21 #include "DNA_text_types.h"
22 
23 #include "BLI_listbase.h"
24 #include "BLI_utildefines.h"
25 
26 #include "BKE_armature.h"
27 #include "BKE_collection.h"
28 #include "BKE_constraint.h"
29 #include "BKE_context.h"
30 #include "BKE_deform.h"
31 #include "BKE_gpencil.h"
32 #include "BKE_gpencil_modifier.h"
33 #include "BKE_layer.h"
34 #include "BKE_lib_id.h"
35 #include "BKE_main.h"
36 #include "BKE_modifier.h"
37 #include "BKE_object.h"
38 #include "BKE_particle.h"
39 #include "BKE_report.h"
40 #include "BKE_shader_fx.h"
41 
42 #include "DEG_depsgraph.h"
43 #include "DEG_depsgraph_build.h"
44 
45 #include "ED_armature.h"
46 #include "ED_buttons.h"
47 #include "ED_object.h"
48 #include "ED_outliner.h"
49 #include "ED_screen.h"
50 #include "ED_select_utils.h"
51 #include "ED_sequencer.h"
52 #include "ED_text.h"
53 #include "ED_undo.h"
54 
55 #include "SEQ_select.h"
56 #include "SEQ_sequencer.h"
57 
58 #include "WM_api.h"
59 #include "WM_types.h"
60 
61 #include "UI_interface.h"
62 #include "UI_view2d.h"
63 
64 #include "RNA_access.h"
65 #include "RNA_define.h"
66 #include "RNA_prototypes.h"
67 
68 #include "outliner_intern.hh"
69 #include "tree/tree_display.hh"
70 #include "tree/tree_element_seq.hh"
71 #include "tree/tree_iterator.hh"
72 
73 using namespace blender::ed::outliner;
74 
75 /* -------------------------------------------------------------------- */
85 {
86  Main *bmain = CTX_data_main(C);
87  Object *ob = base->object;
88 
89  bool changed = false;
90  if (BKE_object_is_in_editmode(ob)) {
91  changed = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
92  if (changed) {
95  }
96  }
97  else {
99  if (changed) {
102  }
103  }
104 
105  if (changed) {
108  ED_undo_push(C, "Outliner Edit Mode Toggle");
109  }
110 }
111 
118 {
119  Main *bmain = CTX_data_main(C);
120  Object *ob = base->object;
121 
122  if (!BKE_id_is_editable(CTX_data_main(C), &ob->id)) {
123  BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose non-editable data");
124  return;
125  }
126 
127  bool changed = false;
128  if (ob->mode & OB_MODE_POSE) {
129  changed = ED_object_posemode_exit_ex(bmain, ob);
130  if (changed) {
133  }
134  }
135  else {
136  changed = ED_object_posemode_enter_ex(bmain, ob);
137  if (changed) {
140  }
141  }
142 
143  if (changed) {
146  ED_undo_push(C, "Outliner Pose Mode Toggle");
147  }
148 }
149 
162 {
163  const eObjectMode active_mode = (eObjectMode)tvc->obact->mode;
165 
167  Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact);
168  if (base_active != base) {
172  ED_undo_push(C, "Change Active");
173 
174  /* Operator call does undo push. */
175  ED_object_mode_set(C, active_mode);
177  }
178  }
180 }
181 
183  TreeViewContext *tvc,
184  TreeElement *te,
185  const bool do_extend)
186 {
187  TreeStoreElem *tselem = TREESTORE(te);
188 
189  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
190  Object *ob = (Object *)tselem->id;
191  Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
192 
193  /* Hidden objects can be removed from the mode. */
194  if (!base || (!(base->flag & BASE_VISIBLE_DEPSGRAPH) && (ob->mode != tvc->obact->mode))) {
195  return;
196  }
197 
198  if (!do_extend) {
200  }
201  else if (tvc->ob_edit && OB_TYPE_SUPPORT_EDITMODE(ob->type)) {
203  }
204  else if (tvc->ob_pose && ob->type == OB_ARMATURE) {
206  }
207  }
208 }
209 
212 /* -------------------------------------------------------------------- */
217 {
218  /* paranoia check */
219  if (te->idcode != ID_SCE) {
220  return;
221  }
222 
223  ViewLayer *view_layer = reinterpret_cast<ViewLayer *>(te->directdata);
224  wmWindow *win = CTX_wm_window(C);
226 
227  if (BLI_findindex(&scene->view_layers, view_layer) != -1) {
228  WM_window_set_active_view_layer(win, view_layer);
230  }
231 }
232 
237  Object *ob_parent,
238  bool select)
239 {
240  Base *base;
241 
242  for (base = reinterpret_cast<Base *>(FIRSTBASE(view_layer)); base; base = base->next) {
243  Object *ob = base->object;
244  if ((((base->flag & BASE_VISIBLE_DEPSGRAPH) != 0) &&
245  BKE_object_is_child_recursive(ob_parent, ob))) {
247  }
248  }
249 }
250 
251 static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select)
252 {
253  LISTBASE_FOREACH (Bone *, bone, &bone_parent->childbase) {
254  if (select && PBONE_SELECTABLE(arm, bone)) {
255  bone->flag |= BONE_SELECTED;
256  }
257  else {
258  bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
259  }
261  }
262 }
263 
264 static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select)
265 {
266  EditBone *ebone;
267  for (ebone = ebone_parent->next; ebone; ebone = ebone->next) {
268  if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
269  if (select && EBONE_SELECTABLE(arm, ebone)) {
271  }
272  else {
273  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
274  }
275  }
276  }
277 }
278 
280  Scene *scene,
281  ViewLayer *view_layer,
282  TreeElement *te,
283  const eOLSetState set,
284  bool recursive)
285 {
286  TreeStoreElem *tselem = TREESTORE(te);
287  TreeStoreElem *parent_tselem = nullptr;
288  TreeElement *parent_te = nullptr;
289  Scene *sce;
290  Base *base;
291  Object *ob = nullptr;
292 
293  /* if id is not object, we search back */
294  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
295  ob = (Object *)tselem->id;
296  }
297  else {
298  parent_te = outliner_search_back_te(te, ID_OB);
299  if (parent_te) {
300  parent_tselem = TREESTORE(parent_te);
301  ob = (Object *)parent_tselem->id;
302 
303  /* Don't return when activating children of the previous active object. */
304  if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) {
305  return;
306  }
307  }
308  }
309  if (ob == nullptr) {
310  return;
311  }
312 
313  sce = (Scene *)outliner_search_back(te, ID_SCE);
314  if (sce && scene != sce) {
317  scene = sce;
318  }
319 
320  /* find associated base in current scene */
321  base = BKE_view_layer_base_find(view_layer, ob);
322 
324  if (base != nullptr) {
325  Object *obact = OBACT(view_layer);
326  const eObjectMode object_mode = obact ? (eObjectMode)obact->mode : OB_MODE_OBJECT;
327  if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
328  if (object_mode == OB_MODE_OBJECT) {
329  struct Main *bmain = CTX_data_main(C);
332  }
333  if (!BKE_object_is_mode_compat(base->object, object_mode)) {
334  base = nullptr;
335  }
336  }
337  }
338  }
339 
340  if (base) {
341  if (set == OL_SETSEL_EXTEND) {
342  /* swap select */
343  if (base->flag & BASE_SELECTED) {
345  if (parent_tselem) {
346  parent_tselem->flag &= ~TSE_SELECTED;
347  }
348  }
349  else {
351  if (parent_tselem) {
352  parent_tselem->flag |= TSE_SELECTED;
353  }
354  }
355  }
356  else {
357  /* De-select all. */
358 
359  /* Only in object mode so we can switch the active object,
360  * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode.
361  * This keeps the convention that all objects in the current mode are also selected.
362  * see T55246. */
364  (ob->mode == OB_MODE_OBJECT) :
365  true) {
367  }
369  if (parent_tselem) {
370  parent_tselem->flag |= TSE_SELECTED;
371  }
372  }
373 
374  if (recursive) {
375  /* Recursive select/deselect for Object hierarchies */
376  do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0);
377  }
378 
379  if (set != OL_SETSEL_NONE) {
380  ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
383  }
384  }
385 }
386 
388 {
389  /* we search for the object parent */
390  Object *ob = (Object *)outliner_search_back(te, ID_OB);
391  /* Note : ob->matbits can be nullptr when a local object points to a library mesh. */
392  if (ob == nullptr || ob != OBACT(view_layer) || ob->matbits == nullptr) {
393  return; /* just paranoia */
394  }
395 
396  /* In ob mat array? */
397  TreeElement *tes = te->parent;
398  if (tes->idcode == ID_OB) {
399  ob->actcol = te->index + 1;
400  ob->matbits[te->index] = 1; /* Make ob material active too. */
401  }
402  else {
403  /* or in obdata material */
404  ob->actcol = te->index + 1;
405  ob->matbits[te->index] = 0; /* Make obdata material active too. */
406  }
407 
408  /* Tagging object for update seems a bit stupid here, but looks like we have to do it
409  * for render views to update. See T42973.
410  * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
413 }
414 
416 {
417  Object *ob = (Object *)outliner_search_back(te, ID_OB);
418 
419  scene->camera = ob;
420 
421  Main *bmain = CTX_data_main(C);
422  wmWindowManager *wm = reinterpret_cast<wmWindowManager *>(bmain->wm.first);
423 
424  WM_windows_scene_data_sync(&wm->windows, scene);
428 }
429 
431 {
432  Scene *sce = nullptr;
433 
434  TreeElement *tep = te->parent;
435  if (tep) {
436  TreeStoreElem *tselem = TREESTORE(tep);
437  if (tselem->type == TSE_SOME_ID) {
438  sce = (Scene *)tselem->id;
439  }
440  }
441 
442  /* make new scene active */
443  if (sce && scene != sce) {
445  }
446 }
447 
449 {
450  /* id in tselem is object */
451  Object *ob = (Object *)tselem->id;
452  BLI_assert(te->index + 1 >= 0);
454 
457 }
458 
460 {
461  bGPdata *gpd = (bGPdata *)tselem->id;
462  bGPDlayer *gpl = reinterpret_cast<bGPDlayer *>(te->directdata);
463 
464  /* We can only have a single "active" layer at a time
465  * and there must always be an active layer... */
466  if (gpl) {
470  }
471 }
472 
474 {
475  Object *ob = (Object *)tselem->id;
476  if (ob->pose) {
477  ob->pose->active_group = te->index + 1;
479  }
480 }
481 
483  ViewLayer *view_layer,
484  TreeElement *te,
485  TreeStoreElem *tselem,
486  const eOLSetState set,
487  bool recursive)
488 {
489  Object *ob = (Object *)tselem->id;
490  bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
491  bPoseChannel *pchan = reinterpret_cast<bPoseChannel *>(te->directdata);
492 
493  if (!(pchan->bone->flag & BONE_HIDDEN_P)) {
494  if (set != OL_SETSEL_EXTEND) {
495  /* Single select forces all other bones to get unselected. */
496  uint objects_len = 0;
497  Object **objects = BKE_object_pose_array_get_unique(view_layer, nullptr, &objects_len);
498 
499  for (uint object_index = 0; object_index < objects_len; object_index++) {
500  Object *ob_iter = BKE_object_pose_armature_get(objects[object_index]);
501 
502  /* Sanity checks. */
503  if (ELEM(nullptr, ob_iter, ob_iter->pose, ob_iter->data)) {
504  continue;
505  }
506 
507  LISTBASE_FOREACH (bPoseChannel *, pchannel, &ob_iter->pose->chanbase) {
508  pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
509  }
510 
511  if (ob != ob_iter) {
512  DEG_id_tag_update(reinterpret_cast<ID *>(ob_iter->data), ID_RECALC_SELECT);
513  }
514  }
516  }
517 
518  if ((set == OL_SETSEL_EXTEND) && (pchan->bone->flag & BONE_SELECTED)) {
519  pchan->bone->flag &= ~BONE_SELECTED;
520  }
521  else {
522  pchan->bone->flag |= BONE_SELECTED;
523  arm->act_bone = pchan->bone;
524  }
525 
526  if (recursive) {
527  /* Recursive select/deselect */
529  arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0);
530  }
531 
534  }
535 }
536 
538  ViewLayer *view_layer,
539  TreeElement *te,
540  TreeStoreElem *tselem,
541  const eOLSetState set,
542  bool recursive)
543 {
544  bArmature *arm = (bArmature *)tselem->id;
545  Bone *bone = reinterpret_cast<Bone *>(te->directdata);
546 
547  if (!(bone->flag & BONE_HIDDEN_P)) {
548  Object *ob = OBACT(view_layer);
549  if (ob) {
550  if (set != OL_SETSEL_EXTEND) {
551  /* single select forces all other bones to get unselected */
552  for (Bone *bone_iter = reinterpret_cast<Bone *>(arm->bonebase.first); bone_iter != nullptr;
553  bone_iter = bone_iter->next) {
554  bone_iter->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
555  do_outliner_bone_select_recursive(arm, bone_iter, false);
556  }
557  }
558  }
559 
560  if (set == OL_SETSEL_EXTEND && (bone->flag & BONE_SELECTED)) {
561  bone->flag &= ~BONE_SELECTED;
562  }
563  else {
564  bone->flag |= BONE_SELECTED;
565  arm->act_bone = bone;
566  }
567 
568  if (recursive) {
569  /* Recursive select/deselect */
570  do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0);
571  }
572 
574  }
575 }
576 
578 static void tree_element_active_ebone__sel(bContext *C, bArmature *arm, EditBone *ebone, short sel)
579 {
580  if (sel) {
581  arm->act_edbone = ebone;
582  }
583  ED_armature_ebone_select_set(ebone, sel);
585 }
587  ViewLayer *view_layer,
588  TreeElement *te,
589  TreeStoreElem *tselem,
590  const eOLSetState set,
591  bool recursive)
592 {
593  bArmature *arm = (bArmature *)tselem->id;
594  EditBone *ebone = reinterpret_cast<EditBone *>(te->directdata);
595 
596  if (set == OL_SETSEL_NORMAL) {
597  if (!(ebone->flag & BONE_HIDDEN_A)) {
598  uint bases_len = 0;
599 
600  ObjectsInModeParams ob_params{};
601  ob_params.object_mode = OB_MODE_EDIT;
602  ob_params.no_dup_data = true;
603 
605  view_layer, nullptr, &bases_len, &ob_params);
606  ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
607  MEM_freeN(bases);
608 
609  tree_element_active_ebone__sel(C, arm, ebone, true);
610  }
611  }
612  else if (set == OL_SETSEL_EXTEND) {
613  if (!(ebone->flag & BONE_HIDDEN_A)) {
614  if (!(ebone->flag & BONE_SELECTED)) {
615  tree_element_active_ebone__sel(C, arm, ebone, true);
616  }
617  else {
618  /* entirely selected, so de-select */
619  tree_element_active_ebone__sel(C, arm, ebone, false);
620  }
621  }
622  }
623 
624  if (recursive) {
625  /* Recursive select/deselect */
626  do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
627  }
628 }
629 
631  TreeElement *te,
632  TreeStoreElem *tselem,
633  const eOLSetState set)
634 {
635  Object *ob = (Object *)tselem->id;
636  ModifierData *md = (ModifierData *)te->directdata;
637 
638  if (set == OL_SETSEL_NORMAL) {
641  }
642 }
643 
645 {
646  Object *ob = (Object *)tselem->id;
647 
649 }
650 
652  ViewLayer *view_layer,
653  TreeElement *te,
654  TreeStoreElem *tselem,
655  const eOLSetState set)
656 {
657  Object *ob = (Object *)tselem->id;
658 
659  /* Activate the parent bone if this is a bone constraint. */
660  te = te->parent;
661  while (te) {
662  tselem = TREESTORE(te);
663  if (tselem->type == TSE_POSE_CHANNEL) {
664  tree_element_posechannel_activate(C, view_layer, te, tselem, set, false);
665  return;
666  }
667  te = te->parent;
668  }
669 
671 }
672 
674  Scene *scene,
675  TreeElement *te,
676  const eOLSetState set)
677 {
678  const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
679  Sequence *seq = &te_seq->getSequence();
681 
682  if (BLI_findindex(ed->seqbasep, seq) != -1) {
683  if (set == OL_SETSEL_EXTEND) {
684  SEQ_select_active_set(scene, nullptr);
685  }
687 
688  if ((set == OL_SETSEL_EXTEND) && seq->flag & SELECT) {
689  seq->flag &= ~SELECT;
690  }
691  else {
692  seq->flag |= SELECT;
694  }
695  }
696 
698 }
699 
701 {
703 
704 #if 0
705  select_single_seq(seq, 1);
706 #endif
707  Sequence *p = reinterpret_cast<Sequence *>(ed->seqbasep->first);
708  while (p) {
709  if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
710  p = p->next;
711  continue;
712  }
713 
714 #if 0
715  if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) {
716  select_single_seq(p, 0);
717  }
718 #endif
719  p = p->next;
720  }
721 }
722 
724 {
725  ViewLayer *view_layer = CTX_data_view_layer(C);
726  LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>(
727  view_layer->layer_collections.first);
728  BKE_layer_collection_activate(view_layer, layer_collection);
729  /* A very precise notifier - ND_LAYER alone is quite vague, we want to avoid unnecessary work
730  * when only the active collection changes. */
732 }
733 
735 {
737  LayerCollection *layer_collection = reinterpret_cast<LayerCollection *>(te->directdata);
738  ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
739  BKE_layer_collection_activate(view_layer, layer_collection);
740  /* A very precise notifier - ND_LAYER alone is quite vague, we want to avoid unnecessary work
741  * when only the active collection changes. */
743 }
744 
746 {
747  Text *text = (Text *)te->store_elem->id;
749 }
750 
751 /* ---------------------------------------------- */
752 
754  const TreeViewContext *tvc,
755  TreeElement *te,
756  const eOLSetState set,
757  const bool handle_all_types)
758 {
759  switch (te->idcode) {
763  case ID_OB:
764  if (handle_all_types) {
765  tree_element_object_activate(C, tvc->scene, tvc->view_layer, te, set, false);
766  }
767  break;
768  case ID_MA:
770  break;
771  case ID_WO:
773  break;
774  case ID_CA:
776  break;
777  case ID_TXT:
779  break;
780  }
781 }
782 
784  const TreeViewContext *tvc,
785  TreeElement *te,
786  TreeStoreElem *tselem,
787  const eOLSetState set,
788  bool recursive)
789 {
790  BLI_assert(set != OL_SETSEL_NONE);
791  switch (tselem->type) {
792  case TSE_DEFGROUP:
793  tree_element_defgroup_activate(C, te, tselem);
794  break;
795  case TSE_BONE:
796  tree_element_bone_activate(C, tvc->view_layer, te, tselem, set, recursive);
797  break;
798  case TSE_EBONE:
799  tree_element_ebone_activate(C, tvc->view_layer, te, tselem, set, recursive);
800  break;
801  case TSE_MODIFIER:
802  tree_element_modifier_activate(C, te, tselem, set);
803  break;
804  case TSE_LINKED_OB:
805  tree_element_object_activate(C, tvc->scene, tvc->view_layer, te, set, false);
806  break;
807  case TSE_LINKED_PSYS:
808  tree_element_psys_activate(C, tselem);
809  break;
810  case TSE_POSE_BASE:
811  return;
812  case TSE_POSE_CHANNEL:
813  tree_element_posechannel_activate(C, tvc->view_layer, te, tselem, set, recursive);
814  break;
815  case TSE_CONSTRAINT_BASE:
816  case TSE_CONSTRAINT:
817  tree_element_constraint_activate(C, tvc->view_layer, te, tselem, set);
818  break;
819  case TSE_R_LAYER:
821  break;
822  case TSE_POSEGRP:
823  tree_element_posegroup_activate(C, te, tselem);
824  break;
825  case TSE_SEQUENCE:
826  tree_element_sequence_activate(C, tvc->scene, te, set);
827  break;
828  case TSE_SEQUENCE_DUP:
830  break;
831  case TSE_GP_LAYER:
832  tree_element_gplayer_activate(C, te, tselem);
833  break;
836  break;
839  break;
840  }
841 }
842 
844  const TreeElement *te,
845  const TreeStoreElem *tselem)
846 {
847  const Object *ob = (const Object *)tselem->id;
848  if (ob == OBACT(view_layer)) {
849  if (BKE_object_defgroup_active_index_get(ob) == te->index + 1) {
850  return OL_DRAWSEL_NORMAL;
851  }
852  }
853  return OL_DRAWSEL_NONE;
854 }
855 
857  const TreeElement *te,
858  const TreeStoreElem *tselem)
859 {
860  const bArmature *arm = (const bArmature *)tselem->id;
861  const Bone *bone = reinterpret_cast<Bone *>(te->directdata);
862  const Object *ob = OBACT(view_layer);
863  if (ob && ob->data == arm) {
864  if (bone->flag & BONE_SELECTED) {
865  return OL_DRAWSEL_NORMAL;
866  }
867  }
868  return OL_DRAWSEL_NONE;
869 }
870 
872 {
873  const EditBone *ebone = reinterpret_cast<EditBone *>(te->directdata);
874  if (ebone->flag & BONE_SELECTED) {
875  return OL_DRAWSEL_NORMAL;
876  }
877  return OL_DRAWSEL_NONE;
878 }
879 
881  const TreeStoreElem *tselem)
882 {
883  const Object *ob = (const Object *)tselem->id;
884  const ModifierData *md = (const ModifierData *)te->directdata;
885 
887 }
888 
890  const TreeStoreElem *tselem)
891 {
892  return (tselem->id == (const ID *)tvc->obact) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
893 }
894 
896  const TreeStoreElem *tselem)
897 {
898  const Object *ob = (const Object *)tselem->id;
899  /* This will just lookup in a cache, it will not change the arguments. */
900  const Base *base = BKE_view_layer_base_find((ViewLayer *)view_layer, (Object *)ob);
901  if (base == nullptr) {
902  /* Armature not instantiated in current scene (e.g. inside an appended group). */
903  return OL_DRAWSEL_NONE;
904  }
905 
906  if (ob->mode & OB_MODE_POSE) {
907  return OL_DRAWSEL_NORMAL;
908  }
909  return OL_DRAWSEL_NONE;
910 }
911 
913  const TreeElement *te,
914  const TreeStoreElem *tselem)
915 {
916  const Object *ob = (const Object *)tselem->id;
917  const bPoseChannel *pchan = reinterpret_cast<bPoseChannel *>(te->directdata);
918  if (ob == ob_pose && ob->pose) {
919  if (pchan->bone->flag & BONE_SELECTED) {
920  return OL_DRAWSEL_NORMAL;
921  }
922  }
923  return OL_DRAWSEL_NONE;
924 }
925 
927 {
928  /* paranoia check */
929  if (te->idcode != ID_SCE) {
930  return OL_DRAWSEL_NONE;
931  }
932 
933  const ViewLayer *view_layer = reinterpret_cast<ViewLayer *>(te->directdata);
934 
935  if (CTX_data_view_layer(C) == view_layer) {
936  return OL_DRAWSEL_NORMAL;
937  }
938  return OL_DRAWSEL_NONE;
939 }
940 
942  const TreeElement *te,
943  const TreeStoreElem *tselem)
944 {
945  const Object *ob = (const Object *)tselem->id;
946 
947  if (ob == OBACT(view_layer) && ob->pose) {
948  if (ob->pose->active_group == te->index + 1) {
949  return OL_DRAWSEL_NORMAL;
950  }
951  }
952  return OL_DRAWSEL_NONE;
953 }
954 
956 {
957  const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
958  const Sequence *seq = &te_seq->getSequence();
959  const Editing *ed = scene->ed;
960 
961  if (ed && ed->act_seq == seq && seq->flag & SELECT) {
962  return OL_DRAWSEL_NORMAL;
963  }
964  return OL_DRAWSEL_NONE;
965 }
966 
968 {
969  const TreeElementSequenceStripDuplicate *te_dup =
970  tree_element_cast<TreeElementSequenceStripDuplicate>(te);
971  const Sequence *seq = &te_dup->getSequence();
972  if (seq->flag & SELECT) {
973  return OL_DRAWSEL_NORMAL;
974  }
975  return OL_DRAWSEL_NONE;
976 }
977 
979 {
980  if (((const bGPDlayer *)te->directdata)->flag & GP_LAYER_ACTIVE) {
981  return OL_DRAWSEL_NORMAL;
982  }
983  return OL_DRAWSEL_NONE;
984 }
985 
987 {
988  const ViewLayer *view_layer = CTX_data_view_layer(C);
990 
991  if (active == view_layer->layer_collections.first) {
992  return OL_DRAWSEL_NORMAL;
993  }
994  return OL_DRAWSEL_NONE;
995 }
996 
998  const TreeElement *te)
999 {
1001  if (active == te->directdata) {
1002  return OL_DRAWSEL_NORMAL;
1003  }
1004  return OL_DRAWSEL_NONE;
1005 }
1006 
1008  const TreeElement *te)
1009 {
1010  /* we search for the object parent */
1011  const Object *ob = (const Object *)outliner_search_back((TreeElement *)te, ID_OB);
1012  /* Note : ob->matbits can be nullptr when a local object points to a library mesh. */
1013  if (ob == nullptr || ob != OBACT(view_layer) || ob->matbits == nullptr) {
1014  return OL_DRAWSEL_NONE; /* just paranoia */
1015  }
1016 
1017  /* searching in ob mat array? */
1018  const TreeElement *tes = te->parent;
1019  if (tes->idcode == ID_OB) {
1020  if (ob->actcol == te->index + 1) {
1021  if (ob->matbits[te->index]) {
1022  return OL_DRAWSEL_NORMAL;
1023  }
1024  }
1025  }
1026  /* or we search for obdata material */
1027  else {
1028  if (ob->actcol == te->index + 1) {
1029  if (ob->matbits[te->index] == 0) {
1030  return OL_DRAWSEL_NORMAL;
1031  }
1032  }
1033  }
1034  return OL_DRAWSEL_NONE;
1035 }
1036 
1038  const TreeElement *te,
1039  const TreeStoreElem *tselem)
1040 {
1041  if (te->idcode == ID_SCE) {
1042  if (tselem->id == (ID *)tvc->scene) {
1043  return OL_DRAWSEL_NORMAL;
1044  }
1045  }
1046  return OL_DRAWSEL_NONE;
1047 }
1048 
1050 {
1051  const TreeElement *tep = te->parent;
1052  if (tep == nullptr) {
1053  return OL_DRAWSEL_NORMAL;
1054  }
1055 
1056  const TreeStoreElem *tselem = TREESTORE(tep);
1057  if (tselem->id == (const ID *)scene) {
1058  return OL_DRAWSEL_NORMAL;
1059  }
1060  return OL_DRAWSEL_NONE;
1061 }
1062 
1064 {
1065  const Object *ob = (const Object *)outliner_search_back((TreeElement *)te, ID_OB);
1066 
1067  return (scene->camera == ob) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
1068 }
1069 
1071  const TreeElement *te,
1072  const TreeStoreElem *tselem)
1073 {
1074  switch (te->idcode) {
1075  case ID_SCE:
1076  return tree_element_active_scene_get(tvc, te, tselem);
1077  case ID_OB:
1078  /* Objects are currently handled by the caller in order to also change text color. */
1079  return OL_DRAWSEL_NONE;
1080  break;
1081  case ID_MA:
1083  case ID_WO:
1084  return tree_element_active_world_get(tvc->scene, te);
1085  case ID_CA:
1086  return tree_element_active_camera_get(tvc->scene, te);
1087  }
1088  return OL_DRAWSEL_NONE;
1089 }
1090 
1092  const TreeViewContext *tvc,
1093  const TreeElement *te,
1094  const TreeStoreElem *tselem)
1095 {
1096  switch (tselem->type) {
1097  case TSE_DEFGROUP:
1098  return tree_element_defgroup_state_get(tvc->view_layer, te, tselem);
1099  case TSE_BONE:
1100  return tree_element_bone_state_get(tvc->view_layer, te, tselem);
1101  case TSE_EBONE:
1102  return tree_element_ebone_state_get(te);
1103  case TSE_MODIFIER:
1104  return tree_element_modifier_state_get(te, tselem);
1105  case TSE_LINKED_OB:
1106  return tree_element_object_state_get(tvc, tselem);
1107  case TSE_LINKED_PSYS:
1108  return OL_DRAWSEL_NONE;
1109  case TSE_POSE_BASE:
1110  return tree_element_pose_state_get(tvc->view_layer, tselem);
1111  case TSE_POSE_CHANNEL:
1112  return tree_element_posechannel_state_get(tvc->ob_pose, te, tselem);
1113  case TSE_CONSTRAINT_BASE:
1114  case TSE_CONSTRAINT:
1115  return OL_DRAWSEL_NONE;
1116  case TSE_R_LAYER:
1117  return tree_element_viewlayer_state_get(C, te);
1118  case TSE_POSEGRP:
1119  return tree_element_posegroup_state_get(tvc->view_layer, te, tselem);
1120  case TSE_SEQUENCE:
1121  return tree_element_sequence_state_get(tvc->scene, te);
1122  case TSE_SEQUENCE_DUP:
1124  case TSE_GP_LAYER:
1125  return tree_element_gplayer_state_get(te);
1128  case TSE_LAYER_COLLECTION:
1130  }
1131  return OL_DRAWSEL_NONE;
1132 }
1133 
1135 {
1136  TreeStoreElem *tselem;
1137 
1138  te = te->parent;
1139  while (te) {
1140  tselem = TREESTORE(te);
1141  if (tselem->type == TSE_POSE_CHANNEL) {
1142  *r_bone_te = te;
1143  return (bPoseChannel *)te->directdata;
1144  }
1145  te = te->parent;
1146  }
1147 
1148  return nullptr;
1149 }
1150 
1152  PointerRNA *ptr,
1153  const int context)
1154 {
1155  bScreen *screen = CTX_wm_screen(C);
1156 
1157  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1158  if (area->spacetype != SPACE_PROPERTIES) {
1159  continue;
1160  }
1161 
1162  SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first;
1164  ED_buttons_set_context(C, sbuts, ptr, context);
1165  }
1166  }
1167 }
1168 
1170 {
1171  PointerRNA ptr = {nullptr};
1172  int context = 0;
1173 
1174  /* ID Types */
1175  if (tselem->type == TSE_SOME_ID) {
1176  RNA_id_pointer_create(tselem->id, &ptr);
1177 
1178  switch (te->idcode) {
1179  case ID_SCE:
1181  break;
1182  case ID_OB:
1184  break;
1185  case ID_ME:
1186  case ID_CU_LEGACY:
1187  case ID_MB:
1188  case ID_IM:
1189  case ID_LT:
1190  case ID_LA:
1191  case ID_CA:
1192  case ID_KE:
1193  case ID_SPK:
1194  case ID_AR:
1195  case ID_GD:
1196  case ID_LP:
1197  case ID_CV:
1198  case ID_PT:
1199  case ID_VO:
1201  break;
1202  case ID_MA:
1204  break;
1205  case ID_WO:
1207  break;
1208  }
1209  }
1210  else {
1211  switch (tselem->type) {
1212  case TSE_DEFGROUP_BASE:
1213  case TSE_DEFGROUP:
1214  RNA_id_pointer_create(tselem->id, &ptr);
1216  break;
1217  case TSE_CONSTRAINT_BASE:
1218  case TSE_CONSTRAINT: {
1219  TreeElement *bone_te = nullptr;
1220  bPoseChannel *pchan = outliner_find_parent_bone(te, &bone_te);
1221 
1222  if (pchan) {
1223  RNA_pointer_create(TREESTORE(bone_te)->id, &RNA_PoseBone, pchan, &ptr);
1225  }
1226  else {
1227  RNA_id_pointer_create(tselem->id, &ptr);
1229  }
1230 
1231  /* Expand the selected constraint in the properties editor. */
1232  if (tselem->type != TSE_CONSTRAINT_BASE) {
1233  BKE_constraint_panel_expand(reinterpret_cast<bConstraint *>(te->directdata));
1234  }
1235  break;
1236  }
1237  case TSE_MODIFIER_BASE:
1238  case TSE_MODIFIER:
1239  RNA_id_pointer_create(tselem->id, &ptr);
1241 
1242  if (tselem->type != TSE_MODIFIER_BASE) {
1243  Object *ob = (Object *)tselem->id;
1244 
1245  if (ob->type == OB_GPENCIL) {
1247  reinterpret_cast<GpencilModifierData *>(te->directdata));
1248  }
1249  else {
1250  ModifierData *md = (ModifierData *)te->directdata;
1251 
1252  switch ((ModifierType)md->type) {
1255  break;
1256  case eModifierType_Cloth:
1261  case eModifierType_Fluid:
1263  break;
1264  default:
1265  break;
1266  }
1267 
1268  if (context == BCONTEXT_MODIFIER) {
1270  }
1271  }
1272  }
1273  break;
1275  case TSE_GPENCIL_EFFECT:
1276  RNA_id_pointer_create(tselem->id, &ptr);
1278 
1279  if (tselem->type != TSE_GPENCIL_EFFECT_BASE) {
1280  BKE_shaderfx_panel_expand(reinterpret_cast<ShaderFxData *>(te->directdata));
1281  }
1282  break;
1283  case TSE_BONE: {
1284  bArmature *arm = (bArmature *)tselem->id;
1285  Bone *bone = reinterpret_cast<Bone *>(te->directdata);
1286 
1287  RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr);
1289  break;
1290  }
1291  case TSE_EBONE: {
1292  bArmature *arm = (bArmature *)tselem->id;
1293  EditBone *ebone = reinterpret_cast<EditBone *>(te->directdata);
1294 
1295  RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &ptr);
1297  break;
1298  }
1299  case TSE_POSE_CHANNEL: {
1300  Object *ob = (Object *)tselem->id;
1301  bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
1302  bPoseChannel *pchan = reinterpret_cast<bPoseChannel *>(te->directdata);
1303 
1304  RNA_pointer_create(&arm->id, &RNA_PoseBone, pchan, &ptr);
1306  break;
1307  }
1308  case TSE_POSE_BASE: {
1309  Object *ob = (Object *)tselem->id;
1310  bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
1311 
1312  RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr);
1314  break;
1315  }
1316  case TSE_R_LAYER_BASE:
1317  case TSE_R_LAYER: {
1318  ViewLayer *view_layer = reinterpret_cast<ViewLayer *>(te->directdata);
1319 
1320  RNA_pointer_create(tselem->id, &RNA_ViewLayer, view_layer, &ptr);
1322  break;
1323  }
1324  case TSE_POSEGRP_BASE:
1325  case TSE_POSEGRP: {
1326  Object *ob = (Object *)tselem->id;
1327  bArmature *arm = reinterpret_cast<bArmature *>(ob->data);
1328 
1329  RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr);
1331  break;
1332  }
1333  case TSE_LINKED_PSYS: {
1334  Object *ob = (Object *)tselem->id;
1335  ParticleSystem *psys = psys_get_current(ob);
1336 
1337  RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &ptr);
1339  break;
1340  }
1341  case TSE_GP_LAYER:
1342  RNA_id_pointer_create(tselem->id, &ptr);
1344  break;
1345  }
1346  }
1347 
1348  if (ptr.data) {
1350  }
1351 }
1352 
1353 /* ================================================ */
1354 
1362  const TreeViewContext *tvc,
1363  SpaceOutliner *space_outliner,
1364  TreeElement *te,
1365  TreeStoreElem *tselem,
1366  const bool extend,
1367  const bool recursive,
1368  const bool do_activate_data)
1369 {
1370  /* Always makes active object, except for some specific types. */
1371  if (ELEM(tselem->type,
1372  TSE_SEQUENCE,
1373  TSE_SEQ_STRIP,
1375  TSE_EBONE,
1377  /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several
1378  * objects, we do not want to switch out of edit mode (see T48328 for details). */
1379  }
1380  else if (do_activate_data) {
1382  tvc->scene,
1383  tvc->view_layer,
1384  te,
1385  (extend && tselem->type == TSE_SOME_ID) ? OL_SETSEL_EXTEND :
1387  recursive && tselem->type == TSE_SOME_ID);
1388  }
1389 
1390  if (tselem->type == TSE_SOME_ID) { /* The lib blocks. */
1391  if (do_activate_data == false) {
1392  /* Only select in outliner. */
1393  }
1394  else if (te->idcode == ID_SCE) {
1395  if (tvc->scene != (Scene *)tselem->id) {
1397  }
1398  }
1399  else if ((te->idcode == ID_GR) && (space_outliner->outlinevis != SO_VIEW_LAYER)) {
1400  Collection *gr = (Collection *)tselem->id;
1401 
1402  if (extend) {
1405  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1406  if (base && (base->flag & BASE_SELECTED)) {
1407  sel = BA_DESELECT;
1408  break;
1409  }
1410  }
1412 
1414  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1415  if (base) {
1416  ED_object_base_select(base, sel);
1417  }
1418  }
1420  }
1421  else {
1423 
1425  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1426  /* Object may not be in this scene */
1427  if (base != nullptr) {
1428  if ((base->flag & BASE_SELECTED) == 0) {
1430  }
1431  }
1432  }
1434  }
1435 
1438  }
1439  else { /* Rest of types. */
1440  tree_element_activate(C, tvc, te, OL_SETSEL_NORMAL, false);
1441  }
1442  }
1443  else if (do_activate_data) {
1445  C, tvc, te, tselem, extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive);
1446  }
1447 }
1448 
1450  SpaceOutliner *space_outliner,
1451  TreeElement *te,
1452  const short select_flag)
1453 {
1454  TreeStoreElem *tselem = TREESTORE(te);
1455  const bool activate = select_flag & OL_ITEM_ACTIVATE;
1456  const bool extend = select_flag & OL_ITEM_EXTEND;
1457  const bool activate_data = select_flag & OL_ITEM_SELECT_DATA;
1458 
1459  /* Clear previous active when activating and clear selection when not extending selection */
1460  const short clear_flag = (activate ? TSE_ACTIVE : 0) | (extend ? 0 : TSE_SELECTED);
1461  if (clear_flag) {
1462  outliner_flag_set(*space_outliner, clear_flag, false);
1463  }
1464 
1465  if (select_flag & OL_ITEM_SELECT) {
1466  tselem->flag |= TSE_SELECTED;
1467  }
1468  else {
1469  tselem->flag &= ~TSE_SELECTED;
1470  }
1471 
1472  if (activate) {
1473  TreeViewContext tvc;
1475 
1476  tselem->flag |= TSE_ACTIVE;
1478  &tvc,
1479  space_outliner,
1480  te,
1481  tselem,
1482  extend,
1483  select_flag & OL_ITEM_RECURSIVE,
1484  activate_data || space_outliner->flag & SO_SYNC_SELECT);
1485  }
1486 }
1487 
1490  TreeElement *cursor,
1491  bool selecting)
1492 {
1493  LISTBASE_FOREACH (TreeElement *, te, lb) {
1494  TreeStoreElem *tselem = TREESTORE(te);
1495 
1496  if (selecting) {
1497  tselem->flag |= TSE_SELECTED;
1498  }
1499 
1500  /* Set state for selection */
1501  if (ELEM(te, active, cursor)) {
1502  selecting = !selecting;
1503  }
1504 
1505  if (selecting) {
1506  tselem->flag |= TSE_SELECTED;
1507  }
1508 
1509  /* Don't look inside closed elements */
1510  if (!(tselem->flag & TSE_CLOSED)) {
1511  selecting = do_outliner_range_select_recursive(&te->subtree, active, cursor, selecting);
1512  }
1513  }
1514 
1515  return selecting;
1516 }
1517 
1518 /* Select a range of items between cursor and active element */
1520  SpaceOutliner *space_outliner,
1521  TreeElement *cursor,
1522  const bool extend)
1523 {
1525 
1526  /* If no active element exists, activate the element under the cursor */
1527  if (!active) {
1528  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
1529  return;
1530  }
1531 
1532  TreeStoreElem *tselem = TREESTORE(active);
1533  const bool active_selected = (tselem->flag & TSE_SELECTED);
1534 
1535  if (!extend) {
1536  outliner_flag_set(*space_outliner, TSE_SELECTED, false);
1537  }
1538 
1539  /* Select active if under cursor */
1540  if (active == cursor) {
1541  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT);
1542  return;
1543  }
1544 
1545  /* If active is not selected or visible, select and activate the element under the cursor */
1546  if (!active_selected || !outliner_is_element_visible(active)) {
1547  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
1548  return;
1549  }
1550 
1551  do_outliner_range_select_recursive(&space_outliner->tree, active, cursor, false);
1552 }
1553 
1554 static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *space_outliner,
1555  const ARegion *region,
1556  float view_co_x)
1557 {
1558  return (view_co_x > region->v2d.cur.xmax - outliner_right_columns_width(space_outliner));
1559 }
1560 
1561 bool outliner_is_co_within_mode_column(SpaceOutliner *space_outliner, const float view_mval[2])
1562 {
1563  if (!outliner_shows_mode_column(*space_outliner)) {
1564  return false;
1565  }
1566 
1567  return view_mval[0] < UI_UNIT_X;
1568 }
1569 
1571  SpaceOutliner *space_outliner,
1572  const float view_mval[2])
1573 {
1574  ViewLayer *view_layer = CTX_data_view_layer(C);
1575  Object *obact = OBACT(view_layer);
1576 
1577  return outliner_is_co_within_mode_column(space_outliner, view_mval) && obact &&
1578  obact->mode != OB_MODE_OBJECT;
1579 }
1580 
1587  const int mval[2],
1588  const bool extend,
1589  const bool use_range,
1590  const bool deselect_all)
1591 {
1592  ARegion *region = CTX_wm_region(C);
1593  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1594  TreeElement *te;
1595  float view_mval[2];
1596  bool changed = false, rebuild_tree = false;
1597 
1598  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
1599 
1600  if (outliner_is_co_within_restrict_columns(space_outliner, region, view_mval[0])) {
1601  return OPERATOR_CANCELLED;
1602  }
1603  if (outliner_is_co_within_active_mode_column(C, space_outliner, view_mval)) {
1604  return OPERATOR_CANCELLED;
1605  }
1606 
1607  if (!(te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]))) {
1608  if (deselect_all) {
1609  changed |= outliner_flag_set(*space_outliner, TSE_SELECTED, false);
1610  }
1611  }
1612  /* Don't allow toggle on scene collection */
1613  else if ((TREESTORE(te)->type != TSE_VIEW_COLLECTION_BASE) &&
1614  outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
1616  }
1617  else {
1618  /* The row may also contain children, if one is hovered we want this instead of current te. */
1619  bool merged_elements = false;
1620  bool is_over_icon = false;
1622  space_outliner, te, view_mval[0], &merged_elements, &is_over_icon);
1623 
1624  /* If the selected icon was an aggregate of multiple elements, run the search popup */
1625  if (merged_elements) {
1626  merged_element_search_menu_invoke(C, te, activate_te);
1627  return OPERATOR_CANCELLED;
1628  }
1629 
1630  TreeStoreElem *activate_tselem = TREESTORE(activate_te);
1631 
1632  if (use_range) {
1633  do_outliner_range_select(C, space_outliner, activate_te, extend);
1634  }
1635  else {
1636  const bool is_over_name_icons = outliner_item_is_co_over_name_icons(activate_te,
1637  view_mval[0]);
1638  /* Always select unless already active and selected */
1639  const bool select = !extend || !(activate_tselem->flag & TSE_ACTIVE &&
1640  activate_tselem->flag & TSE_SELECTED);
1641 
1642  const short select_flag = OL_ITEM_ACTIVATE | (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) |
1643  (is_over_name_icons ? OL_ITEM_SELECT_DATA : 0) |
1644  (extend ? OL_ITEM_EXTEND : 0);
1645 
1646  outliner_item_select(C, space_outliner, activate_te, select_flag);
1647 
1648  /* Only switch properties editor tabs when icons are selected. */
1649  if (is_over_icon) {
1650  outliner_set_properties_tab(C, activate_te, activate_tselem);
1651  }
1652  }
1653 
1654  changed = true;
1655  }
1656 
1657  if (!changed) {
1658  return OPERATOR_CANCELLED;
1659  }
1660 
1661  if (rebuild_tree) {
1662  ED_region_tag_redraw(region);
1663  }
1664  else {
1666  }
1667 
1668  ED_outliner_select_sync_from_outliner(C, space_outliner);
1669 
1670  return OPERATOR_FINISHED;
1671 }
1672 
1673 /* Event can enter-key, then it opens/closes. */
1675 {
1676  ARegion *region = CTX_wm_region(C);
1677 
1678  const bool extend = RNA_boolean_get(op->ptr, "extend");
1679  const bool use_range = RNA_boolean_get(op->ptr, "extend_range");
1680  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1681 
1682  int mval[2];
1683  WM_event_drag_start_mval(event, region, mval);
1684  return outliner_item_do_activate_from_cursor(C, mval, extend, use_range, deselect_all);
1685 }
1686 
1688 {
1689  ot->name = "Select";
1690  ot->idname = "OUTLINER_OT_item_activate";
1691  ot->description = "Handle mouse clicks to select and activate items";
1692 
1694 
1696 
1698 
1699  PropertyRNA *prop;
1700  prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection for activation");
1702  prop = RNA_def_boolean(
1703  ot->srna, "extend_range", false, "Extend Range", "Select a range from active element");
1705 
1706  prop = RNA_def_boolean(ot->srna,
1707  "deselect_all",
1708  false,
1709  "Deselect On Nothing",
1710  "Deselect all when nothing under the cursor");
1712 }
1713 
1716 /* -------------------------------------------------------------------- */
1721  SpaceOutliner *space_outliner,
1722  const rctf *rectf,
1723  const bool select)
1724 {
1725  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
1726  if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
1727  outliner_item_select(
1728  C, space_outliner, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND);
1729  }
1730  });
1731 }
1732 
1734 {
1736  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1737  ARegion *region = CTX_wm_region(C);
1738  rctf rectf;
1739 
1740  const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode");
1741  const bool select = (sel_op != SEL_OP_SUB);
1742  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
1743  outliner_flag_set(*space_outliner, TSE_SELECTED, 0);
1744  }
1745 
1747  UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
1748 
1749  outliner_box_select(C, space_outliner, &rectf, select);
1750 
1754 
1755  ED_outliner_select_sync_from_outliner(C, space_outliner);
1756 
1757  return OPERATOR_FINISHED;
1758 }
1759 
1760 static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1761 {
1762  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1763  ARegion *region = CTX_wm_region(C);
1764  float view_mval[2];
1765  const bool tweak = RNA_boolean_get(op->ptr, "tweak");
1766 
1767  int mval[2];
1768  WM_event_drag_start_mval(event, region, mval);
1769  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
1770 
1771  /* Find element clicked on */
1772  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
1773 
1774  /* Pass through if click is over name or icons, or not tweak event */
1775  if (te && tweak && outliner_item_is_co_over_name_icons(te, view_mval[0])) {
1777  }
1778 
1779  if (outliner_is_co_within_active_mode_column(C, space_outliner, view_mval)) {
1781  }
1782 
1783  return WM_gesture_box_invoke(C, op, event);
1784 }
1785 
1787 {
1788  /* identifiers */
1789  ot->name = "Box Select";
1790  ot->idname = "OUTLINER_OT_select_box";
1791  ot->description = "Use box selection to select tree elements";
1792 
1793  /* api callbacks */
1798 
1800 
1801  /* flags */
1803 
1804  /* properties */
1805  PropertyRNA *prop;
1806 
1807  prop = RNA_def_boolean(
1808  ot->srna, "tweak", false, "Tweak", "Tweak gesture from empty space for box selection");
1810 
1813 }
1814 
1817 /* -------------------------------------------------------------------- */
1821 /* Given a tree element return the rightmost child that is visible in the outliner */
1823  TreeElement *te)
1824 {
1825  while (te->subtree.last) {
1826  if (TSELEM_OPEN(TREESTORE(te), space_outliner)) {
1827  te = reinterpret_cast<TreeElement *>(te->subtree.last);
1828  }
1829  else {
1830  break;
1831  }
1832  }
1833  return te;
1834 }
1835 
1836 /* Find previous visible element in the tree. */
1838 {
1839  if (te->prev) {
1840  te = outliner_find_rightmost_visible_child(space_outliner, te->prev);
1841  }
1842  else if (te->parent) {
1843  /* Use parent if at beginning of list */
1844  te = te->parent;
1845  }
1846 
1847  return te;
1848 }
1849 
1850 /* Recursively search up the tree until a successor to a given element is found */
1852 {
1853  TreeElement *successor = te;
1854  while (successor->parent) {
1855  if (successor->parent->next) {
1856  te = successor->parent->next;
1857  break;
1858  }
1859  successor = successor->parent;
1860  }
1861 
1862  return te;
1863 }
1864 
1865 /* Find next visible element in the tree */
1867 {
1868  TreeStoreElem *tselem = TREESTORE(te);
1869 
1870  if (TSELEM_OPEN(tselem, space_outliner) && te->subtree.first) {
1871  te = reinterpret_cast<TreeElement *>(te->subtree.first);
1872  }
1873  else if (te->next) {
1874  te = te->next;
1875  }
1876  else {
1878  }
1879 
1880  return te;
1881 }
1882 
1884  TreeElement *te,
1885  bool toggle_all)
1886 {
1887  TreeStoreElem *tselem = TREESTORE(te);
1888 
1889  if (TSELEM_OPEN(tselem, space_outliner)) {
1890  outliner_item_openclose(te, false, toggle_all);
1891  }
1892  /* Only walk up a level if the element is closed and not toggling expand */
1893  else if (!toggle_all && te->parent) {
1894  te = te->parent;
1895  }
1896 
1897  return te;
1898 }
1899 
1901  TreeElement *te,
1902  bool toggle_all)
1903 {
1904  TreeStoreElem *tselem = TREESTORE(te);
1905 
1906  /* Only walk down a level if the element is open and not toggling expand */
1907  if (!toggle_all && TSELEM_OPEN(tselem, space_outliner) && !BLI_listbase_is_empty(&te->subtree)) {
1908  te = reinterpret_cast<TreeElement *>(te->subtree.first);
1909  }
1910  else {
1911  outliner_item_openclose(te, true, toggle_all);
1912  }
1913 
1914  return te;
1915 }
1916 
1918  TreeElement *te,
1919  const int direction,
1920  const bool extend,
1921  const bool toggle_all)
1922 {
1923  TreeStoreElem *tselem = TREESTORE(te);
1924 
1925  switch (direction) {
1926  case UI_SELECT_WALK_UP:
1927  te = outliner_find_previous_element(space_outliner, te);
1928  break;
1929  case UI_SELECT_WALK_DOWN:
1930  te = outliner_find_next_element(space_outliner, te);
1931  break;
1932  case UI_SELECT_WALK_LEFT:
1933  te = outliner_walk_left(space_outliner, te, toggle_all);
1934  break;
1935  case UI_SELECT_WALK_RIGHT:
1936  te = outliner_walk_right(space_outliner, te, toggle_all);
1937  break;
1938  }
1939 
1940  /* If new element is already selected, deselect the previous element */
1941  TreeStoreElem *tselem_new = TREESTORE(te);
1942  if (extend) {
1943  tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
1944  (tselem->flag | TSE_SELECTED);
1945  }
1946 
1947  return te;
1948 }
1949 
1950 /* Find the active element to walk from, or set one if none exists.
1951  * Changed is set to true if the active element is found, or false if it was set */
1952 static TreeElement *find_walk_select_start_element(SpaceOutliner *space_outliner, bool *changed)
1953 {
1954  TreeElement *active_te = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE);
1955  *changed = false;
1956 
1957  /* If no active element exists, use the first element in the tree */
1958  if (!active_te) {
1959  active_te = reinterpret_cast<TreeElement *>(space_outliner->tree.first);
1960  *changed = true;
1961  }
1962 
1963  /* If the active element is not visible, activate the first visible parent element */
1964  if (!outliner_is_element_visible(active_te)) {
1965  while (!outliner_is_element_visible(active_te)) {
1966  active_te = active_te->parent;
1967  }
1968  *changed = true;
1969  }
1970 
1971  return active_te;
1972 }
1973 
1974 /* Scroll the outliner when the walk element reaches the top or bottom boundary */
1975 static void outliner_walk_scroll(SpaceOutliner *space_outliner, ARegion *region, TreeElement *te)
1976 {
1977  /* Account for the header height */
1978  int y_max = region->v2d.cur.ymax - UI_UNIT_Y;
1979  int y_min = region->v2d.cur.ymin;
1980 
1981  /* Scroll if walked position is beyond the border */
1982  if (te->ys > y_max) {
1983  outliner_scroll_view(space_outliner, region, te->ys - y_max);
1984  }
1985  else if (te->ys < y_min) {
1986  outliner_scroll_view(space_outliner, region, -(y_min - te->ys));
1987  }
1988 }
1989 
1991 {
1992  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1993  ARegion *region = CTX_wm_region(C);
1994 
1995  const short direction = RNA_enum_get(op->ptr, "direction");
1996  const bool extend = RNA_boolean_get(op->ptr, "extend");
1997  const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all");
1998 
1999  bool changed;
2000  TreeElement *active_te = find_walk_select_start_element(space_outliner, &changed);
2001 
2002  /* If finding the active element did not modify the selection, proceed to walk */
2003  if (!changed) {
2004  active_te = do_outliner_select_walk(space_outliner, active_te, direction, extend, toggle_all);
2005  }
2006 
2008  space_outliner,
2009  active_te,
2010  OL_ITEM_SELECT | OL_ITEM_ACTIVATE | (extend ? OL_ITEM_EXTEND : 0));
2011 
2012  /* Scroll outliner to focus on walk element */
2013  outliner_walk_scroll(space_outliner, region, active_te);
2014 
2015  ED_outliner_select_sync_from_outliner(C, space_outliner);
2016  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
2017 
2018  return OPERATOR_FINISHED;
2019 }
2020 
2022 {
2023  /* identifiers */
2024  ot->name = "Walk Select";
2025  ot->idname = "OUTLINER_OT_select_walk";
2026  ot->description = "Use walk navigation to select tree elements";
2027 
2028  /* api callbacks */
2031 
2033 
2034  /* properties */
2035  PropertyRNA *prop;
2037  prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk");
2039  prop = RNA_def_boolean(
2040  ot->srna, "toggle_all", false, "Toggle All", "Toggle open/close hierarchy");
2042 }
2043 
#define PBONE_SELECTABLE(arm, bone)
Definition: BKE_armature.h:554
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
void BKE_constraint_panel_expand(struct bConstraint *con)
Definition: constraint.c:5734
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
struct SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
Definition: context.c:860
struct LayerCollection * CTX_data_layer_collection(const bContext *C)
Definition: context.c:1126
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:775
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
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const struct Object *ob)
void BKE_object_defgroup_active_index_set(struct Object *ob, int new_index)
Definition: deform.c:568
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
Definition: gpencil.c:1601
void BKE_gpencil_modifier_panel_expand(struct GpencilModifierData *md)
struct ViewLayer * BKE_view_layer_find_from_collection(const struct Scene *scene, struct LayerCollection *lc)
bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCollection *lc)
Definition: layer.c:641
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
Definition: layer.c:388
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
struct Base ** BKE_view_layer_array_from_bases_in_mode_params(struct ViewLayer *view_layer, const struct View3D *v3d, uint *r_len, const struct ObjectsInModeParams *params)
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:397
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
void BKE_modifier_panel_expand(struct ModifierData *md)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_child_recursive(const struct Object *ob_parent, const struct Object *ob_child)
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
Definition: object.cc:2034
void BKE_object_modifier_set_active(struct Object *ob, struct ModifierData *md)
Definition: object.cc:1367
struct ModifierData * BKE_object_active_modifier(const struct Object *ob)
struct Object ** BKE_object_pose_array_get_unique(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_objects_len)
Definition: object.cc:2594
bool BKE_object_is_in_editmode(const struct Object *ob)
struct ParticleSystem * psys_get_current(struct Object *ob)
Definition: particle.c:634
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void BKE_shaderfx_panel_expand(struct ShaderFxData *fx)
Definition: shader_fx.c:163
#define BLI_assert(a)
Definition: BLI_assert.h:46
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
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ID_CA
Definition: DNA_ID_enums.h:56
@ ID_AR
Definition: DNA_ID_enums.h:66
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_VO
Definition: DNA_ID_enums.h:83
@ 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_SCE
Definition: DNA_ID_enums.h:45
@ ID_GD
Definition: DNA_ID_enums.h:71
@ ID_CV
Definition: DNA_ID_enums.h:81
@ ID_LP
Definition: DNA_ID_enums.h:80
@ ID_WO
Definition: DNA_ID_enums.h:59
@ ID_MA
Definition: DNA_ID_enums.h:51
@ 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
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_HIDDEN_A
@ BONE_HIDDEN_P
@ BONE_TIPSEL
Object groups, one object can be in many groups at once.
@ GP_LAYER_ACTIVE
@ BASE_VISIBLE_DEPSGRAPH
@ BASE_SELECTED
ModifierType
@ eModifierType_ParticleSystem
@ eModifierType_Fluidsim
@ eModifierType_Cloth
@ eModifierType_Fluid
@ eModifierType_Collision
@ eModifierType_DynamicPaint
@ eModifierType_Softbody
eObjectMode
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_GPENCIL
#define OB_TYPE_SUPPORT_EDITMODE(_type)
@ TSE_POSE_CHANNEL
@ TSE_CONSTRAINT_BASE
@ TSE_MODIFIER_BASE
@ TSE_GP_LAYER
@ TSE_SEQUENCE_DUP
@ TSE_SEQUENCE
@ TSE_GPENCIL_EFFECT
@ TSE_POSEGRP_BASE
@ TSE_VIEW_COLLECTION_BASE
@ TSE_EBONE
@ TSE_BONE
@ TSE_LINKED_PSYS
@ TSE_DEFGROUP_BASE
@ TSE_CONSTRAINT
@ TSE_R_LAYER_BASE
@ TSE_LAYER_COLLECTION
@ TSE_SEQ_STRIP
@ TSE_GPENCIL_EFFECT_BASE
@ TSE_LINKED_OB
@ TSE_SOME_ID
@ TSE_MODIFIER
@ TSE_POSEGRP
@ TSE_R_LAYER
@ TSE_POSE_BASE
@ TSE_DEFGROUP
@ TSE_SELECTED
@ TSE_CLOSED
@ TSE_ACTIVE
#define FIRSTBASE(_view_layer)
@ SCE_OBJECT_MODE_LOCK
#define OBACT(_view_layer)
@ SPACE_PROPERTIES
@ SO_SYNC_SELECT
@ SO_VIEW_LAYER
@ BCONTEXT_CONSTRAINT
@ BCONTEXT_VIEW_LAYER
@ BCONTEXT_MATERIAL
@ BCONTEXT_SHADERFX
@ BCONTEXT_MODIFIER
@ BCONTEXT_BONE
@ BCONTEXT_DATA
@ BCONTEXT_OBJECT
@ BCONTEXT_BONE_CONSTRAINT
@ BCONTEXT_PHYSICS
@ BCONTEXT_SCENE
@ BCONTEXT_WORLD
@ BCONTEXT_PARTICLE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
#define EBONE_SELECTABLE(arm, ebone)
Definition: ED_armature.h:52
bool ED_buttons_should_sync_with_outliner(const struct bContext *C, const struct SpaceProperties *sbuts, struct ScrArea *area)
void ED_buttons_set_context(const struct bContext *C, struct SpaceProperties *sbuts, PointerRNA *ptr, int context)
@ EM_NO_CONTEXT
Definition: ED_object.h:243
@ EM_FREEDATA
Definition: ED_object.h:242
void ED_object_base_activate_with_mode_exit_if_needed(struct bContext *C, struct Base *base)
void ED_object_mode_generic_exit(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
Definition: object_modes.c:387
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode)
Definition: object_select.c:76
bool ED_object_editmode_exit_ex(struct Main *bmain, struct Scene *scene, struct Object *obedit, int flag)
Definition: object_edit.c:653
bool ED_object_editmode_enter_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int flag)
Definition: object_edit.c:734
bool ED_object_mode_set(struct bContext *C, eObjectMode mode)
Definition: object_modes.c:231
eObjectSelect_Mode
Definition: ED_object.h:153
@ BA_DESELECT
Definition: ED_object.h:154
@ BA_SELECT
Definition: ED_object.h:155
void ED_outliner_select_sync_from_object_tag(struct bContext *C)
void ED_outliner_select_sync_from_outliner(struct bContext *C, struct SpaceOutliner *space_outliner)
void ED_region_tag_redraw_no_rebuild(struct ARegion *region)
Definition: area.c:674
bool ED_operator_outliner_active(struct bContext *C)
Definition: screen_ops.c:253
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
#define SEL_OP_USE_PRE_DESELECT(sel_op)
@ UI_SELECT_WALK_RIGHT
@ UI_SELECT_WALK_UP
@ UI_SELECT_WALK_LEFT
@ UI_SELECT_WALK_DOWN
eSelectOp
@ SEL_OP_SUB
void ED_sequencer_deselect_all(struct Scene *scene)
bool ED_text_activate_in_screen(struct bContext *C, struct Text *text)
void ED_undo_group_begin(struct bContext *C)
Definition: ed_undo.c:88
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:100
void ED_undo_group_end(struct bContext *C)
Definition: ed_undo.c:94
_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 type
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_Y
#define UI_UNIT_X
void UI_view2d_region_to_view_rctf(const struct View2D *v2d, const struct rctf *rect_src, struct rctf *rect_dst) ATTR_NONNULL()
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
#define ND_SEQUENCER
Definition: WM_types.h:385
#define NA_ACTIVATED
Definition: WM_types.h:529
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DRAW
Definition: WM_types.h:410
#define ND_DATA
Definition: WM_types.h:456
#define NC_SCREEN
Definition: WM_types.h:327
#define ND_MODE
Definition: WM_types.h:393
#define ND_OB_SELECT
Definition: WM_types.h:390
#define NC_SCENE
Definition: WM_types.h:328
#define ND_MODIFIER
Definition: WM_types.h:411
#define NA_EDITED
Definition: WM_types.h:523
#define ND_PARTICLE
Definition: WM_types.h:414
#define NS_MODE_OBJECT
Definition: WM_types.h:501
#define NC_MATERIAL
Definition: WM_types.h:330
#define ND_CONSTRAINT
Definition: WM_types.h:413
#define NC_GPENCIL
Definition: WM_types.h:349
#define ND_BONE_ACTIVE
Definition: WM_types.h:408
#define ND_TRANSFORM
Definition: WM_types.h:405
#define ND_LAYER
Definition: WM_types.h:398
#define NS_MODE_POSE
Definition: WM_types.h:510
#define NC_OBJECT
Definition: WM_types.h:329
#define ND_SHADING_LINKS
Definition: WM_types.h:427
#define NS_LAYER_COLLECTION
Definition: WM_types.h:519
#define NA_SELECTED
Definition: WM_types.h:528
bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
void activate(bool forceActivation=false) const
#define SELECT
Scene scene
const Depsgraph * depsgraph
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static void area(int d1, int d2, int e1, int e2, float weights[2])
bool active
all scheduled work for the GPU.
void all_open(const SpaceOutliner &space_outliner, const VisitorFn visitor)
bool outliner_flag_set(const SpaceOutliner &space_outliner, const short flag, const short set)
void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
@ OL_ITEM_EXTEND
@ OL_ITEM_RECURSIVE
@ OL_ITEM_DESELECT
@ OL_ITEM_SELECT
@ OL_ITEM_ACTIVATE
@ OL_ITEM_SELECT_DATA
void outliner_viewcontext_init(const struct bContext *C, TreeViewContext *tvc)
TreeElement * outliner_find_element_with_flag(const ListBase *lb, short flag)
eOLSetState
@ OL_SETSEL_NORMAL
@ OL_SETSEL_EXTEND
@ OL_SETSEL_NONE
float outliner_right_columns_width(const struct SpaceOutliner *space_outliner)
bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_co_x)
void outliner_scroll_view(struct SpaceOutliner *space_outliner, struct ARegion *region, int delta_y)
eOLDrawState
@ OL_DRAWSEL_NORMAL
@ OL_DRAWSEL_NONE
bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x)
TreeElement * outliner_search_back_te(TreeElement *te, short idcode)
#define TREESTORE(a)
TreeElement * outliner_find_item_at_y(const SpaceOutliner *space_outliner, const ListBase *tree, float view_co_y)
bool outliner_is_element_visible(const TreeElement *te)
bool outliner_shows_mode_column(const SpaceOutliner &space_outliner)
struct ID * outliner_search_back(TreeElement *te, short idcode)
#define TSELEM_OPEN(telm, sv)
TreeElement * outliner_find_item_at_x_in_row(const SpaceOutliner *space_outliner, TreeElement *parent_te, float view_co_x, bool *r_is_merged_icon, bool *r_is_over_icon)
void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct SpaceOutliner *space_outliner, struct ARegion *region)
void merged_element_search_menu_invoke(struct bContext *C, TreeElement *parent_te, TreeElement *activate_te)
static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select)
static eOLDrawState tree_element_viewlayer_state_get(const bContext *C, const TreeElement *te)
static void tree_element_camera_activate(bContext *C, Scene *scene, TreeElement *te)
void outliner_item_mode_toggle(bContext *C, TreeViewContext *tvc, TreeElement *te, const bool do_extend)
static eOLDrawState tree_element_posegroup_state_get(const ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem)
static void do_outliner_item_mode_toggle_generic(bContext *C, TreeViewContext *tvc, Base *base)
static void tree_element_master_collection_activate(const bContext *C)
static void do_outliner_item_editmode_toggle(bContext *C, Scene *scene, Base *base)
static eOLDrawState tree_element_active_world_get(const Scene *scene, const TreeElement *te)
static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *space_outliner, const ARegion *region, float view_co_x)
static eOLDrawState tree_element_defgroup_state_get(const ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem)
static TreeElement * outliner_find_next_element(SpaceOutliner *space_outliner, TreeElement *te)
static TreeElement * outliner_find_previous_element(SpaceOutliner *space_outliner, TreeElement *te)
static eOLDrawState tree_element_ebone_state_get(const TreeElement *te)
void tree_element_activate(bContext *C, const TreeViewContext *tvc, TreeElement *te, const eOLSetState set, const bool handle_all_types)
static bool do_outliner_range_select_recursive(ListBase *lb, TreeElement *active, TreeElement *cursor, bool selecting)
static int outliner_item_do_activate_from_cursor(bContext *C, const int mval[2], const bool extend, const bool use_range, const bool deselect_all)
static eOLDrawState tree_element_object_state_get(const TreeViewContext *tvc, const TreeStoreElem *tselem)
static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void tree_element_world_activate(bContext *C, Scene *scene, TreeElement *te)
eOLDrawState tree_element_active_state_get(const TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *base)
void OUTLINER_OT_select_walk(wmOperatorType *ot)
static TreeElement * outliner_element_find_successor_in_parents(TreeElement *te)
static void tree_element_object_activate(bContext *C, Scene *scene, ViewLayer *view_layer, TreeElement *te, const eOLSetState set, bool recursive)
static eOLDrawState tree_element_pose_state_get(const ViewLayer *view_layer, const TreeStoreElem *tselem)
static eOLDrawState tree_element_gplayer_state_get(const TreeElement *te)
static TreeElement * do_outliner_select_walk(SpaceOutliner *space_outliner, TreeElement *te, const int direction, const bool extend, const bool toggle_all)
static void do_outliner_range_select(bContext *C, SpaceOutliner *space_outliner, TreeElement *cursor, const bool extend)
static void tree_element_bone_activate(bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
static TreeElement * outliner_find_rightmost_visible_child(SpaceOutliner *space_outliner, TreeElement *te)
static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, bool select)
void outliner_item_select(bContext *C, SpaceOutliner *space_outliner, TreeElement *te, const short select_flag)
static void tree_element_viewlayer_activate(bContext *C, TreeElement *te)
static void outliner_sync_to_properties_editors(const bContext *C, PointerRNA *ptr, const int context)
void tree_element_type_active_set(bContext *C, const TreeViewContext *tvc, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
static eOLDrawState tree_element_posechannel_state_get(const Object *ob_pose, const TreeElement *te, const TreeStoreElem *tselem)
void OUTLINER_OT_item_activate(wmOperatorType *ot)
static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select)
static void tree_element_modifier_activate(bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
static void tree_element_material_activate(bContext *C, ViewLayer *view_layer, TreeElement *te)
static bool outliner_is_co_within_active_mode_column(bContext *C, SpaceOutliner *space_outliner, const float view_mval[2])
static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static eOLDrawState tree_element_active_scene_get(const TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
static TreeElement * outliner_walk_right(SpaceOutliner *space_outliner, TreeElement *te, bool toggle_all)
static void tree_element_constraint_activate(bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
static void tree_element_psys_activate(bContext *C, TreeStoreElem *tselem)
static void tree_element_gplayer_activate(bContext *C, TreeElement *te, TreeStoreElem *tselem)
static TreeElement * outliner_walk_left(SpaceOutliner *space_outliner, TreeElement *te, bool toggle_all)
static eOLDrawState tree_element_active_material_get(const ViewLayer *view_layer, const TreeElement *te)
static void tree_element_posegroup_activate(bContext *C, TreeElement *te, TreeStoreElem *tselem)
static void outliner_box_select(bContext *C, SpaceOutliner *space_outliner, const rctf *rectf, const bool select)
bPoseChannel * outliner_find_parent_bone(TreeElement *te, TreeElement **r_bone_te)
static void tree_element_text_activate(bContext *C, TreeElement *te)
static void tree_element_active_ebone__sel(bContext *C, bArmature *arm, EditBone *ebone, short sel)
static eOLDrawState tree_element_bone_state_get(const ViewLayer *view_layer, const TreeElement *te, const TreeStoreElem *tselem)
static void outliner_walk_scroll(SpaceOutliner *space_outliner, ARegion *region, TreeElement *te)
static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreElem *tselem)
static eOLDrawState tree_element_modifier_state_get(const TreeElement *te, const TreeStoreElem *tselem)
eOLDrawState tree_element_type_active_state_get(const bContext *C, const TreeViewContext *tvc, const TreeElement *te, const TreeStoreElem *tselem)
static void tree_element_sequence_dup_activate(Scene *scene, TreeElement *UNUSED(te))
static void tree_element_layer_collection_activate(bContext *C, TreeElement *te)
static void do_outliner_item_activate_tree_element(bContext *C, const TreeViewContext *tvc, SpaceOutliner *space_outliner, TreeElement *te, TreeStoreElem *tselem, const bool extend, const bool recursive, const bool do_activate_data)
static eOLDrawState tree_element_layer_collection_state_get(const bContext *C, const TreeElement *te)
static eOLDrawState tree_element_active_camera_get(const Scene *scene, const TreeElement *te)
static eOLDrawState tree_element_sequence_state_get(const Scene *scene, const TreeElement *te)
bool outliner_is_co_within_mode_column(SpaceOutliner *space_outliner, const float view_mval[2])
static void tree_element_defgroup_activate(bContext *C, TreeElement *te, TreeStoreElem *tselem)
void OUTLINER_OT_select_box(wmOperatorType *ot)
static void tree_element_posechannel_activate(bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
static TreeElement * find_walk_select_start_element(SpaceOutliner *space_outliner, bool *changed)
static void tree_element_ebone_activate(bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
static eOLDrawState tree_element_master_collection_state_get(const bContext *C)
static void tree_element_sequence_activate(bContext *C, Scene *scene, TreeElement *te, const eOLSetState set)
static eOLDrawState tree_element_sequence_dup_state_get(const TreeElement *te)
static int outliner_box_select_exec(bContext *C, wmOperator *op)
bool ED_object_posemode_enter_ex(struct Main *bmain, Object *ob)
Definition: pose_edit.c:80
bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
Definition: pose_edit.c:115
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_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
Editing * SEQ_editing_get(const Scene *scene)
Definition: sequencer.c:241
void SEQ_select_active_set(Scene *scene, Sequence *seq)
Definition: strip_select.c:29
struct Base * next
short flag
struct Object * object
struct Bone * next
ListBase childbase
struct EditBone * next
Definition: BKE_armature.h:33
ListBase * seqbasep
Sequence * act_seq
Definition: DNA_ID.h:368
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase wm
Definition: BKE_main.h:197
ListBase objects
Definition: BKE_main.h:170
struct bPose * pose
char * matbits
void * data
void * data
Definition: RNA_types.h:38
struct ToolSettings * toolsettings
struct Editing * ed
ListBase view_layers
struct Object * camera
struct Sequence * next
char name[256]
StripElem * stripdata
struct TreeElement * parent
ListBase subtree
TreeStoreElem * store_elem
struct TreeElement * prev
struct TreeElement * next
struct Scene * scene
struct ViewLayer * view_layer
ListBase layer_collections
ListBase bonebase
struct EditBone * act_edbone
struct Bone * bone
ListBase chanbase
int active_group
ListBase areabase
float xmax
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct PointerRNA * ptr
Establish and manage Outliner trees for different display modes.
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
void WM_operator_properties_select_walk_direction(wmOperatorType *ot)
void WM_operator_properties_border_to_rctf(struct wmOperator *op, rctf *rect)
void WM_window_set_active_scene(Main *bmain, bContext *C, wmWindow *win, Scene *scene)
Definition: wm_window.c:2188
ViewLayer * WM_window_get_active_view_layer(const wmWindow *win)
Definition: wm_window.c:2217
void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer)
Definition: wm_window.c:2237
void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene)
Definition: wm_window.c:2142
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2183