Blender  V2.93
outliner_select.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2004 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <stdlib.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_armature_types.h"
29 #include "DNA_collection_types.h"
31 #include "DNA_gpencil_types.h"
32 #include "DNA_modifier_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_sequence_types.h"
36 #include "DNA_shader_fx_types.h"
37 
38 #include "BLI_listbase.h"
39 #include "BLI_utildefines.h"
40 
41 #include "BKE_armature.h"
42 #include "BKE_collection.h"
43 #include "BKE_constraint.h"
44 #include "BKE_context.h"
45 #include "BKE_gpencil.h"
46 #include "BKE_gpencil_modifier.h"
47 #include "BKE_layer.h"
48 #include "BKE_main.h"
49 #include "BKE_modifier.h"
50 #include "BKE_object.h"
51 #include "BKE_particle.h"
52 #include "BKE_report.h"
53 #include "BKE_shader_fx.h"
54 
55 #include "DEG_depsgraph.h"
56 #include "DEG_depsgraph_build.h"
57 
58 #include "ED_armature.h"
59 #include "ED_buttons.h"
60 #include "ED_object.h"
61 #include "ED_outliner.h"
62 #include "ED_screen.h"
63 #include "ED_select_utils.h"
64 #include "ED_sequencer.h"
65 #include "ED_undo.h"
66 
67 #include "SEQ_select.h"
68 #include "SEQ_sequencer.h"
69 
70 #include "WM_api.h"
71 #include "WM_types.h"
72 
73 #include "UI_interface.h"
74 #include "UI_view2d.h"
75 
76 #include "RNA_access.h"
77 #include "RNA_define.h"
78 
79 #include "outliner_intern.h"
80 
87 {
88  Main *bmain = CTX_data_main(C);
89  Object *ob = base->object;
90 
91  bool changed = false;
92  if (BKE_object_is_in_editmode(ob)) {
93  changed = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
94  if (changed) {
97  }
98  }
99  else {
101  if (changed) {
104  }
105  }
106 
107  if (changed) {
110  ED_undo_push(C, "Outliner Edit Mode Toggle");
111  }
112 }
113 
120 {
121  Main *bmain = CTX_data_main(C);
122  Object *ob = base->object;
123 
124  if (ID_IS_LINKED(ob)) {
125  BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata");
126  return;
127  }
128 
129  bool changed = false;
130  if (ob->mode & OB_MODE_POSE) {
131  changed = ED_object_posemode_exit_ex(bmain, ob);
132  if (changed) {
135  }
136  }
137  else {
138  changed = ED_object_posemode_enter_ex(bmain, ob);
139  if (changed) {
142  }
143  }
144 
145  if (changed) {
148  ED_undo_push(C, "Outliner Pose Mode Toggle");
149  }
150 }
151 
164 {
165  const int active_mode = tvc->obact->mode;
167 
169  Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact);
170  if (base_active != base) {
174  ED_undo_push(C, "Change Active");
175 
176  /* Operator call does undo push. */
177  ED_object_mode_set(C, active_mode);
179  }
180  }
182 }
183 
184 /* Toggle the item's interaction mode if supported */
186  TreeViewContext *tvc,
187  TreeElement *te,
188  const bool do_extend)
189 {
190  TreeStoreElem *tselem = TREESTORE(te);
191 
192  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
193  Object *ob = (Object *)tselem->id;
194  Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
195 
196  /* Hidden objects can be removed from the mode. */
197  if (!base || (!(base->flag & BASE_VISIBLE_DEPSGRAPH) && (ob->mode != tvc->obact->mode))) {
198  return;
199  }
200 
201  if (!do_extend) {
203  }
204  else if (tvc->ob_edit && OB_TYPE_SUPPORT_EDITMODE(ob->type)) {
206  }
207  else if (tvc->ob_pose && ob->type == OB_ARMATURE) {
209  }
210  }
211 }
212 
213 /* ****************************************************** */
214 /* Outliner Element Selection/Activation on Click */
215 
217 {
218  /* paranoia check */
219  if (te->idcode != ID_SCE) {
220  return;
221  }
222 
223  ViewLayer *view_layer = 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 = 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  Bone *bone;
254  for (bone = bone_parent->childbase.first; bone; bone = bone->next) {
255  if (select && PBONE_SELECTABLE(arm, bone)) {
256  bone->flag |= BONE_SELECTED;
257  }
258  else {
259  bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
260  }
262  }
263 }
264 
265 static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select)
266 {
267  EditBone *ebone;
268  for (ebone = ebone_parent->next; ebone; ebone = ebone->next) {
269  if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) {
270  if (select && EBONE_SELECTABLE(arm, ebone)) {
272  }
273  else {
274  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
275  }
276  }
277  }
278 }
279 
281  Scene *scene,
282  ViewLayer *view_layer,
283  TreeElement *te,
284  const eOLSetState set,
285  bool recursive)
286 {
287  TreeStoreElem *tselem = TREESTORE(te);
288  TreeStoreElem *parent_tselem = NULL;
289  TreeElement *parent_te = NULL;
290  Scene *sce;
291  Base *base;
292  Object *ob = NULL;
293 
294  /* if id is not object, we search back */
295  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
296  ob = (Object *)tselem->id;
297  }
298  else {
299  parent_te = outliner_search_back_te(te, ID_OB);
300  if (parent_te) {
301  parent_tselem = TREESTORE(parent_te);
302  ob = (Object *)parent_tselem->id;
303 
304  /* Don't return when activating children of the previous active object. */
305  if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) {
306  return;
307  }
308  }
309  }
310  if (ob == NULL) {
311  return;
312  }
313 
314  sce = (Scene *)outliner_search_back(te, ID_SCE);
315  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 != NULL) {
325  Object *obact = OBACT(view_layer);
326  const eObjectMode object_mode = obact ? 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 = NULL;
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  /* deleselect 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 NULL when a local object points to a library mesh. */
392  if (ob == NULL || ob != OBACT(view_layer) || ob->matbits == NULL) {
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 = bmain->wm.first;
423 
424  WM_windows_scene_data_sync(&wm->windows, scene);
428 }
429 
431 {
432  Scene *sce = NULL;
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);
453  ob->actdef = te->index + 1;
454 
457 }
458 
460 {
461  bGPdata *gpd = (bGPdata *)tselem->id;
462  bGPDlayer *gpl = 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 = ob->data;
491  bPoseChannel *pchan = 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, NULL, &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(NULL, ob_iter, ob_iter->pose, ob_iter->data)) {
504  continue;
505  }
506 
507  bPoseChannel *pchannel;
508  for (pchannel = ob_iter->pose->chanbase.first; pchannel; pchannel = pchannel->next) {
509  pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
510  }
511 
512  if (ob != ob_iter) {
514  }
515  }
517  }
518 
519  if ((set == OL_SETSEL_EXTEND) && (pchan->bone->flag & BONE_SELECTED)) {
520  pchan->bone->flag &= ~BONE_SELECTED;
521  }
522  else {
523  pchan->bone->flag |= BONE_SELECTED;
524  arm->act_bone = pchan->bone;
525  }
526 
527  if (recursive) {
528  /* Recursive select/deselect */
530  arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0);
531  }
532 
535  }
536 }
537 
539  ViewLayer *view_layer,
540  TreeElement *te,
541  TreeStoreElem *tselem,
542  const eOLSetState set,
543  bool recursive)
544 {
545  bArmature *arm = (bArmature *)tselem->id;
546  Bone *bone = te->directdata;
547 
548  if (!(bone->flag & BONE_HIDDEN_P)) {
549  Object *ob = OBACT(view_layer);
550  if (ob) {
551  if (set != OL_SETSEL_EXTEND) {
552  /* single select forces all other bones to get unselected */
553  for (Bone *bone_iter = arm->bonebase.first; bone_iter != NULL;
554  bone_iter = bone_iter->next) {
555  bone_iter->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
556  do_outliner_bone_select_recursive(arm, bone_iter, false);
557  }
558  }
559  }
560 
561  if (set == OL_SETSEL_EXTEND && (bone->flag & BONE_SELECTED)) {
562  bone->flag &= ~BONE_SELECTED;
563  }
564  else {
565  bone->flag |= BONE_SELECTED;
566  arm->act_bone = bone;
567  }
568 
569  if (recursive) {
570  /* Recursive select/deselect */
571  do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0);
572  }
573 
575  }
576 }
577 
579 static void tree_element_active_ebone__sel(bContext *C, bArmature *arm, EditBone *ebone, short sel)
580 {
581  if (sel) {
582  arm->act_edbone = ebone;
583  }
584  ED_armature_ebone_select_set(ebone, sel);
586 }
588  ViewLayer *view_layer,
589  TreeElement *te,
590  TreeStoreElem *tselem,
591  const eOLSetState set,
592  bool recursive)
593 {
594  bArmature *arm = (bArmature *)tselem->id;
595  EditBone *ebone = te->directdata;
596 
597  if (set == OL_SETSEL_NORMAL) {
598  if (!(ebone->flag & BONE_HIDDEN_A)) {
599  uint bases_len = 0;
601  view_layer, NULL, &bases_len);
602  ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
603  MEM_freeN(bases);
604 
605  tree_element_active_ebone__sel(C, arm, ebone, true);
606  }
607  }
608  else if (set == OL_SETSEL_EXTEND) {
609  if (!(ebone->flag & BONE_HIDDEN_A)) {
610  if (!(ebone->flag & BONE_SELECTED)) {
611  tree_element_active_ebone__sel(C, arm, ebone, true);
612  }
613  else {
614  /* entirely selected, so de-select */
615  tree_element_active_ebone__sel(C, arm, ebone, false);
616  }
617  }
618  }
619 
620  if (recursive) {
621  /* Recursive select/deselect */
622  do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0);
623  }
624 }
625 
627  TreeElement *te,
628  TreeStoreElem *tselem,
629  const eOLSetState set)
630 {
631  Object *ob = (Object *)tselem->id;
632  ModifierData *md = (ModifierData *)te->directdata;
633 
634  if (set == OL_SETSEL_NORMAL) {
637  }
638 }
639 
641 {
642  Object *ob = (Object *)tselem->id;
643 
645 }
646 
648  ViewLayer *view_layer,
649  TreeElement *te,
650  TreeStoreElem *tselem,
651  const eOLSetState set)
652 {
653  Object *ob = (Object *)tselem->id;
654 
655  /* Activate the parent bone if this is a bone constraint. */
656  te = te->parent;
657  while (te) {
658  tselem = TREESTORE(te);
659  if (tselem->type == TSE_POSE_CHANNEL) {
660  tree_element_posechannel_activate(C, view_layer, te, tselem, set, false);
661  return;
662  }
663  te = te->parent;
664  }
665 
667 }
668 
670  Scene *scene,
671  TreeElement *te,
672  const eOLSetState set)
673 {
674  Sequence *seq = (Sequence *)te->directdata;
675  Editing *ed = SEQ_editing_get(scene, false);
676 
677  if (BLI_findindex(ed->seqbasep, seq) != -1) {
678  if (set == OL_SETSEL_EXTEND) {
680  }
682 
683  if ((set == OL_SETSEL_EXTEND) && seq->flag & SELECT) {
684  seq->flag &= ~SELECT;
685  }
686  else {
687  seq->flag |= SELECT;
689  }
690  }
691 
693 }
694 
696 {
697  Editing *ed = SEQ_editing_get(scene, false);
698 
699  /* XXX select_single_seq(seq, 1); */
700  Sequence *p = ed->seqbasep->first;
701  while (p) {
702  if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) {
703  p = p->next;
704  continue;
705  }
706 
707  /* XXX: if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) select_single_seq(p,
708  * 0); */
709  p = p->next;
710  }
711 }
712 
714 {
715  ViewLayer *view_layer = CTX_data_view_layer(C);
716  LayerCollection *layer_collection = view_layer->layer_collections.first;
717  BKE_layer_collection_activate(view_layer, layer_collection);
718  /* A very precise notifier - ND_LAYER alone is quite vague, we want to avoid unnecessary work
719  * when only the active collection changes. */
721 }
722 
724 {
726  LayerCollection *layer_collection = te->directdata;
727  ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
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 
734 /* ---------------------------------------------- */
735 
736 /* generic call for ID data check or make/check active in UI */
738  const TreeViewContext *tvc,
739  TreeElement *te,
740  const eOLSetState set,
741  const bool handle_all_types)
742 {
743  switch (te->idcode) {
747  case ID_OB:
748  if (handle_all_types) {
749  tree_element_object_activate(C, tvc->scene, tvc->view_layer, te, set, false);
750  }
751  break;
752  case ID_MA:
754  break;
755  case ID_WO:
757  break;
758  case ID_CA:
760  break;
761  }
762 }
763 
768  const TreeViewContext *tvc,
769  TreeElement *te,
770  TreeStoreElem *tselem,
771  const eOLSetState set,
772  bool recursive)
773 {
774  BLI_assert(set != OL_SETSEL_NONE);
775  switch (tselem->type) {
776  case TSE_DEFGROUP:
777  tree_element_defgroup_activate(C, te, tselem);
778  break;
779  case TSE_BONE:
780  tree_element_bone_activate(C, tvc->view_layer, te, tselem, set, recursive);
781  break;
782  case TSE_EBONE:
783  tree_element_ebone_activate(C, tvc->view_layer, te, tselem, set, recursive);
784  break;
785  case TSE_MODIFIER:
786  tree_element_modifier_activate(C, te, tselem, set);
787  break;
788  case TSE_LINKED_OB:
789  tree_element_object_activate(C, tvc->scene, tvc->view_layer, te, set, false);
790  break;
791  case TSE_LINKED_PSYS:
792  tree_element_psys_activate(C, tselem);
793  break;
794  case TSE_POSE_BASE:
795  return;
796  case TSE_POSE_CHANNEL:
797  tree_element_posechannel_activate(C, tvc->view_layer, te, tselem, set, recursive);
798  break;
799  case TSE_CONSTRAINT_BASE:
800  case TSE_CONSTRAINT:
801  tree_element_constraint_activate(C, tvc->view_layer, te, tselem, set);
802  break;
803  case TSE_R_LAYER:
805  break;
806  case TSE_POSEGRP:
807  tree_element_posegroup_activate(C, te, tselem);
808  break;
809  case TSE_SEQUENCE:
810  tree_element_sequence_activate(C, tvc->scene, te, set);
811  break;
812  case TSE_SEQUENCE_DUP:
814  break;
815  case TSE_GP_LAYER:
816  tree_element_gplayer_activate(C, te, tselem);
817  break;
820  break;
823  break;
824  }
825 }
826 
828  const TreeElement *te,
829  const TreeStoreElem *tselem)
830 {
831  const Object *ob = (const Object *)tselem->id;
832  if (ob == OBACT(view_layer)) {
833  if (ob->actdef == te->index + 1) {
834  return OL_DRAWSEL_NORMAL;
835  }
836  }
837  return OL_DRAWSEL_NONE;
838 }
839 
841  const TreeElement *te,
842  const TreeStoreElem *tselem)
843 {
844  const bArmature *arm = (const bArmature *)tselem->id;
845  const Bone *bone = te->directdata;
846  const Object *ob = OBACT(view_layer);
847  if (ob && ob->data == arm) {
848  if (bone->flag & BONE_SELECTED) {
849  return OL_DRAWSEL_NORMAL;
850  }
851  }
852  return OL_DRAWSEL_NONE;
853 }
854 
856 {
857  const EditBone *ebone = te->directdata;
858  if (ebone->flag & BONE_SELECTED) {
859  return OL_DRAWSEL_NORMAL;
860  }
861  return OL_DRAWSEL_NONE;
862 }
863 
865  const TreeStoreElem *tselem)
866 {
867  const Object *ob = (const Object *)tselem->id;
868  const ModifierData *md = (const ModifierData *)te->directdata;
869 
871 }
872 
874  const TreeStoreElem *tselem)
875 {
876  return (tselem->id == (const ID *)tvc->obact) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
877 }
878 
880  const TreeStoreElem *tselem)
881 {
882  const Object *ob = (const Object *)tselem->id;
883  /* This will just lookup in a cache, it will not change the arguments. */
884  const Base *base = BKE_view_layer_base_find((ViewLayer *)view_layer, (Object *)ob);
885  if (base == NULL) {
886  /* Armature not instantiated in current scene (e.g. inside an appended group). */
887  return OL_DRAWSEL_NONE;
888  }
889 
890  if (ob->mode & OB_MODE_POSE) {
891  return OL_DRAWSEL_NORMAL;
892  }
893  return OL_DRAWSEL_NONE;
894 }
895 
897  const TreeElement *te,
898  const TreeStoreElem *tselem)
899 {
900  const Object *ob = (const Object *)tselem->id;
901  const bPoseChannel *pchan = te->directdata;
902  if (ob == ob_pose && ob->pose) {
903  if (pchan->bone->flag & BONE_SELECTED) {
904  return OL_DRAWSEL_NORMAL;
905  }
906  }
907  return OL_DRAWSEL_NONE;
908 }
909 
911 {
912  /* paranoia check */
913  if (te->idcode != ID_SCE) {
914  return OL_DRAWSEL_NONE;
915  }
916 
917  const ViewLayer *view_layer = te->directdata;
918 
919  if (CTX_data_view_layer(C) == view_layer) {
920  return OL_DRAWSEL_NORMAL;
921  }
922  return OL_DRAWSEL_NONE;
923 }
924 
926  const TreeElement *te,
927  const TreeStoreElem *tselem)
928 {
929  const Object *ob = (const Object *)tselem->id;
930 
931  if (ob == OBACT(view_layer) && ob->pose) {
932  if (ob->pose->active_group == te->index + 1) {
933  return OL_DRAWSEL_NORMAL;
934  }
935  }
936  return OL_DRAWSEL_NONE;
937 }
938 
940 {
941  const Sequence *seq = (const Sequence *)te->directdata;
942  const Editing *ed = scene->ed;
943 
944  if (ed && ed->act_seq == seq && seq->flag & SELECT) {
945  return OL_DRAWSEL_NORMAL;
946  }
947  return OL_DRAWSEL_NONE;
948 }
949 
951 {
952  const Sequence *seq = (const Sequence *)te->directdata;
953  if (seq->flag & SELECT) {
954  return OL_DRAWSEL_NORMAL;
955  }
956  return OL_DRAWSEL_NONE;
957 }
958 
960 {
961  if (((const bGPDlayer *)te->directdata)->flag & GP_LAYER_ACTIVE) {
962  return OL_DRAWSEL_NORMAL;
963  }
964  return OL_DRAWSEL_NONE;
965 }
966 
968 {
969  const ViewLayer *view_layer = CTX_data_view_layer(C);
971 
972  if (active == view_layer->layer_collections.first) {
973  return OL_DRAWSEL_NORMAL;
974  }
975  return OL_DRAWSEL_NONE;
976 }
977 
979  const TreeElement *te)
980 {
982  if (active == te->directdata) {
983  return OL_DRAWSEL_NORMAL;
984  }
985  return OL_DRAWSEL_NONE;
986 }
987 
989  const TreeElement *te)
990 {
991  /* we search for the object parent */
992  const Object *ob = (const Object *)outliner_search_back((TreeElement *)te, ID_OB);
993  /* Note : ob->matbits can be NULL when a local object points to a library mesh. */
994  if (ob == NULL || ob != OBACT(view_layer) || ob->matbits == NULL) {
995  return OL_DRAWSEL_NONE; /* just paranoia */
996  }
997 
998  /* searching in ob mat array? */
999  const TreeElement *tes = te->parent;
1000  if (tes->idcode == ID_OB) {
1001  if (ob->actcol == te->index + 1) {
1002  if (ob->matbits[te->index]) {
1003  return OL_DRAWSEL_NORMAL;
1004  }
1005  }
1006  }
1007  /* or we search for obdata material */
1008  else {
1009  if (ob->actcol == te->index + 1) {
1010  if (ob->matbits[te->index] == 0) {
1011  return OL_DRAWSEL_NORMAL;
1012  }
1013  }
1014  }
1015  return OL_DRAWSEL_NONE;
1016 }
1017 
1019  const TreeElement *te,
1020  const TreeStoreElem *tselem)
1021 {
1022  if (te->idcode == ID_SCE) {
1023  if (tselem->id == (ID *)tvc->scene) {
1024  return OL_DRAWSEL_NORMAL;
1025  }
1026  }
1027  return OL_DRAWSEL_NONE;
1028 }
1029 
1031 {
1032  const TreeElement *tep = te->parent;
1033  if (tep == NULL) {
1034  return OL_DRAWSEL_NORMAL;
1035  }
1036 
1037  const TreeStoreElem *tselem = TREESTORE(tep);
1038  if (tselem->id == (const ID *)scene) {
1039  return OL_DRAWSEL_NORMAL;
1040  }
1041  return OL_DRAWSEL_NONE;
1042 }
1043 
1045 {
1046  const Object *ob = (const Object *)outliner_search_back((TreeElement *)te, ID_OB);
1047 
1048  return (scene->camera == ob) ? OL_DRAWSEL_NORMAL : OL_DRAWSEL_NONE;
1049 }
1050 
1052  const TreeElement *te,
1053  const TreeStoreElem *tselem)
1054 {
1055  switch (te->idcode) {
1056  case ID_SCE:
1057  return tree_element_active_scene_get(tvc, te, tselem);
1058  case ID_OB:
1059  /* Objects are currently handled by the caller in order to also change text color. */
1060  return OL_DRAWSEL_NONE;
1061  break;
1062  case ID_MA:
1064  case ID_WO:
1065  return tree_element_active_world_get(tvc->scene, te);
1066  case ID_CA:
1067  return tree_element_active_camera_get(tvc->scene, te);
1068  }
1069  return OL_DRAWSEL_NONE;
1070 }
1071 
1076  const TreeViewContext *tvc,
1077  const TreeElement *te,
1078  const TreeStoreElem *tselem)
1079 {
1080  switch (tselem->type) {
1081  case TSE_DEFGROUP:
1082  return tree_element_defgroup_state_get(tvc->view_layer, te, tselem);
1083  case TSE_BONE:
1084  return tree_element_bone_state_get(tvc->view_layer, te, tselem);
1085  case TSE_EBONE:
1086  return tree_element_ebone_state_get(te);
1087  case TSE_MODIFIER:
1088  return tree_element_modifier_state_get(te, tselem);
1089  case TSE_LINKED_OB:
1090  return tree_element_object_state_get(tvc, tselem);
1091  case TSE_LINKED_PSYS:
1092  return OL_DRAWSEL_NONE;
1093  case TSE_POSE_BASE:
1094  return tree_element_pose_state_get(tvc->view_layer, tselem);
1095  case TSE_POSE_CHANNEL:
1096  return tree_element_posechannel_state_get(tvc->ob_pose, te, tselem);
1097  case TSE_CONSTRAINT_BASE:
1098  case TSE_CONSTRAINT:
1099  return OL_DRAWSEL_NONE;
1100  case TSE_R_LAYER:
1101  return tree_element_viewlayer_state_get(C, te);
1102  case TSE_POSEGRP:
1103  return tree_element_posegroup_state_get(tvc->view_layer, te, tselem);
1104  case TSE_SEQUENCE:
1105  return tree_element_sequence_state_get(tvc->scene, te);
1106  case TSE_SEQUENCE_DUP:
1108  case TSE_GP_LAYER:
1109  return tree_element_gplayer_state_get(te);
1112  case TSE_LAYER_COLLECTION:
1114  }
1115  return OL_DRAWSEL_NONE;
1116 }
1117 
1119 {
1120  TreeStoreElem *tselem;
1121 
1122  te = te->parent;
1123  while (te) {
1124  tselem = TREESTORE(te);
1125  if (tselem->type == TSE_POSE_CHANNEL) {
1126  *r_bone_te = te;
1127  return (bPoseChannel *)te->directdata;
1128  }
1129  te = te->parent;
1130  }
1131 
1132  return NULL;
1133 }
1134 
1136  PointerRNA *ptr,
1137  const int context)
1138 {
1139  bScreen *screen = CTX_wm_screen(C);
1140 
1141  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
1142  if (area->spacetype != SPACE_PROPERTIES) {
1143  continue;
1144  }
1145 
1146  SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first;
1148  ED_buttons_set_context(C, sbuts, ptr, context);
1149  }
1150  }
1151 }
1152 
1154 {
1155  PointerRNA ptr = {0};
1156  int context = 0;
1157 
1158  /* ID Types */
1159  if (tselem->type == TSE_SOME_ID) {
1160  RNA_id_pointer_create(tselem->id, &ptr);
1161 
1162  switch (te->idcode) {
1163  case ID_SCE:
1165  break;
1166  case ID_OB:
1168  break;
1169  case ID_ME:
1170  case ID_CU:
1171  case ID_MB:
1172  case ID_IM:
1173  case ID_LT:
1174  case ID_LA:
1175  case ID_CA:
1176  case ID_KE:
1177  case ID_SPK:
1178  case ID_AR:
1179  case ID_GD:
1180  case ID_LP:
1181  case ID_HA:
1182  case ID_PT:
1183  case ID_VO:
1185  break;
1186  case ID_MA:
1188  break;
1189  case ID_WO:
1191  break;
1192  }
1193  }
1194  else {
1195  switch (tselem->type) {
1196  case TSE_DEFGROUP_BASE:
1197  case TSE_DEFGROUP:
1198  RNA_id_pointer_create(tselem->id, &ptr);
1200  break;
1201  case TSE_CONSTRAINT_BASE:
1202  case TSE_CONSTRAINT: {
1203  TreeElement *bone_te = NULL;
1204  bPoseChannel *pchan = outliner_find_parent_bone(te, &bone_te);
1205 
1206  if (pchan) {
1207  RNA_pointer_create(TREESTORE(bone_te)->id, &RNA_PoseBone, pchan, &ptr);
1209  }
1210  else {
1211  RNA_id_pointer_create(tselem->id, &ptr);
1213  }
1214 
1215  /* Expand the selected constraint in the properties editor. */
1216  if (tselem->type != TSE_CONSTRAINT_BASE) {
1218  }
1219  break;
1220  }
1221  case TSE_MODIFIER_BASE:
1222  case TSE_MODIFIER:
1223  RNA_id_pointer_create(tselem->id, &ptr);
1225 
1226  if (tselem->type != TSE_MODIFIER_BASE) {
1227  Object *ob = (Object *)tselem->id;
1228 
1229  if (ob->type == OB_GPENCIL) {
1231  }
1232  else {
1233  ModifierData *md = (ModifierData *)te->directdata;
1234 
1235  switch ((ModifierType)md->type) {
1238  break;
1239  case eModifierType_Cloth:
1244  case eModifierType_Fluid:
1246  break;
1247  default:
1248  break;
1249  }
1250 
1251  if (context == BCONTEXT_MODIFIER) {
1253  }
1254  }
1255  }
1256  break;
1258  case TSE_GPENCIL_EFFECT:
1259  RNA_id_pointer_create(tselem->id, &ptr);
1261 
1262  if (tselem->type != TSE_GPENCIL_EFFECT_BASE) {
1264  }
1265  break;
1266  case TSE_BONE: {
1267  bArmature *arm = (bArmature *)tselem->id;
1268  Bone *bone = te->directdata;
1269 
1270  RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr);
1272  break;
1273  }
1274  case TSE_EBONE: {
1275  bArmature *arm = (bArmature *)tselem->id;
1276  EditBone *ebone = te->directdata;
1277 
1278  RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &ptr);
1280  break;
1281  }
1282  case TSE_POSE_CHANNEL: {
1283  Object *ob = (Object *)tselem->id;
1284  bArmature *arm = ob->data;
1285  bPoseChannel *pchan = te->directdata;
1286 
1287  RNA_pointer_create(&arm->id, &RNA_PoseBone, pchan, &ptr);
1289  break;
1290  }
1291  case TSE_POSE_BASE: {
1292  Object *ob = (Object *)tselem->id;
1293  bArmature *arm = ob->data;
1294 
1295  RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr);
1297  break;
1298  }
1299  case TSE_R_LAYER_BASE:
1300  case TSE_R_LAYER: {
1301  ViewLayer *view_layer = te->directdata;
1302 
1303  RNA_pointer_create(tselem->id, &RNA_ViewLayer, view_layer, &ptr);
1305  break;
1306  }
1307  case TSE_POSEGRP_BASE:
1308  case TSE_POSEGRP: {
1309  Object *ob = (Object *)tselem->id;
1310  bArmature *arm = ob->data;
1311 
1312  RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr);
1314  break;
1315  }
1316  case TSE_LINKED_PSYS: {
1317  Object *ob = (Object *)tselem->id;
1318  ParticleSystem *psys = psys_get_current(ob);
1319 
1320  RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &ptr);
1322  break;
1323  }
1324  case TSE_GP_LAYER:
1325  RNA_id_pointer_create(tselem->id, &ptr);
1327  break;
1328  }
1329  }
1330 
1331  if (ptr.data) {
1333  }
1334 }
1335 
1336 /* ================================================ */
1337 
1345  const TreeViewContext *tvc,
1346  SpaceOutliner *space_outliner,
1347  TreeElement *te,
1348  TreeStoreElem *tselem,
1349  const bool extend,
1350  const bool recursive,
1351  const bool do_activate_data)
1352 {
1353  /* Always makes active object, except for some specific types. */
1354  if (ELEM(tselem->type,
1355  TSE_SEQUENCE,
1356  TSE_SEQ_STRIP,
1358  TSE_EBONE,
1360  /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several
1361  * objects, we do not want to switch out of edit mode (see T48328 for details). */
1362  }
1363  else if (do_activate_data) {
1365  tvc->scene,
1366  tvc->view_layer,
1367  te,
1368  (extend && tselem->type == TSE_SOME_ID) ? OL_SETSEL_EXTEND :
1370  recursive && tselem->type == TSE_SOME_ID);
1371  }
1372 
1373  if (tselem->type == TSE_SOME_ID) { /* The lib blocks. */
1374  if (do_activate_data == false) {
1375  /* Only select in outliner. */
1376  }
1377  else if (te->idcode == ID_SCE) {
1378  if (tvc->scene != (Scene *)tselem->id) {
1380  }
1381  }
1382  else if ((te->idcode == ID_GR) && (space_outliner->outlinevis != SO_VIEW_LAYER)) {
1383  Collection *gr = (Collection *)tselem->id;
1384 
1385  if (extend) {
1386  int sel = BA_SELECT;
1388  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1389  if (base && (base->flag & BASE_SELECTED)) {
1390  sel = BA_DESELECT;
1391  break;
1392  }
1393  }
1395 
1397  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1398  if (base) {
1399  ED_object_base_select(base, sel);
1400  }
1401  }
1403  }
1404  else {
1406 
1408  Base *base = BKE_view_layer_base_find(tvc->view_layer, object);
1409  /* Object may not be in this scene */
1410  if (base != NULL) {
1411  if ((base->flag & BASE_SELECTED) == 0) {
1413  }
1414  }
1415  }
1417  }
1418 
1421  }
1422  else { /* Rest of types. */
1423  tree_element_activate(C, tvc, te, OL_SETSEL_NORMAL, false);
1424  }
1425  }
1426  else if (do_activate_data) {
1428  C, tvc, te, tselem, extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive);
1429  }
1430 }
1431 
1432 /* Select the item using the set flags */
1434  SpaceOutliner *space_outliner,
1435  TreeElement *te,
1436  const short select_flag)
1437 {
1438  TreeStoreElem *tselem = TREESTORE(te);
1439  const bool activate = select_flag & OL_ITEM_ACTIVATE;
1440  const bool extend = select_flag & OL_ITEM_EXTEND;
1441  const bool activate_data = select_flag & OL_ITEM_SELECT_DATA;
1442 
1443  /* Clear previous active when activating and clear selection when not extending selection */
1444  const short clear_flag = (activate ? TSE_ACTIVE : 0) | (extend ? 0 : TSE_SELECTED);
1445  if (clear_flag) {
1446  outliner_flag_set(&space_outliner->tree, clear_flag, false);
1447  }
1448 
1449  if (select_flag & OL_ITEM_SELECT) {
1450  tselem->flag |= TSE_SELECTED;
1451  }
1452  else {
1453  tselem->flag &= ~TSE_SELECTED;
1454  }
1455 
1456  if (activate) {
1457  TreeViewContext tvc;
1459 
1460  tselem->flag |= TSE_ACTIVE;
1462  &tvc,
1463  space_outliner,
1464  te,
1465  tselem,
1466  extend,
1467  select_flag & OL_ITEM_RECURSIVE,
1468  activate_data || space_outliner->flag & SO_SYNC_SELECT);
1469  }
1470 }
1471 
1474  TreeElement *cursor,
1475  bool selecting)
1476 {
1477  LISTBASE_FOREACH (TreeElement *, te, lb) {
1478  TreeStoreElem *tselem = TREESTORE(te);
1479 
1480  if (selecting) {
1481  tselem->flag |= TSE_SELECTED;
1482  }
1483 
1484  /* Set state for selection */
1485  if (ELEM(te, active, cursor)) {
1486  selecting = !selecting;
1487  }
1488 
1489  if (selecting) {
1490  tselem->flag |= TSE_SELECTED;
1491  }
1492 
1493  /* Don't look inside closed elements */
1494  if (!(tselem->flag & TSE_CLOSED)) {
1495  selecting = do_outliner_range_select_recursive(&te->subtree, active, cursor, selecting);
1496  }
1497  }
1498 
1499  return selecting;
1500 }
1501 
1502 /* Select a range of items between cursor and active element */
1504  SpaceOutliner *space_outliner,
1505  TreeElement *cursor,
1506  const bool extend)
1507 {
1509 
1510  /* If no active element exists, activate the element under the cursor */
1511  if (!active) {
1512  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
1513  return;
1514  }
1515 
1516  TreeStoreElem *tselem = TREESTORE(active);
1517  const bool active_selected = (tselem->flag & TSE_SELECTED);
1518 
1519  if (!extend) {
1520  outliner_flag_set(&space_outliner->tree, TSE_SELECTED, false);
1521  }
1522 
1523  /* Select active if under cursor */
1524  if (active == cursor) {
1525  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT);
1526  return;
1527  }
1528 
1529  /* If active is not selected or visible, select and activate the element under the cursor */
1530  if (!active_selected || !outliner_is_element_visible(active)) {
1531  outliner_item_select(C, space_outliner, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
1532  return;
1533  }
1534 
1535  do_outliner_range_select_recursive(&space_outliner->tree, active, cursor, false);
1536 }
1537 
1538 static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *space_outliner,
1539  const ARegion *region,
1540  float view_co_x)
1541 {
1542  return (view_co_x > region->v2d.cur.xmax - outliner_restrict_columns_width(space_outliner));
1543 }
1544 
1545 bool outliner_is_co_within_mode_column(SpaceOutliner *space_outliner, const float view_mval[2])
1546 {
1547  /* Mode toggles only show in View Layer and Scenes modes. */
1548  if (!ELEM(space_outliner->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
1549  return false;
1550  }
1551 
1552  return space_outliner->flag & SO_MODE_COLUMN && view_mval[0] < UI_UNIT_X;
1553 }
1554 
1556  SpaceOutliner *space_outliner,
1557  const float view_mval[2])
1558 {
1559  ViewLayer *view_layer = CTX_data_view_layer(C);
1560  Object *obact = OBACT(view_layer);
1561 
1562  return outliner_is_co_within_mode_column(space_outliner, view_mval) && obact &&
1563  obact->mode != OB_MODE_OBJECT;
1564 }
1565 
1572  const int mval[2],
1573  const bool extend,
1574  const bool use_range,
1575  const bool deselect_all)
1576 {
1577  ARegion *region = CTX_wm_region(C);
1578  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1579  TreeElement *te;
1580  float view_mval[2];
1581  bool changed = false, rebuild_tree = false;
1582 
1583  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
1584 
1585  if (outliner_is_co_within_restrict_columns(space_outliner, region, view_mval[0])) {
1586  return OPERATOR_CANCELLED;
1587  }
1588  if (outliner_is_co_within_active_mode_column(C, space_outliner, view_mval)) {
1589  return OPERATOR_CANCELLED;
1590  }
1591 
1592  if (!(te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]))) {
1593  if (deselect_all) {
1594  outliner_flag_set(&space_outliner->tree, TSE_SELECTED, false);
1595  changed = true;
1596  }
1597  }
1598  /* Don't allow toggle on scene collection */
1599  else if ((TREESTORE(te)->type != TSE_VIEW_COLLECTION_BASE) &&
1600  outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
1602  }
1603  else {
1604  /* The row may also contain children, if one is hovered we want this instead of current te. */
1605  bool merged_elements = false;
1606  bool is_over_icon = false;
1608  space_outliner, te, view_mval[0], &merged_elements, &is_over_icon);
1609 
1610  /* If the selected icon was an aggregate of multiple elements, run the search popup */
1611  if (merged_elements) {
1612  merged_element_search_menu_invoke(C, te, activate_te);
1613  return OPERATOR_CANCELLED;
1614  }
1615 
1616  TreeStoreElem *activate_tselem = TREESTORE(activate_te);
1617 
1618  if (use_range) {
1619  do_outliner_range_select(C, space_outliner, activate_te, extend);
1620  }
1621  else {
1622  const bool is_over_name_icons = outliner_item_is_co_over_name_icons(activate_te,
1623  view_mval[0]);
1624  /* Always select unless already active and selected */
1625  const bool select = !extend || !(activate_tselem->flag & TSE_ACTIVE &&
1626  activate_tselem->flag & TSE_SELECTED);
1627 
1628  const short select_flag = OL_ITEM_ACTIVATE | (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) |
1629  (is_over_name_icons ? OL_ITEM_SELECT_DATA : 0) |
1630  (extend ? OL_ITEM_EXTEND : 0);
1631 
1632  outliner_item_select(C, space_outliner, activate_te, select_flag);
1633 
1634  /* Only switch properties editor tabs when icons are selected. */
1635  if (is_over_icon) {
1636  outliner_set_properties_tab(C, activate_te, activate_tselem);
1637  }
1638  }
1639 
1640  changed = true;
1641  }
1642 
1643  if (changed) {
1644  if (rebuild_tree) {
1645  ED_region_tag_redraw(region);
1646  }
1647  else {
1649  }
1650 
1651  ED_outliner_select_sync_from_outliner(C, space_outliner);
1652  }
1653 
1654  return OPERATOR_FINISHED;
1655 }
1656 
1657 /* event can enterkey, then it opens/closes */
1659 {
1660  const bool extend = RNA_boolean_get(op->ptr, "extend");
1661  const bool use_range = RNA_boolean_get(op->ptr, "extend_range");
1662  const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
1663  return outliner_item_do_activate_from_cursor(C, event->mval, extend, use_range, deselect_all);
1664 }
1665 
1667 {
1668  ot->name = "Select";
1669  ot->idname = "OUTLINER_OT_item_activate";
1670  ot->description = "Handle mouse clicks to select and activate items";
1671 
1673 
1675 
1677 
1678  PropertyRNA *prop;
1679  RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation");
1680  prop = RNA_def_boolean(
1681  ot->srna, "extend_range", false, "Extend Range", "Select a range from active element");
1683 
1684  prop = RNA_def_boolean(ot->srna,
1685  "deselect_all",
1686  false,
1687  "Deselect On Nothing",
1688  "Deselect all when nothing under the cursor");
1690 }
1691 
1692 /* ****************************************************** */
1693 
1694 /* **************** Box Select Tool ****************** */
1696  SpaceOutliner *space_outliner,
1697  Scene *scene,
1698  rctf *rectf,
1699  TreeElement *te,
1700  bool select)
1701 {
1702  TreeStoreElem *tselem = TREESTORE(te);
1703 
1704  if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
1706  C, space_outliner, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND);
1707  }
1708 
1709  /* Look at its children. */
1710  if (TSELEM_OPEN(tselem, space_outliner)) {
1711  LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
1712  outliner_item_box_select(C, space_outliner, scene, rectf, te_sub, select);
1713  }
1714  }
1715 }
1716 
1718 {
1720  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1721  ARegion *region = CTX_wm_region(C);
1722  rctf rectf;
1723 
1724  const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
1725  const bool select = (sel_op != SEL_OP_SUB);
1726  if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
1727  outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 0);
1728  }
1729 
1731  UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
1732 
1733  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
1734  outliner_item_box_select(C, space_outliner, scene, &rectf, te, select);
1735  }
1736 
1740 
1741  ED_outliner_select_sync_from_outliner(C, space_outliner);
1742 
1743  return OPERATOR_FINISHED;
1744 }
1745 
1746 static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1747 {
1748  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1749  ARegion *region = CTX_wm_region(C);
1750  float view_mval[2];
1751  const bool tweak = RNA_boolean_get(op->ptr, "tweak");
1752 
1754  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
1755 
1756  /* Find element clicked on */
1757  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
1758 
1759  /* Pass through if click is over name or icons, or not tweak event */
1760  if (te && tweak && outliner_item_is_co_over_name_icons(te, view_mval[0])) {
1762  }
1763 
1764  if (outliner_is_co_within_active_mode_column(C, space_outliner, view_mval)) {
1766  }
1767 
1768  return WM_gesture_box_invoke(C, op, event);
1769 }
1770 
1772 {
1773  /* identifiers */
1774  ot->name = "Box Select";
1775  ot->idname = "OUTLINER_OT_select_box";
1776  ot->description = "Use box selection to select tree elements";
1777 
1778  /* api callbacks */
1783 
1785 
1786  /* flags */
1788 
1789  /* properties */
1790  PropertyRNA *prop;
1791 
1792  prop = RNA_def_boolean(
1793  ot->srna, "tweak", false, "Tweak", "Tweak gesture from empty space for box selection");
1795 
1798 }
1799 
1800 /* ****************************************************** */
1801 
1802 /* **************** Walk Select Tool ****************** */
1803 
1804 /* Given a tree element return the rightmost child that is visible in the outliner */
1806  TreeElement *te)
1807 {
1808  while (te->subtree.last) {
1809  if (TSELEM_OPEN(TREESTORE(te), space_outliner)) {
1810  te = te->subtree.last;
1811  }
1812  else {
1813  break;
1814  }
1815  }
1816  return te;
1817 }
1818 
1819 /* Find previous visible element in the tree */
1821 {
1822  if (te->prev) {
1823  te = outliner_find_rightmost_visible_child(space_outliner, te->prev);
1824  }
1825  else if (te->parent) {
1826  /* Use parent if at beginning of list */
1827  te = te->parent;
1828  }
1829 
1830  return te;
1831 }
1832 
1833 /* Recursively search up the tree until a successor to a given element is found */
1835 {
1836  TreeElement *successor = te;
1837  while (successor->parent) {
1838  if (successor->parent->next) {
1839  te = successor->parent->next;
1840  break;
1841  }
1842  successor = successor->parent;
1843  }
1844 
1845  return te;
1846 }
1847 
1848 /* Find next visible element in the tree */
1850 {
1851  TreeStoreElem *tselem = TREESTORE(te);
1852 
1853  if (TSELEM_OPEN(tselem, space_outliner) && te->subtree.first) {
1854  te = te->subtree.first;
1855  }
1856  else if (te->next) {
1857  te = te->next;
1858  }
1859  else {
1861  }
1862 
1863  return te;
1864 }
1865 
1867  TreeElement *te,
1868  bool toggle_all)
1869 {
1870  TreeStoreElem *tselem = TREESTORE(te);
1871 
1872  if (TSELEM_OPEN(tselem, space_outliner)) {
1873  outliner_item_openclose(space_outliner, te, false, toggle_all);
1874  }
1875  /* Only walk up a level if the element is closed and not toggling expand */
1876  else if (!toggle_all && te->parent) {
1877  te = te->parent;
1878  }
1879 
1880  return te;
1881 }
1882 
1884  TreeElement *te,
1885  bool toggle_all)
1886 {
1887  TreeStoreElem *tselem = TREESTORE(te);
1888 
1889  /* Only walk down a level if the element is open and not toggling expand */
1890  if (!toggle_all && TSELEM_OPEN(tselem, space_outliner) && !BLI_listbase_is_empty(&te->subtree)) {
1891  te = te->subtree.first;
1892  }
1893  else {
1894  outliner_item_openclose(space_outliner, te, true, toggle_all);
1895  }
1896 
1897  return te;
1898 }
1899 
1901  TreeElement *te,
1902  const int direction,
1903  const bool extend,
1904  const bool toggle_all)
1905 {
1906  TreeStoreElem *tselem = TREESTORE(te);
1907 
1908  switch (direction) {
1909  case UI_SELECT_WALK_UP:
1910  te = outliner_find_previous_element(space_outliner, te);
1911  break;
1912  case UI_SELECT_WALK_DOWN:
1913  te = outliner_find_next_element(space_outliner, te);
1914  break;
1915  case UI_SELECT_WALK_LEFT:
1916  te = outliner_walk_left(space_outliner, te, toggle_all);
1917  break;
1918  case UI_SELECT_WALK_RIGHT:
1919  te = outliner_walk_right(space_outliner, te, toggle_all);
1920  break;
1921  }
1922 
1923  /* If new element is already selected, deselect the previous element */
1924  TreeStoreElem *tselem_new = TREESTORE(te);
1925  if (extend) {
1926  tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
1927  (tselem->flag | TSE_SELECTED);
1928  }
1929 
1930  return te;
1931 }
1932 
1933 /* Find the active element to walk from, or set one if none exists.
1934  * Changed is set to true if the active element is found, or false if it was set */
1935 static TreeElement *find_walk_select_start_element(SpaceOutliner *space_outliner, bool *changed)
1936 {
1937  TreeElement *active_te = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE);
1938  *changed = false;
1939 
1940  /* If no active element exists, use the first element in the tree */
1941  if (!active_te) {
1942  active_te = space_outliner->tree.first;
1943  *changed = true;
1944  }
1945 
1946  /* If the active element is not visible, activate the first visible parent element */
1947  if (!outliner_is_element_visible(active_te)) {
1948  while (!outliner_is_element_visible(active_te)) {
1949  active_te = active_te->parent;
1950  }
1951  *changed = true;
1952  }
1953 
1954  return active_te;
1955 }
1956 
1957 /* Scroll the outliner when the walk element reaches the top or bottom boundary */
1958 static void outliner_walk_scroll(SpaceOutliner *space_outliner, ARegion *region, TreeElement *te)
1959 {
1960  /* Account for the header height */
1961  int y_max = region->v2d.cur.ymax - UI_UNIT_Y;
1962  int y_min = region->v2d.cur.ymin;
1963 
1964  /* Scroll if walked position is beyond the border */
1965  if (te->ys > y_max) {
1966  outliner_scroll_view(space_outliner, region, te->ys - y_max);
1967  }
1968  else if (te->ys < y_min) {
1969  outliner_scroll_view(space_outliner, region, -(y_min - te->ys));
1970  }
1971 }
1972 
1974 {
1975  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1976  ARegion *region = CTX_wm_region(C);
1977 
1978  const short direction = RNA_enum_get(op->ptr, "direction");
1979  const bool extend = RNA_boolean_get(op->ptr, "extend");
1980  const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all");
1981 
1982  bool changed;
1983  TreeElement *active_te = find_walk_select_start_element(space_outliner, &changed);
1984 
1985  /* If finding the active element did not modify the selection, proceed to walk */
1986  if (!changed) {
1987  active_te = do_outliner_select_walk(space_outliner, active_te, direction, extend, toggle_all);
1988  }
1989 
1991  space_outliner,
1992  active_te,
1993  OL_ITEM_SELECT | OL_ITEM_ACTIVATE | (extend ? OL_ITEM_EXTEND : 0));
1994 
1995  /* Scroll outliner to focus on walk element */
1996  outliner_walk_scroll(space_outliner, region, active_te);
1997 
1998  ED_outliner_select_sync_from_outliner(C, space_outliner);
1999  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
2000 
2001  return OPERATOR_FINISHED;
2002 }
2003 
2005 {
2006  /* identifiers */
2007  ot->name = "Walk Select";
2008  ot->idname = "OUTLINER_OT_select_walk";
2009  ot->description = "Use walk navigation to select tree elements";
2010 
2011  /* api callbacks */
2014 
2016 
2017  /* properties */
2018  PropertyRNA *prop;
2020  prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk");
2022  prop = RNA_def_boolean(
2023  ot->srna, "toggle_all", false, "Toggle All", "Toggle open/close hierarchy");
2025 }
2026 
2027 /* ****************************************************** */
#define PBONE_SELECTABLE(arm, bone)
Definition: BKE_armature.h:343
#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:5540
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
Definition: context.c:836
struct LayerCollection * CTX_data_layer_collection(const bContext *C)
Definition: context.c:1077
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:709
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:751
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
Definition: gpencil.c:1698
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:638
void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer)
Definition: layer.c:403
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:394
#define BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:430
void BKE_view_layer_base_select_and_set_active(struct ViewLayer *view_layer, struct Base *selbase)
Definition: layer.c:412
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.c:2487
bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
Definition: object.c:1982
void BKE_object_modifier_set_active(struct Object *ob, struct ModifierData *md)
Definition: object.c:1284
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.c:2552
bool BKE_object_is_in_editmode(const struct Object *ob)
struct ParticleSystem * psys_get_current(struct Object *ob)
Definition: particle.c:645
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_shaderfx_panel_expand(struct ShaderFxData *fx)
Definition: shader_fx.c:181
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
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:83
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
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:599
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
@ ID_CA
Definition: DNA_ID_enums.h:68
@ ID_AR
Definition: DNA_ID_enums.h:78
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_VO
Definition: DNA_ID_enums.h:95
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_KE
Definition: DNA_ID_enums.h:70
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_GD
Definition: DNA_ID_enums.h:83
@ ID_LP
Definition: DNA_ID_enums.h:92
@ ID_HA
Definition: DNA_ID_enums.h:93
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_GR
Definition: DNA_ID_enums.h:77
@ ID_SPK
Definition: DNA_ID_enums.h:75
@ ID_MB
Definition: DNA_ID_enums.h:62
@ ID_LT
Definition: DNA_ID_enums.h:66
@ ID_OB
Definition: DNA_ID_enums.h:59
@ ID_PT
Definition: DNA_ID_enums.h:94
@ ID_CU
Definition: DNA_ID_enums.h:61
@ 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_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
@ SCE_OBJECT_MODE_LOCK
#define FIRSTBASE(_view_layer)
#define OBACT(_view_layer)
@ SPACE_PROPERTIES
@ SO_SYNC_SELECT
@ SO_MODE_COLUMN
@ SO_VIEW_LAYER
@ SO_SCENES
@ 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:61
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, const int context)
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:391
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode)
Definition: object_select.c:98
@ EM_NO_CONTEXT
Definition: ED_object.h:205
@ EM_FREEDATA
Definition: ED_object.h:204
bool ED_object_editmode_exit_ex(struct Main *bmain, struct Scene *scene, struct Object *obedit, int flag)
Definition: object_edit.c:676
bool ED_object_editmode_enter_ex(struct Main *bmain, struct Scene *scene, struct Object *ob, int flag)
Definition: object_edit.c:762
bool ED_object_mode_set(struct bContext *C, eObjectMode mode)
Definition: object_modes.c:235
@ BA_DESELECT
Definition: ED_object.h:146
@ BA_SELECT
Definition: ED_object.h:147
void ED_outliner_select_sync_from_object_tag(struct bContext *C)
Definition: outliner_sync.c:56
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:686
bool ED_operator_outliner_active(struct bContext *C)
Definition: screen_ops.c:259
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
#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)
void ED_undo_group_begin(struct bContext *C)
Definition: ed_undo.c:105
void ED_undo_push(struct bContext *C, const char *str)
Definition: ed_undo.c:117
void ED_undo_group_end(struct bContext *C)
Definition: ed_undo.c:111
_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.
StructRNA RNA_Bone
StructRNA RNA_Armature
StructRNA RNA_ViewLayer
StructRNA RNA_ParticleSystem
StructRNA RNA_EditBone
StructRNA RNA_PoseBone
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
#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:337
#define NA_ACTIVATED
Definition: WM_types.h:468
#define ND_DRAW
Definition: WM_types.h:362
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NC_SCREEN
Definition: WM_types.h:278
#define ND_MODE
Definition: WM_types.h:345
#define ND_OB_SELECT
Definition: WM_types.h:342
#define NC_SCENE
Definition: WM_types.h:279
#define ND_MODIFIER
Definition: WM_types.h:363
#define NA_EDITED
Definition: WM_types.h:462
#define ND_PARTICLE
Definition: WM_types.h:366
#define NS_MODE_OBJECT
Definition: WM_types.h:441
#define NC_MATERIAL
Definition: WM_types.h:281
#define ND_CONSTRAINT
Definition: WM_types.h:365
#define NC_GPENCIL
Definition: WM_types.h:300
#define ND_BONE_ACTIVE
Definition: WM_types.h:360
#define ND_TRANSFORM
Definition: WM_types.h:357
#define ND_LAYER
Definition: WM_types.h:350
#define NS_MODE_POSE
Definition: WM_types.h:450
#define NC_OBJECT
Definition: WM_types.h:280
#define ND_SHADING_LINKS
Definition: WM_types.h:379
#define NS_LAYER_COLLECTION
Definition: WM_types.h:458
#define NA_SELECTED
Definition: WM_types.h:467
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)
void activate(bool forceActivation=false) const
#define SELECT
Scene scene
const Depsgraph * depsgraph
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static void area(int d1, int d2, int e1, int e2, float weights[2])
bool active
all scheduled work for the GPU.
void outliner_item_openclose(SpaceOutliner *space_outliner, TreeElement *te, bool open, bool toggle_all)
bool outliner_flag_set(ListBase *lb, short flag, short set)
@ 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
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)
float outliner_restrict_columns_width(const struct SpaceOutliner *space_outliner)
#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)
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 void outliner_item_box_select(bContext *C, SpaceOutliner *space_outliner, Scene *scene, rctf *rectf, TreeElement *te, bool select)
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)
bPoseChannel * outliner_find_parent_bone(TreeElement *te, TreeElement **r_bone_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:94
bool ED_object_posemode_exit_ex(struct Main *bmain, Object *ob)
Definition: pose_edit.c:129
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
struct SELECTID_Context context
Definition: select_engine.c:47
Editing * SEQ_editing_get(Scene *scene, bool alloc)
Definition: sequencer.c:232
void SEQ_select_active_set(Scene *scene, Sequence *seq)
Definition: strip_select.c:46
struct Base * next
short flag
struct Object * object
struct Bone * next
ListBase childbase
struct EditBone * next
Definition: BKE_armature.h:49
ListBase * seqbasep
Definition: DNA_ID.h:273
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase wm
Definition: BKE_main.h:175
ListBase objects
Definition: BKE_main.h:148
struct bPose * pose
char * matbits
unsigned short actdef
void * data
void * data
Definition: RNA_types.h:52
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
void * directdata
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
struct bPoseChannel * next
ListBase chanbase
int active_group
ListBase areabase
float xmax
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int mval[2]
Definition: WM_types.h:583
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct PointerRNA * ptr
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
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:3157
wmOperatorType * ot
Definition: wm_files.c:3156
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:2257
void WM_window_set_active_view_layer(wmWindow *win, ViewLayer *view_layer)
Definition: wm_window.c:2306
void WM_windows_scene_data_sync(const ListBase *win_lb, Scene *scene)
Definition: wm_window.c:2208
Scene * WM_window_get_active_scene(const wmWindow *win)
Definition: wm_window.c:2249