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:
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h23
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c181
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c14
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c8
4 files changed, 129 insertions, 97 deletions
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 32a67d57d0f..dae8f8a91ce 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -216,6 +216,16 @@ typedef struct TreeViewContext {
Object *ob_pose;
} TreeViewContext;
+typedef enum TreeItemSelectAction {
+ OL_ITEM_DESELECT = 0, /* Deselect the item */
+ OL_ITEM_SELECT = (1 << 0), /* Select the item */
+ OL_ITEM_SELECT_DATA = (1 << 1), /* Select object data */
+ OL_ITEM_ACTIVATE = (1 << 2), /* Activate the item */
+ OL_ITEM_EXTEND = (1 << 3), /* Extend the current selection */
+ OL_ITEM_RECURSIVE = (1 << 4), /* Select recursively */
+ OL_ITEM_TOGGLE_MODE = (1 << 5) /* Temporary */
+} TreeItemSelectAction;
+
/* outliner_tree.c ----------------------------------------------- */
void outliner_free_tree(ListBase *tree);
@@ -268,20 +278,17 @@ eOLDrawState tree_element_active(struct bContext *C,
const eOLSetState set,
const bool handle_all_types);
-void outliner_item_do_activate_from_tree_element(
- struct bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive);
-
-void outliner_item_select(struct SpaceOutliner *soops,
- const struct TreeElement *te,
- const bool extend,
- const bool toggle);
+void outliner_item_select(struct bContext *C,
+ struct SpaceOutliner *soops,
+ struct TreeElement *te,
+ const short select_flag);
void outliner_object_mode_toggle(struct bContext *C,
Scene *scene,
ViewLayer *view_layer,
Base *base);
-void outliner_element_activate(struct SpaceOutliner *soops, struct TreeStoreElem *tselem);
+void outliner_set_walk_element(struct SpaceOutliner *soops, struct TreeStoreElem *tselem);
bool outliner_item_is_co_over_name_icons(const TreeElement *te, float view_co_x);
bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_co_x);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 40fb5c7be3a..d9db4edc88a 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -111,7 +111,7 @@ static bool do_outliner_activate_common(bContext *C,
* If extend is used, we try to have the other compatible selected objects in the new mode as well.
* Otherwise only the new object will be active, selected and in the edit mode.
*/
-static void do_outliner_activate_obdata(
+static void do_outliner_item_editmode_toggle(
bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
{
Main *bmain = CTX_data_main(C);
@@ -159,7 +159,7 @@ static void do_outliner_activate_obdata(
}
}
-static void do_outliner_activate_pose(
+static void do_outliner_item_posemode_toggle(
bContext *C, Scene *scene, ViewLayer *view_layer, Base *base, const bool extend)
{
Main *bmain = CTX_data_main(C);
@@ -214,10 +214,42 @@ void outliner_object_mode_toggle(bContext *C, Scene *scene, ViewLayer *view_laye
{
Object *obact = OBACT(view_layer);
if (obact->mode & OB_MODE_EDIT) {
- do_outliner_activate_obdata(C, scene, view_layer, base, true);
+ do_outliner_item_editmode_toggle(C, scene, view_layer, base, true);
}
else if (obact->mode & OB_MODE_POSE) {
- do_outliner_activate_pose(C, scene, view_layer, base, true);
+ do_outliner_item_posemode_toggle(C, scene, view_layer, base, true);
+ }
+}
+
+/* Toggle the item's interaction mode if supported */
+static void outliner_item_mode_toggle(bContext *C,
+ TreeViewContext *tvc,
+ TreeElement *te,
+ const bool extend)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == 0) {
+ if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
+ Object *ob = (Object *)outliner_search_back(te, ID_OB);
+ if ((ob != NULL) && (ob->data == tselem->id)) {
+ Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
+ if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
+ do_outliner_item_editmode_toggle(C, tvc->scene, tvc->view_layer, base, extend);
+ }
+ }
+ }
+ else if (ELEM(te->idcode, ID_GD)) {
+ /* set grease pencil to object mode */
+ WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
+ }
+ else if (tselem->type == TSE_POSE_BASE) {
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
+ if (base != NULL) {
+ do_outliner_item_posemode_toggle(C, tvc->scene, tvc->view_layer, base, extend);
+ }
}
}
@@ -862,8 +894,8 @@ static eOLDrawState tree_element_active_text(bContext *UNUSED(C),
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_pose(bContext *C,
- Scene *scene,
+static eOLDrawState tree_element_active_pose(bContext *UNUSED(C),
+ Scene *UNUSED(scene),
ViewLayer *view_layer,
TreeElement *UNUSED(te),
TreeStoreElem *tselem,
@@ -878,7 +910,6 @@ static eOLDrawState tree_element_active_pose(bContext *C,
}
if (set != OL_SETSEL_NONE) {
- do_outliner_activate_pose(C, scene, view_layer, base, (set == OL_SETSEL_EXTEND));
}
else {
if (ob->mode & OB_MODE_POSE) {
@@ -1112,11 +1143,11 @@ eOLDrawState tree_element_type_active(bContext *C,
/* ================================================ */
-/* Activate a tree store element and set the walk navigation start element */
-void outliner_element_activate(SpaceOutliner *soops, TreeStoreElem *tselem)
+/* Set the walk navigation start element */
+void outliner_set_walk_element(SpaceOutliner *soops, TreeStoreElem *tselem)
{
- outliner_flag_set(&soops->tree, TSE_ACTIVE | TSE_ACTIVE_WALK, false);
- tselem->flag |= TSE_ACTIVE | TSE_ACTIVE_WALK;
+ outliner_flag_set(&soops->tree, TSE_ACTIVE_WALK, false);
+ tselem->flag |= TSE_ACTIVE_WALK;
}
/**
@@ -1132,9 +1163,8 @@ static void do_outliner_item_activate_tree_element(bContext *C,
TreeStoreElem *tselem,
const bool extend,
const bool recursive,
- const bool is_over_name_icons)
+ const bool do_activate_data)
{
- bool do_activate_data = soops->flag & SO_SYNC_SELECT || is_over_name_icons;
/* Always makes active object, except for some specific types. */
if (ELEM(tselem->type,
TSE_SEQUENCE,
@@ -1152,7 +1182,6 @@ static void do_outliner_item_activate_tree_element(bContext *C,
/* Support pose mode toggle, keeping the active object as is. */
}
else if (do_activate_data) {
- /* Only activate when synced selection is enabled */
tree_element_set_active_object(C,
tvc->scene,
tvc->view_layer,
@@ -1163,8 +1192,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
recursive && tselem->type == 0);
}
- /* Mark as active in the outliner */
- outliner_element_activate(soops, tselem);
+ outliner_set_walk_element(soops, tselem);
if (tselem->type == 0) { // the lib blocks
if (do_activate_data == false) {
@@ -1215,19 +1243,6 @@ static void do_outliner_item_activate_tree_element(bContext *C,
DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, tvc->scene);
}
- else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
- Object *ob = (Object *)outliner_search_back(te, ID_OB);
- if ((ob != NULL) && (ob->data == tselem->id)) {
- Base *base = BKE_view_layer_base_find(tvc->view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE_DEPSGRAPH)) {
- do_outliner_activate_obdata(C, tvc->scene, tvc->view_layer, base, extend);
- }
- }
- }
- else if (ELEM(te->idcode, ID_GD)) {
- /* set grease pencil to object mode */
- WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
else { // rest of types
tree_element_active(C, tvc, soops, te, OL_SETSEL_NORMAL, false);
}
@@ -1238,23 +1253,49 @@ static void do_outliner_item_activate_tree_element(bContext *C,
}
}
-/**
- * \param extend: Don't deselect other items, only modify \a te.
- * \param toggle: Select \a te when not selected, deselect when selected.
- */
-void outliner_item_select(SpaceOutliner *soops,
- const TreeElement *te,
- const bool extend,
- const bool toggle)
+/* Select the item using the set flags */
+void outliner_item_select(bContext *C,
+ SpaceOutliner *soops,
+ TreeElement *te,
+ const short select_flag)
{
TreeStoreElem *tselem = TREESTORE(te);
- const short new_flag = (toggle && (tselem->flag & TSE_ACTIVE)) ? (tselem->flag ^ TSE_SELECTED) :
- (tselem->flag | TSE_SELECTED);
+ const bool activate = select_flag & OL_ITEM_ACTIVATE;
+ const bool extend = select_flag & OL_ITEM_EXTEND;
+ const bool activate_data = select_flag & OL_ITEM_SELECT_DATA;
- if (extend == false) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, false);
+ /* Clear previous active when activating and clear selection when not extending selection */
+ const short clear_flag = (activate ? TSE_ACTIVE : 0) | (extend ? 0 : TSE_SELECTED);
+ if (clear_flag) {
+ outliner_flag_set(&soops->tree, clear_flag, false);
+ }
+
+ if (select_flag & OL_ITEM_SELECT) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+
+ if (activate) {
+ TreeViewContext tvc;
+ outliner_viewcontext_init(C, &tvc);
+
+ tselem->flag |= TSE_ACTIVE;
+ do_outliner_item_activate_tree_element(C,
+ &tvc,
+ soops,
+ te,
+ tselem,
+ extend,
+ select_flag & OL_ITEM_RECURSIVE,
+ activate_data || soops->flag & SO_SYNC_SELECT);
+
+ /* Mode toggle on data activate for now, but move later */
+ if (select_flag & OL_ITEM_TOGGLE_MODE) {
+ outliner_item_mode_toggle(C, &tvc, te, extend);
+ }
}
- tselem->flag = new_flag;
}
static bool do_outliner_range_select_recursive(ListBase *lb,
@@ -1297,8 +1338,7 @@ static void do_outliner_range_select(bContext *C,
/* If no active element exists, activate the element under the cursor */
if (!active) {
- outliner_item_select(soops, cursor, false, false);
- outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false);
+ outliner_item_select(C, soops, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
return;
}
@@ -1311,14 +1351,13 @@ static void do_outliner_range_select(bContext *C,
/* Select active if under cursor */
if (active == cursor) {
- TREESTORE(cursor)->flag |= TSE_SELECTED;
+ outliner_item_select(C, soops, cursor, OL_ITEM_SELECT);
return;
}
- /* If active is not selected, select the element under the cursor */
+ /* If active is not selected or visible, select and activate the element under the cursor */
if (!active_selected || !outliner_is_element_visible(active)) {
- outliner_item_select(soops, cursor, false, false);
- outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false);
+ outliner_item_select(C, soops, cursor, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
return;
}
@@ -1333,23 +1372,6 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
}
/**
- * A version of #outliner_item_do_activate_from_cursor that takes the tree element directly.
- * and doesn't depend on the pointer position.
- *
- * This allows us to simulate clicking on an item without dealing with the mouse cursor.
- */
-void outliner_item_do_activate_from_tree_element(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, bool extend, bool recursive)
-{
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
-
- TreeViewContext tvc;
- outliner_viewcontext_init(C, &tvc);
-
- do_outliner_item_activate_tree_element(C, &tvc, soops, te, tselem, extend, recursive, false);
-}
-
-/**
* Action to run when clicking in the outliner,
*
* May expend/collapse branches or activate items.
@@ -1401,14 +1423,17 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
do_outliner_range_select(C, soops, activate_te, extend);
}
else {
- TreeViewContext tvc;
- outliner_viewcontext_init(C, &tvc);
-
const bool is_over_name_icons = outliner_item_is_co_over_name_icons(activate_te,
view_mval[0]);
- outliner_item_select(soops, activate_te, extend, extend);
- do_outliner_item_activate_tree_element(
- C, &tvc, soops, activate_te, activate_tselem, extend, false, is_over_name_icons);
+ /* Always select unless already active and selected */
+ const bool select = !extend || !(activate_tselem->flag & TSE_ACTIVE &&
+ activate_tselem->flag & TSE_SELECTED);
+
+ const short select_flag = OL_ITEM_ACTIVATE | (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) |
+ (is_over_name_icons ? OL_ITEM_SELECT_DATA : 0) |
+ (extend ? OL_ITEM_EXTEND : 0) | OL_ITEM_TOGGLE_MODE;
+
+ outliner_item_select(C, soops, activate_te, select_flag);
}
changed = true;
@@ -1467,23 +1492,19 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
/* **************** Box Select Tool ****************** */
static void outliner_item_box_select(
- SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select)
+ bContext *C, SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select)
{
TreeStoreElem *tselem = TREESTORE(te);
if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
- if (select) {
- tselem->flag |= TSE_SELECTED;
- }
- else {
- tselem->flag &= ~TSE_SELECTED;
- }
+ outliner_item_select(
+ C, soops, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND);
}
/* Look at its children. */
if (TSELEM_OPEN(tselem, soops)) {
for (te = te->subtree.first; te; te = te->next) {
- outliner_item_box_select(soops, scene, rectf, te, select);
+ outliner_item_box_select(C, soops, scene, rectf, te, select);
}
}
}
@@ -1505,7 +1526,7 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
UI_view2d_region_to_view_rctf(&region->v2d, &rectf, &rectf);
LISTBASE_FOREACH (TreeElement *, te, &soops->tree) {
- outliner_item_box_select(soops, scene, &rectf, te, select);
+ outliner_item_box_select(C, soops, scene, &rectf, te, select);
}
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
index 852773d3979..943738680e6 100644
--- a/source/blender/editors/space_outliner/outliner_sync.c
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -403,7 +403,8 @@ static void outliner_select_sync_from_object(ViewLayer *view_layer,
const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
if (base && (ob == obact)) {
- outliner_element_activate(soops, tselem);
+ tselem->flag |= TSE_ACTIVE;
+ outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@@ -425,7 +426,8 @@ static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops,
EditBone *ebone = (EditBone *)te->directdata;
if (ebone == ebone_active) {
- outliner_element_activate(soops, tselem);
+ tselem->flag |= TSE_ACTIVE;
+ outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@@ -448,7 +450,8 @@ static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops,
Bone *bone = pchan->bone;
if (pchan == pchan_active) {
- outliner_element_activate(soops, tselem);
+ tselem->flag |= TSE_ACTIVE;
+ outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@@ -469,7 +472,8 @@ static void outliner_select_sync_from_sequence(SpaceOutliner *soops,
Sequence *seq = (Sequence *)tselem->id;
if (seq == sequence_active) {
- outliner_element_activate(soops, tselem);
+ tselem->flag |= TSE_ACTIVE;
+ outliner_set_walk_element(soops, tselem);
}
else {
tselem->flag &= ~TSE_ACTIVE;
@@ -525,7 +529,7 @@ static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
}
}
else {
- tselem->flag &= ~TSE_SELECTED;
+ tselem->flag &= ~(TSE_SELECTED | TSE_ACTIVE);
}
/* Sync subtree elements */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4b780df1cbf..d04402f989c 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -574,8 +574,7 @@ static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = (TreeElement *)element;
- outliner_item_select(soops, te, false, false);
- outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
ED_outliner_select_sync_from_outliner(C, soops);
}
@@ -665,12 +664,13 @@ static void object_select_hierarchy_cb(bContext *C,
Scene *UNUSED(scene),
TreeElement *te,
TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
+ TreeStoreElem *UNUSED(tselem),
void *UNUSED(user_data))
{
/* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
* it's especially confusing when multiple items are selected since some toggle on/off. */
- outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | OL_ITEM_RECURSIVE);
}
static void object_deselect_cb(bContext *C,