Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_select.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c428
1 files changed, 211 insertions, 217 deletions
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 12b9d273a47..b9222e62bb0 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -44,12 +44,15 @@
#include "BLI_listbase.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_group.h"
#include "BKE_object.h"
+#include "BKE_layer.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
#include "BKE_armature.h"
+#include "DEG_depsgraph.h"
+
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -68,61 +71,12 @@
#include "outliner_intern.h"
-/* ****************************************************** */
-/* Outliner Selection (gray-blue highlight for rows) */
-
-static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool changed = false;
-
- for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) {
- tselem = TREESTORE(te);
-
- /* if we've encountered the right item, set its 'Outliner' selection status */
- if (*index == 0) {
- /* this should be the last one, so no need to do anything with index */
- if ((te->flag & TE_ICONROW) == 0) {
- /* -1 value means toggle testing for now... */
- if (*selecting == -1) {
- if (tselem->flag & TSE_SELECTED)
- *selecting = 0;
- else
- *selecting = 1;
- }
-
- /* set selection */
- if (*selecting)
- tselem->flag |= TSE_SELECTED;
- else
- tselem->flag &= ~TSE_SELECTED;
-
- changed |= true;
- }
- }
- else if (TSELEM_OPEN(tselem, soops)) {
- /* Only try selecting sub-elements if we haven't hit the right element yet
- *
- * Hack warning:
- * Index must be reduced before supplying it to the sub-tree to try to do
- * selection, however, we need to increment it again for the next loop to
- * function correctly
- */
- (*index)--;
- changed |= outliner_select(soops, &te->subtree, index, selecting);
- (*index)++;
- }
- }
-
- return changed;
-}
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
static eOLDrawState tree_element_active_renderlayer(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Scene *sce;
@@ -132,11 +86,11 @@ static eOLDrawState tree_element_active_renderlayer(
sce = (Scene *)tselem->id;
if (set != OL_SETSEL_NONE) {
- sce->r.actlay = tselem->nr;
+ sce->active_view_layer = tselem->nr;
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, sce);
}
else {
- return sce->r.actlay == tselem->nr;
+ return sce->active_view_layer == tselem->nr;
}
return OL_DRAWSEL_NONE;
}
@@ -146,14 +100,14 @@ static eOLDrawState tree_element_active_renderlayer(
* CTRL+LMB: Select/Deselect object and all children.
* CTRL+SHIFT+LMB: Add/Remove object and all children.
*/
-static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select)
+static void do_outliner_object_select_recursive(ViewLayer *view_layer, Object *ob_parent, bool select)
{
Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
Object *ob = base->object;
- if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ if ((((base->flag & BASE_VISIBLED) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) {
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
}
}
@@ -184,7 +138,7 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p
}
static eOLDrawState tree_element_set_active_object(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set, bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
@@ -198,7 +152,7 @@ static eOLDrawState tree_element_set_active_object(
}
else {
ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == OBACT) {
+ if (ob == OBACT(view_layer)) {
return OL_DRAWSEL_NONE;
}
}
@@ -208,34 +162,34 @@ static eOLDrawState tree_element_set_active_object(
sce = (Scene *)outliner_search_back(soops, te, ID_SCE);
if (sce && scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
scene = sce;
}
/* find associated base in current scene */
- base = BKE_scene_base_find(scene, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
if (base) {
if (set == OL_SETSEL_EXTEND) {
/* swap select */
- if (base->flag & SELECT)
- ED_base_object_select(base, BA_DESELECT);
+ if (base->flag & BASE_SELECTED)
+ ED_object_base_select(base, BA_DESELECT);
else
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
else {
/* deleselect all */
- BKE_scene_base_deselect_all(scene);
- ED_base_object_select(base, BA_SELECT);
+ BKE_view_layer_base_deselect_all(view_layer);
+ ED_object_base_select(base, BA_SELECT);
}
if (recursive) {
/* Recursive select/deselect for Object hierarchies */
- do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0);
+ do_outliner_object_select_recursive(view_layer, ob, (base->flag & BASE_SELECTED) != 0);
}
- if (C) {
- ED_base_object_activate(C, base); /* adds notifier */
+ if (set != OL_SETSEL_NONE) {
+ ED_object_base_activate(C, base); /* adds notifier */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -247,7 +201,7 @@ static eOLDrawState tree_element_set_active_object(
}
static eOLDrawState tree_element_active_material(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
TreeElement *tes;
@@ -256,7 +210,7 @@ static eOLDrawState tree_element_active_material(
/* we search for the object parent */
ob = (Object *)outliner_search_back(soops, te, ID_OB);
// note: ob->matbits can be NULL when a local object points to a library mesh.
- if (ob == NULL || ob != OBACT || ob->matbits == NULL) {
+ if (ob == NULL || ob != OBACT(view_layer) || ob->matbits == NULL) {
return OL_DRAWSEL_NONE; /* just paranoia */
}
@@ -293,19 +247,19 @@ static eOLDrawState tree_element_active_material(
/* Tagging object for update seems a bit stupid here, but looks like we have to do it
* for render views to update. See T42973.
* Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */
- DAG_id_tag_update((ID *)ob, OB_RECALC_OB);
+ DEG_id_tag_update((ID *)ob, OB_RECALC_OB);
WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_active_texture(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
TreeStoreElem /* *tselem,*/ *tselemp;
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
SpaceButs *sbuts = NULL;
if (ob == NULL) {
@@ -387,14 +341,14 @@ static eOLDrawState tree_element_active_texture(
static eOLDrawState tree_element_active_lamp(
- bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
+ bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
Object *ob;
/* we search for the object parent */
ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == NULL || ob != OBACT) {
+ if (ob == NULL || ob != OBACT(view_layer)) {
/* just paranoia */
return OL_DRAWSEL_NONE;
}
@@ -410,7 +364,7 @@ static eOLDrawState tree_element_active_lamp(
}
static eOLDrawState tree_element_active_camera(
- bContext *UNUSED(C), Scene *scene, SpaceOops *soops,
+ bContext *UNUSED(C), Scene *scene, ViewLayer *UNUSED(sl), SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
@@ -423,7 +377,7 @@ static eOLDrawState tree_element_active_camera(
}
static eOLDrawState tree_element_active_world(
- bContext *C, Scene *scene, SpaceOops *UNUSED(soops),
+ bContext *C, Scene *scene, ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *te, const eOLSetState set)
{
TreeElement *tep;
@@ -440,7 +394,7 @@ static eOLDrawState tree_element_active_world(
if (set != OL_SETSEL_NONE) {
/* make new scene active */
if (sce && scene != sce) {
- ED_screen_set_scene(C, CTX_wm_screen(C), sce);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), sce);
}
}
@@ -456,7 +410,7 @@ static eOLDrawState tree_element_active_world(
}
static eOLDrawState tree_element_active_defgroup(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob;
@@ -466,21 +420,20 @@ static eOLDrawState tree_element_active_defgroup(
BLI_assert(te->index + 1 >= 0);
ob->actdef = te->index + 1;
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
}
else {
- if (ob == OBACT) {
+ if (ob == OBACT(view_layer))
if (ob->actdef == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
- }
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_active_posegroup(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
@@ -491,7 +444,7 @@ static eOLDrawState tree_element_active_posegroup(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT(view_layer) && ob->pose) {
if (ob->pose->active_group == te->index + 1) {
return OL_DRAWSEL_NORMAL;
}
@@ -501,7 +454,7 @@ static eOLDrawState tree_element_active_posegroup(
}
static eOLDrawState tree_element_active_posechannel(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
Object *ob = (Object *)tselem->id;
bArmature *arm = ob->data;
@@ -535,7 +488,7 @@ static eOLDrawState tree_element_active_posechannel(
}
}
else {
- if (ob == OBACT && ob->pose) {
+ if (ob == OBACT(view_layer) && ob->pose) {
if (pchan->bone->flag & BONE_SELECTED) {
return OL_DRAWSEL_NORMAL;
}
@@ -545,14 +498,14 @@ static eOLDrawState tree_element_active_posechannel(
}
static eOLDrawState tree_element_active_bone(
- bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
+ bContext *C, ViewLayer *view_layer, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
bArmature *arm = (bArmature *)tselem->id;
Bone *bone = te->directdata;
if (set != OL_SETSEL_NONE) {
if (!(bone->flag & BONE_HIDDEN_P)) {
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (ob) {
if (set != OL_SETSEL_EXTEND) {
/* single select forces all other bones to get unselected */
@@ -581,7 +534,7 @@ static eOLDrawState tree_element_active_bone(
}
}
else {
- Object *ob = OBACT;
+ Object *ob = OBACT(view_layer);
if (ob && ob->data == arm) {
if (bone->flag & BONE_SELECTED) {
@@ -654,7 +607,7 @@ static eOLDrawState tree_element_active_ebone(
}
static eOLDrawState tree_element_active_modifier(
- bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -682,7 +635,7 @@ static eOLDrawState tree_element_active_psys(
}
static int tree_element_active_constraint(
- bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
if (set != OL_SETSEL_NONE) {
Object *ob = (Object *)tselem->id;
@@ -695,7 +648,7 @@ static int tree_element_active_constraint(
}
static eOLDrawState tree_element_active_text(
- bContext *UNUSED(C), Scene *UNUSED(scene), SpaceOops *UNUSED(soops),
+ bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), SpaceOops *UNUSED(soops),
TreeElement *UNUSED(te), int UNUSED(set))
{
// XXX removed
@@ -703,10 +656,10 @@ static eOLDrawState tree_element_active_text(
}
static eOLDrawState tree_element_active_pose(
- bContext *C, Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
+ bContext *C, Scene *scene, ViewLayer *view_layer, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
Object *ob = (Object *)tselem->id;
- Base *base = BKE_scene_base_find(scene, ob);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
if (base == NULL) {
/* Armature not instantiated in current scene (e.g. inside an appended group...). */
@@ -792,7 +745,7 @@ static eOLDrawState tree_element_active_sequence_dup(
}
static eOLDrawState tree_element_active_keymap_item(
- bContext *UNUSED(C), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+ bContext *UNUSED(C), Scene *UNUSED(scene), ViewLayer *UNUSED(sl), TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
{
wmKeyMapItem *kmi = te->directdata;
@@ -808,84 +761,127 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState tree_element_active_collection(
+ bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ /* sometimes the renderlayer has no LayerCollection at all */
+ if (active == NULL) {
+ return OL_DRAWSEL_NONE;
+ }
+
+ if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
+ (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
+ {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ /* don't allow selecting a scene collection, it can have multiple layer collection
+ * instances (which one would the user want to be selected then?) */
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *layer_collection = te->directdata;
+
+ switch (layer_collection->scene_collection->type) {
+ case COLLECTION_TYPE_NONE:
+ case COLLECTION_TYPE_GROUP_INTERNAL:
+ {
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
+ const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
+
+ if (collection_index > -1) {
+ view_layer->active_collection = collection_index;
+ }
+ break;
+ }
+ default:
+ BLI_assert(!"Collection type not fully implemented");
+ }
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ return OL_DRAWSEL_NONE;
+}
+
/* ---------------------------------------------- */
/* generic call for ID data check or make/check active in UI */
-eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te,
+eOLDrawState tree_element_active(bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops, TreeElement *te,
const eOLSetState set, const bool handle_all_types)
{
switch (te->idcode) {
/* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple
- * selection. See do_outliner_item_activate_from_cursor. */
+ * selection. See do_outliner_item_activate. */
case ID_OB:
if (handle_all_types) {
- return tree_element_set_active_object(C, scene, soops, te, set, false);
+ return tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
}
break;
case ID_MA:
- return tree_element_active_material(C, scene, soops, te, set);
+ return tree_element_active_material(C, scene, view_layer, soops, te, set);
case ID_WO:
- return tree_element_active_world(C, scene, soops, te, set);
+ return tree_element_active_world(C, scene, view_layer, soops, te, set);
case ID_LA:
- return tree_element_active_lamp(C, scene, soops, te, set);
+ return tree_element_active_lamp(C, scene, view_layer, soops, te, set);
case ID_TE:
- return tree_element_active_texture(C, scene, soops, te, set);
+ return tree_element_active_texture(C, scene, view_layer, soops, te, set);
case ID_TXT:
- return tree_element_active_text(C, scene, soops, te, set);
+ return tree_element_active_text(C, scene, view_layer, soops, te, set);
case ID_CA:
- return tree_element_active_camera(C, scene, soops, te, set);
+ return tree_element_active_camera(C, scene, view_layer, soops, te, set);
}
return OL_DRAWSEL_NONE;
}
/**
* Generic call for non-id data to make/check active in UI
- *
- * \note Context can be NULL when ``(set == OL_SETSEL_NONE)``
*/
eOLDrawState tree_element_type_active(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive)
{
switch (tselem->type) {
case TSE_DEFGROUP:
- return tree_element_active_defgroup(C, scene, te, tselem, set);
+ return tree_element_active_defgroup(C, view_layer, te, tselem, set);
case TSE_BONE:
- return tree_element_active_bone(C, scene, te, tselem, set, recursive);
+ return tree_element_active_bone(C, view_layer, te, tselem, set, recursive);
case TSE_EBONE:
return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
case TSE_MODIFIER:
- return tree_element_active_modifier(C, te, tselem, set);
+ return tree_element_active_modifier(C, scene, view_layer, te, tselem, set);
case TSE_LINKED_OB:
if (set != OL_SETSEL_NONE) {
- tree_element_set_active_object(C, scene, soops, te, set, false);
+ tree_element_set_active_object(C, scene, view_layer, soops, te, set, false);
}
- else if (tselem->id == (ID *)OBACT) {
+ else if (tselem->id == (ID *)OBACT(view_layer)) {
return OL_DRAWSEL_NORMAL;
}
break;
case TSE_LINKED_PSYS:
return tree_element_active_psys(C, scene, te, tselem, set);
case TSE_POSE_BASE:
- return tree_element_active_pose(C, scene, te, tselem, set);
+ return tree_element_active_pose(C, scene, view_layer, te, tselem, set);
case TSE_POSE_CHANNEL:
- return tree_element_active_posechannel(C, scene, te, tselem, set, recursive);
+ return tree_element_active_posechannel(C, scene, view_layer, te, tselem, set, recursive);
case TSE_CONSTRAINT:
- return tree_element_active_constraint(C, te, tselem, set);
+ return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- return tree_element_active_renderlayer(C, te, tselem, set);
+ return tree_element_active_renderlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
- return tree_element_active_posegroup(C, scene, te, tselem, set);
+ return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
return tree_element_active_sequence(C, scene, te, tselem, set);
case TSE_SEQUENCE_DUP:
return tree_element_active_sequence_dup(scene, te, tselem, set);
case TSE_KEYMAP_ITEM:
- return tree_element_active_keymap_item(C, te, tselem, set);
+ return tree_element_active_keymap_item(C, scene, view_layer, te, tselem, set);
case TSE_GP_LAYER:
- //return tree_element_active_gplayer(C, scene, te, tselem, set);
+ //return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
-
+ case TSE_SCENE_COLLECTION:
+ case TSE_LAYER_COLLECTION:
+ return tree_element_active_collection(C, te, tselem, set);
}
return OL_DRAWSEL_NONE;
}
@@ -899,16 +895,16 @@ eOLDrawState tree_element_type_active(
* Needed to run from operators accessed from a menu.
*/
static void do_outliner_item_activate_tree_element(
- bContext *C, Scene *scene, SpaceOops *soops,
+ bContext *C, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
TreeElement *te, TreeStoreElem *tselem,
- bool extend, bool recursive)
+ const bool extend, const bool recursive)
{
/* always makes active object, except for some specific types.
* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
* to switch out of edit mode (see T48328 for details). */
- if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
tree_element_set_active_object(
- C, scene, soops, te,
+ C, scene, view_layer, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
recursive && tselem->type == 0);
}
@@ -917,100 +913,101 @@ static void do_outliner_item_activate_tree_element(
/* editmode? */
if (te->idcode == ID_SCE) {
if (scene != (Scene *)tselem->id) {
- ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
+ WM_window_change_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
}
}
else if (te->idcode == ID_GR) {
Group *gr = (Group *)tselem->id;
- GroupObject *gob;
if (extend) {
int sel = BA_SELECT;
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (gob->ob->flag & SELECT) {
+ FOREACH_GROUP_BASE(gr, base)
+ {
+ if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
break;
}
}
+ FOREACH_GROUP_BASE_END
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
+ FOREACH_GROUP_OBJECT_END
}
else {
- BKE_scene_base_deselect_all(scene);
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->flag & SELECT) == 0)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
+ /* Object may not be in this scene */
+ if (base != NULL) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
}
+ FOREACH_GROUP_OBJECT_END
}
-
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
}
else { // rest of types
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
+ tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
}
}
else {
- tree_element_type_active(
- C, scene, soops, te, tselem,
- extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive);
+ tree_element_type_active(C, scene, view_layer, soops, te, tselem,
+ extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive);
}
}
/**
- * Activates tree items, also handles clicking on arrows.
+ * \param extend: Don't deselect other items, only modify \a te.
+ * \param toggle: Select \a te when not selected, deselect when selected.
*/
-static bool do_outliner_item_activate_from_cursor(
- bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, bool extend, bool recursive, const float mval[2])
+void outliner_item_select(SpaceOops *soops, const TreeElement *te, const bool extend, const bool toggle)
{
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
- bool openclose = false;
-
- /* open close icon */
- if ((te->flag & TE_ICONROW) == 0) { // hidden icon, no open/close
- if (mval[0] > te->xs && mval[0] < te->xs + UI_UNIT_X)
- openclose = true;
- }
-
- if (openclose) {
- /* all below close/open? */
- if (extend) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_set_flag(&te->subtree, TSE_CLOSED, !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
- else tselem->flag |= TSE_CLOSED;
-
- }
-
- return true;
- }
- /* name and first icon */
- else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
- do_outliner_item_activate_tree_element(
- C, scene, soops,
- te, tselem,
- extend, recursive);
- return true;
- }
+ TreeStoreElem *tselem = TREESTORE(te);
+ const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
+
+ if (extend == false) {
+ outliner_set_flag(&soops->tree, TSE_SELECTED, false);
}
-
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) {
- return true;
- }
+ tselem->flag = new_flag;
+}
+
+static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (toggle_children) {
+ tselem->flag &= ~TSE_CLOSED;
+
+ const bool all_opened = !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1);
+ outliner_set_flag(&te->subtree, TSE_CLOSED, all_opened);
+ }
+ else {
+ tselem->flag ^= TSE_CLOSED;
}
- return false;
+}
+
+static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
+{
+ return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
+}
+
+static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
+{
+ return ((soops->outlinevis != SO_DATABLOCKS) &&
+ !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
+ (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
/**
@@ -1024,10 +1021,11 @@ void outliner_item_do_activate_from_tree_element(
bool extend, bool recursive)
{
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
do_outliner_item_activate_tree_element(
- C, scene, soops,
+ C, scene, view_layer, soops,
te, tselem,
extend, recursive);
}
@@ -1041,56 +1039,52 @@ int outliner_item_do_activate_from_cursor(
bContext *C, const int mval[2],
bool extend, bool recursive)
{
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
- float fmval[2];
+ float view_mval[2];
+ bool changed = false, rebuild_tree = false;
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
- if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
- !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX))
- {
+ if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
return OPERATOR_CANCELLED;
}
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) {
- break;
- }
+ if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
+ /* skip */
}
-
- if (te) {
- ED_undo_push(C, "Outliner click event");
+ else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ outliner_item_toggle_closed(te, extend);
+ changed = true;
+ rebuild_tree = true;
}
else {
- short selecting = -1;
- int row;
-
- /* get row number - 100 here is just a dummy value since we don't need the column */
- UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET,
- fmval[0], fmval[1], NULL, &row);
-
- /* select relevant row */
- if (outliner_select(soops, &soops->tree, &row, &selecting)) {
-
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ /* the row may also contain children, if one is hovered we want this instead of current te */
+ TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
+ TreeStoreElem *activate_tselem = TREESTORE(activate_te);
+
+ outliner_item_select(soops, activate_te, extend, extend);
+ do_outliner_item_activate_tree_element(C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
+ changed = true;
+ }
+
+ if (changed) {
+ if (!rebuild_tree) {
+ /* only needs to redraw, no rebuild */
soops->storeflag |= SO_TREESTORE_REDRAW;
-
- /* no need for undo push here, only changing outliner data which is
- * scene level - campbell */
- /* ED_undo_push(C, "Outliner selection event"); */
}
+ ED_undo_push(C, "Outliner selection change");
+ ED_region_tag_redraw(ar);
}
-
- ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
/* event can enterkey, then it opens/closes */
-static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event)
+static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bool extend = RNA_boolean_get(op->ptr, "extend");
bool recursive = RNA_boolean_get(op->ptr, "recursive");
@@ -1103,7 +1097,7 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
ot->idname = "OUTLINER_OT_item_activate";
ot->description = "Handle mouse clicks to activate/select items";
- ot->invoke = outliner_item_activate;
+ ot->invoke = outliner_item_activate_invoke;
ot->poll = ED_operator_outliner_active;