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.c305
1 files changed, 148 insertions, 157 deletions
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index fa8422573ab..8a408a41897 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);
+ }
}
}
@@ -302,28 +334,32 @@ static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_p
static eOLDrawState tree_element_set_active_object(bContext *C,
Scene *scene,
ViewLayer *view_layer,
- SpaceOutliner *soops,
+ SpaceOutliner *UNUSED(soops),
TreeElement *te,
const eOLSetState set,
bool recursive)
{
TreeStoreElem *tselem = TREESTORE(te);
TreeStoreElem *parent_tselem = NULL;
+ TreeElement *parent_te = NULL;
Scene *sce;
Base *base;
Object *ob = NULL;
- TreeElement *te_ob = NULL;
/* if id is not object, we search back */
- if (te->idcode == ID_OB) {
+ if (tselem->type == 0 && te->idcode == ID_OB) {
ob = (Object *)tselem->id;
}
else {
- ob = (Object *)outliner_search_back(te, ID_OB);
-
- /* Don't return when activating children of the previous active object. */
- if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) {
- return OL_DRAWSEL_NONE;
+ parent_te = outliner_search_back_te(te, ID_OB);
+ if (parent_te) {
+ parent_tselem = TREESTORE(parent_te);
+ ob = (Object *)parent_tselem->id;
+
+ /* Don't return when activating children of the previous active object. */
+ if (ob == OBACT(view_layer) && set == OL_SETSEL_NONE) {
+ return OL_DRAWSEL_NONE;
+ }
}
}
if (ob == NULL) {
@@ -356,11 +392,6 @@ static eOLDrawState tree_element_set_active_object(bContext *C,
}
}
- te_ob = outliner_find_id(soops, &soops->tree, (ID *)ob);
- if (te_ob != NULL && te_ob != te) {
- parent_tselem = TREESTORE(te_ob);
- }
-
if (base) {
if (set == OL_SETSEL_EXTEND) {
/* swap select */
@@ -863,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,
@@ -879,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) {
@@ -1113,13 +1143,6 @@ 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)
-{
- outliner_flag_set(&soops->tree, TSE_ACTIVE | TSE_ACTIVE_WALK, false);
- tselem->flag |= TSE_ACTIVE | TSE_ACTIVE_WALK;
-}
-
/**
* Action when clicking to activate an item (typically under the mouse cursor),
* but don't do any cursor intersection checks.
@@ -1133,9 +1156,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,
@@ -1153,7 +1175,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,
@@ -1164,9 +1185,6 @@ 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);
-
if (tselem->type == 0) { // the lib blocks
if (do_activate_data == false) {
/* Only select in outliner. */
@@ -1216,19 +1234,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);
}
@@ -1239,23 +1244,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,
@@ -1298,8 +1329,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;
}
@@ -1312,14 +1342,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;
}
@@ -1334,23 +1363,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.
@@ -1402,14 +1414,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;
@@ -1468,23 +1483,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);
}
}
}
@@ -1506,7 +1517,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);
@@ -1587,17 +1598,17 @@ static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops,
}
/* Find previous visible element in the tree */
-static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *walk_element)
+static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *te)
{
- if (walk_element->prev) {
- walk_element = outliner_find_rightmost_visible_child(soops, walk_element->prev);
+ if (te->prev) {
+ te = outliner_find_rightmost_visible_child(soops, te->prev);
}
- else if (walk_element->parent) {
+ else if (te->parent) {
/* Use parent if at beginning of list */
- walk_element = walk_element->parent;
+ te = te->parent;
}
- return walk_element;
+ return te;
}
/* Recursively search up the tree until a successor to a given element is found */
@@ -1618,98 +1629,78 @@ static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te)
}
/* Find next visible element in the tree */
-static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *walk_element)
+static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(walk_element);
+ TreeStoreElem *tselem = TREESTORE(te);
- if (TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) {
- walk_element = walk_element->subtree.first;
+ if (TSELEM_OPEN(tselem, soops) && te->subtree.first) {
+ te = te->subtree.first;
}
- else if (walk_element->next) {
- walk_element = walk_element->next;
+ else if (te->next) {
+ te = te->next;
}
else {
- walk_element = outliner_element_find_successor_in_parents(walk_element);
+ te = outliner_element_find_successor_in_parents(te);
}
- return walk_element;
+ return te;
}
static TreeElement *do_outliner_select_walk(SpaceOutliner *soops,
- TreeElement *walk_element,
+ TreeElement *te,
const int direction,
const bool extend,
const bool toggle_all)
{
- TreeStoreElem *tselem = TREESTORE(walk_element);
-
- if (!extend) {
- outliner_flag_set(&soops->tree, TSE_SELECTED, false);
- }
- tselem->flag &= ~TSE_ACTIVE_WALK;
+ TreeStoreElem *tselem = TREESTORE(te);
switch (direction) {
case UI_SELECT_WALK_UP:
- walk_element = outliner_find_previous_element(soops, walk_element);
+ te = outliner_find_previous_element(soops, te);
break;
case UI_SELECT_WALK_DOWN:
- walk_element = outliner_find_next_element(soops, walk_element);
+ te = outliner_find_next_element(soops, te);
break;
case UI_SELECT_WALK_LEFT:
- outliner_item_openclose(walk_element, false, toggle_all);
+ outliner_item_openclose(te, false, toggle_all);
break;
case UI_SELECT_WALK_RIGHT:
- outliner_item_openclose(walk_element, true, toggle_all);
+ outliner_item_openclose(te, true, toggle_all);
break;
}
- TreeStoreElem *tselem_new = TREESTORE(walk_element);
-
/* If new element is already selected, deselect the previous element */
+ TreeStoreElem *tselem_new = TREESTORE(te);
if (extend) {
tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
(tselem->flag | TSE_SELECTED);
}
- tselem_new->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
-
- return walk_element;
+ return te;
}
-/* Find walk select element, or set it if it does not exist.
- * Changed is set to true if walk element is found, false if it was set */
+/* Find the active element to walk from, or set one if none exists.
+ * Changed is set to true if the active element is found, or false if it was set */
static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed)
{
- TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE_WALK);
-
+ TreeElement *active_te = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
*changed = false;
- /* If no walk element exists, start from active */
- if (!walk_element) {
- TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
-
- /* If no active element exists, use the first element in the tree */
- if (!active_element) {
- walk_element = soops->tree.first;
- }
- else {
- walk_element = active_element;
- }
-
+ /* If no active element exists, use the first element in the tree */
+ if (!active_te) {
+ active_te = soops->tree.first;
*changed = true;
}
- /* If walk element is not visible, set that element's first visible parent as walk element */
- if (!outliner_is_element_visible(walk_element)) {
- TREESTORE(walk_element)->flag &= ~TSE_ACTIVE_WALK;
-
- while (!outliner_is_element_visible(walk_element)) {
- walk_element = walk_element->parent;
+ /* If the active element is not visible, activate the first visible parent element */
+ if (!outliner_is_element_visible(active_te)) {
+ while (!outliner_is_element_visible(active_te)) {
+ active_te = active_te->parent;
}
*changed = true;
}
- return walk_element;
+ return active_te;
}
/* Scroll the outliner when the walk element reaches the top or bottom boundary */
@@ -1738,18 +1729,18 @@ static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEven
const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all");
bool changed;
- TreeElement *walk_element = find_walk_select_start_element(soops, &changed);
+ TreeElement *active_te = find_walk_select_start_element(soops, &changed);
- /* If finding the starting walk select element did not move the element, proceed to walk */
+ /* If finding the active element did not modify the selection, proceed to walk */
if (!changed) {
- walk_element = do_outliner_select_walk(soops, walk_element, direction, extend, toggle_all);
- }
- else {
- TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
+ active_te = do_outliner_select_walk(soops, active_te, direction, extend, toggle_all);
}
+ outliner_item_select(
+ C, soops, active_te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | (extend ? OL_ITEM_EXTEND : 0));
+
/* Scroll outliner to focus on walk element */
- outliner_walk_scroll(region, walk_element);
+ outliner_walk_scroll(region, active_te);
ED_outliner_select_sync_from_outliner(C, soops);
ED_region_tag_redraw(region);