Outliner: Make use of new C++ based functional iterators
(Not meant to cause user visible changes.)
Makes use of the new iterators introduced in the previous commit. Some
benefits:
- Shorter, simpler, easier to read & understand
- Deduplicates logic
- Centralizes iteration logic, making it easier to replace tree storage
(as planned), see previous commit.
- Avoids having to pass (sub-)tree to iterate around (often redundant
since it's just `SpaceOutliner.tree`, even though `SpaceOutliner` is
already passed).
- Function arguments that are only passed to the recursive call are
recognized as unused (found and removed a few).
Also does some general cleanups while refactoring the code for the
iterators. Use `const`, use references (signals null is not expected),
early-exit (see 16fd5fa656
), remove redundant arguments, etc.
This commit is contained in:
parent
a4a7af4732
commit
dc6fe73e70
Notes:
blender-bot
2023-02-14 05:53:38 +01:00
Referenced by issue #101954, Regression: Geometry Node: Delete hair curves from end and set radius form sample nearest surface create incorrect shifting of radius on viewport render Referenced by issue #98454, Geometry Nodes: Vertices from Subdivided Curve to Mesh geometry don't inherit Integer Attributes Referenced by issue #96713, Continued Outliner Code Refactor
|
@ -12,23 +12,25 @@
|
|||
#include "DNA_space_types.h"
|
||||
|
||||
#include "outliner_intern.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
static void outliner_context_selected_ids_recursive(const ListBase *subtree,
|
||||
using namespace blender::ed::outliner;
|
||||
|
||||
static void outliner_context_selected_ids_recursive(const SpaceOutliner &space_outliner,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
LISTBASE_FOREACH (const TreeElement *, te, subtree) {
|
||||
tree_iterator::all(space_outliner, [&](const TreeElement *te) {
|
||||
const TreeStoreElem *tse = TREESTORE(te);
|
||||
if ((tse->flag & TSE_SELECTED) && (ELEM(tse->type, TSE_SOME_ID, TSE_LAYER_COLLECTION))) {
|
||||
CTX_data_id_list_add(result, tse->id);
|
||||
}
|
||||
outliner_context_selected_ids_recursive(&te->subtree, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void outliner_context_selected_ids(const SpaceOutliner *space_outliner,
|
||||
bContextDataResult *result)
|
||||
{
|
||||
outliner_context_selected_ids_recursive(&space_outliner->tree, result);
|
||||
outliner_context_selected_ids_recursive(*space_outliner, result);
|
||||
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
|
||||
}
|
||||
|
||||
|
|
|
@ -316,7 +316,7 @@ static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
|
|||
{
|
||||
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
|
||||
|
||||
bool changed = outliner_flag_set(&space_outliner->tree, TSE_DRAG_ANY, false);
|
||||
bool changed = outliner_flag_set(*space_outliner, TSE_DRAG_ANY, false);
|
||||
if (changed) {
|
||||
ED_region_tag_redraw_no_rebuild(CTX_wm_region(C));
|
||||
}
|
||||
|
@ -847,8 +847,7 @@ static bool datastack_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
|
|||
|
||||
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
bool changed = outliner_flag_set(
|
||||
&space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
bool changed = outliner_flag_set(*space_outliner, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
|
||||
StackDropData *drop_data = reinterpret_cast<StackDropData *>(drag->poin);
|
||||
if (!drop_data) {
|
||||
|
@ -1195,8 +1194,7 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event
|
|||
{
|
||||
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
bool changed = outliner_flag_set(
|
||||
&space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
bool changed = outliner_flag_set(*space_outliner, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
|
||||
CollectionDrop data;
|
||||
if (((event->modifier & KM_SHIFT) == 0) &&
|
||||
|
@ -1461,7 +1459,7 @@ static int outliner_item_drag_drop_invoke(bContext *C,
|
|||
|
||||
/* Only drag element under mouse if it was not selected before. */
|
||||
if ((tselem->flag & TSE_SELECTED) == 0) {
|
||||
outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 0);
|
||||
outliner_flag_set(*space_outliner, TSE_SELECTED, 0);
|
||||
tselem->flag |= TSE_SELECTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "tree/tree_element_id.hh"
|
||||
#include "tree/tree_element_overrides.hh"
|
||||
#include "tree/tree_element_rna.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::ed::outliner;
|
||||
|
@ -1715,72 +1716,70 @@ static void outliner_draw_restrictbuts(uiBlock *block,
|
|||
}
|
||||
|
||||
static void outliner_draw_userbuts(uiBlock *block,
|
||||
ARegion *region,
|
||||
SpaceOutliner *space_outliner,
|
||||
ListBase *lb)
|
||||
const ARegion *region,
|
||||
const SpaceOutliner *space_outliner)
|
||||
{
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (outliner_is_element_in_view(te, ®ion->v2d)) {
|
||||
if (tselem->type == TSE_SOME_ID) {
|
||||
uiBut *bt;
|
||||
ID *id = tselem->id;
|
||||
const char *tip = nullptr;
|
||||
char buf[16] = "";
|
||||
int but_flag = UI_BUT_DRAG_LOCK;
|
||||
|
||||
if (ID_IS_LINKED(id)) {
|
||||
but_flag |= UI_BUT_DISABLED;
|
||||
}
|
||||
|
||||
BLI_str_format_int_grouped(buf, id->us);
|
||||
bt = uiDefBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
1,
|
||||
buf,
|
||||
(int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
|
||||
te->ys,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0.0,
|
||||
0.0,
|
||||
0,
|
||||
0,
|
||||
TIP_("Number of users of this data-block"));
|
||||
UI_but_flag_enable(bt, but_flag);
|
||||
|
||||
if (id->flag & LIB_FAKEUSER) {
|
||||
tip = TIP_("Data-block will be retained using a fake user");
|
||||
}
|
||||
else {
|
||||
tip = TIP_("Data-block has no users and will be deleted");
|
||||
}
|
||||
bt = uiDefIconButBitS(block,
|
||||
UI_BTYPE_ICON_TOGGLE,
|
||||
LIB_FAKEUSER,
|
||||
1,
|
||||
ICON_FAKE_USER_OFF,
|
||||
(int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
|
||||
te->ys,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&id->flag,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
tip);
|
||||
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, nullptr);
|
||||
UI_but_flag_enable(bt, but_flag);
|
||||
}
|
||||
tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
|
||||
if (!outliner_is_element_in_view(te, ®ion->v2d)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_draw_userbuts(block, region, space_outliner, &te->subtree);
|
||||
const TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (tselem->type != TSE_SOME_ID) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uiBut *bt;
|
||||
ID *id = tselem->id;
|
||||
const char *tip = nullptr;
|
||||
char buf[16] = "";
|
||||
int but_flag = UI_BUT_DRAG_LOCK;
|
||||
|
||||
if (ID_IS_LINKED(id)) {
|
||||
but_flag |= UI_BUT_DISABLED;
|
||||
}
|
||||
|
||||
BLI_str_format_int_grouped(buf, id->us);
|
||||
bt = uiDefBut(block,
|
||||
UI_BTYPE_BUT,
|
||||
1,
|
||||
buf,
|
||||
(int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
|
||||
te->ys,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0.0,
|
||||
0.0,
|
||||
0,
|
||||
0,
|
||||
TIP_("Number of users of this data-block"));
|
||||
UI_but_flag_enable(bt, but_flag);
|
||||
|
||||
if (id->flag & LIB_FAKEUSER) {
|
||||
tip = TIP_("Data-block will be retained using a fake user");
|
||||
}
|
||||
else {
|
||||
tip = TIP_("Data-block has no users and will be deleted");
|
||||
}
|
||||
bt = uiDefIconButBitS(block,
|
||||
UI_BTYPE_ICON_TOGGLE,
|
||||
LIB_FAKEUSER,
|
||||
1,
|
||||
ICON_FAKE_USER_OFF,
|
||||
(int)(region->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
|
||||
te->ys,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&id->flag,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
tip);
|
||||
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, nullptr);
|
||||
UI_but_flag_enable(bt, but_flag);
|
||||
});
|
||||
}
|
||||
|
||||
static void outliner_draw_overrides_rna_buts(uiBlock *block,
|
||||
|
@ -1941,81 +1940,82 @@ static void outliner_draw_separator(ARegion *region, const int x)
|
|||
immUnbindProgram();
|
||||
}
|
||||
|
||||
static void outliner_draw_rnabuts(
|
||||
uiBlock *block, ARegion *region, SpaceOutliner *space_outliner, int sizex, ListBase *lb)
|
||||
static void outliner_draw_rnabuts(uiBlock *block,
|
||||
ARegion *region,
|
||||
SpaceOutliner *space_outliner,
|
||||
int sizex)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (outliner_is_element_in_view(te, ®ion->v2d)) {
|
||||
if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) {
|
||||
ptr = te_rna_prop->getPointerRNA();
|
||||
prop = te_rna_prop->getPropertyRNA();
|
||||
|
||||
if (!TSELEM_OPEN(tselem, space_outliner)) {
|
||||
if (RNA_property_type(prop) == PROP_POINTER) {
|
||||
uiBut *but = uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
UI_but_flag_enable(but, UI_BUT_DISABLED);
|
||||
}
|
||||
else if (RNA_property_type(prop) == PROP_ENUM) {
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
nullptr,
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
else {
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
if (!outliner_is_element_in_view(te, ®ion->v2d)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) {
|
||||
ptr = te_rna_prop->getPointerRNA();
|
||||
prop = te_rna_prop->getPropertyRNA();
|
||||
|
||||
if (!TSELEM_OPEN(tselem, space_outliner)) {
|
||||
if (RNA_property_type(prop) == PROP_POINTER) {
|
||||
uiBut *but = uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
UI_but_flag_enable(but, UI_BUT_DISABLED);
|
||||
}
|
||||
else if (RNA_property_type(prop) == PROP_ENUM) {
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
nullptr,
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
else {
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
-1,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
}
|
||||
else if (TreeElementRNAArrayElement *te_rna_array_elem =
|
||||
tree_element_cast<TreeElementRNAArrayElement>(te)) {
|
||||
ptr = te_rna_array_elem->getPointerRNA();
|
||||
prop = te_rna_array_elem->getPropertyRNA();
|
||||
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
te->index,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
}
|
||||
else if (TreeElementRNAArrayElement *te_rna_array_elem =
|
||||
tree_element_cast<TreeElementRNAArrayElement>(te)) {
|
||||
ptr = te_rna_array_elem->getPointerRNA();
|
||||
prop = te_rna_array_elem->getPropertyRNA();
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_draw_rnabuts(block, region, space_outliner, sizex, &te->subtree);
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
te->index,
|
||||
"",
|
||||
ICON_NONE,
|
||||
sizex,
|
||||
te->ys,
|
||||
OL_RNA_COL_SIZEX,
|
||||
UI_UNIT_Y - 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void outliner_buttons(const bContext *C,
|
||||
|
@ -2101,9 +2101,9 @@ static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED
|
|||
static void outliner_draw_mode_column_toggle(uiBlock *block,
|
||||
TreeViewContext *tvc,
|
||||
TreeElement *te,
|
||||
TreeStoreElem *tselem,
|
||||
const bool lock_object_modes)
|
||||
{
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if ((tselem->type != TSE_SOME_ID) || (te->idcode != ID_OB)) {
|
||||
return;
|
||||
}
|
||||
|
@ -2174,26 +2174,17 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
|
|||
}
|
||||
}
|
||||
|
||||
static void outliner_draw_mode_column(const bContext *C,
|
||||
uiBlock *block,
|
||||
static void outliner_draw_mode_column(uiBlock *block,
|
||||
TreeViewContext *tvc,
|
||||
SpaceOutliner *space_outliner,
|
||||
ListBase *tree)
|
||||
SpaceOutliner *space_outliner)
|
||||
{
|
||||
TreeStoreElem *tselem;
|
||||
const bool lock_object_modes = tvc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK;
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, tree) {
|
||||
tselem = TREESTORE(te);
|
||||
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
if (tvc->obact && tvc->obact->mode != OB_MODE_OBJECT) {
|
||||
outliner_draw_mode_column_toggle(block, tvc, te, tselem, lock_object_modes);
|
||||
outliner_draw_mode_column_toggle(block, tvc, te, lock_object_modes);
|
||||
}
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_draw_mode_column(C, block, tvc, space_outliner, &te->subtree);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static StringRefNull outliner_draw_get_warning_tree_element_subtree(const TreeElement *parent_te)
|
||||
|
@ -2235,7 +2226,7 @@ static StringRefNull outliner_draw_get_warning_tree_element(const SpaceOutliner
|
|||
}
|
||||
|
||||
static void outliner_draw_warning_tree_element(uiBlock *block,
|
||||
SpaceOutliner *space_outliner,
|
||||
const SpaceOutliner *space_outliner,
|
||||
StringRefNull warning_msg,
|
||||
const bool use_mode_column,
|
||||
const int te_ys)
|
||||
|
@ -2264,13 +2255,11 @@ static void outliner_draw_warning_tree_element(uiBlock *block,
|
|||
UI_but_flag_disable(but, UI_BUT_UNDO);
|
||||
}
|
||||
|
||||
static void outliner_draw_warning_column(const bContext *C,
|
||||
uiBlock *block,
|
||||
SpaceOutliner *space_outliner,
|
||||
const bool use_mode_column,
|
||||
ListBase *tree)
|
||||
static void outliner_draw_warning_column(uiBlock *block,
|
||||
const SpaceOutliner *space_outliner,
|
||||
const bool use_mode_column)
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, tree) {
|
||||
tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
|
||||
/* Get warning for this element, or if there is none and the element is collapsed, the first
|
||||
* warning in the collapsed sub-tree. */
|
||||
StringRefNull warning_msg = outliner_draw_get_warning_tree_element(*space_outliner, te);
|
||||
|
@ -2279,11 +2268,7 @@ static void outliner_draw_warning_column(const bContext *C,
|
|||
outliner_draw_warning_tree_element(
|
||||
block, space_outliner, warning_msg, use_mode_column, te->ys);
|
||||
}
|
||||
|
||||
if (TSELEM_OPEN(te->store_elem, space_outliner)) {
|
||||
outliner_draw_warning_column(C, block, space_outliner, use_mode_column, &te->subtree);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -3164,18 +3149,16 @@ static void outliner_draw_iconrow(bContext *C,
|
|||
}
|
||||
|
||||
/* closed tree element */
|
||||
static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty)
|
||||
static void outliner_set_subtree_coords(const TreeElement *te)
|
||||
{
|
||||
/* closed items may be displayed in row of parent, don't change their coordinate! */
|
||||
if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) {
|
||||
te->xs = 0;
|
||||
te->ys = 0;
|
||||
te->xend = 0;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
|
||||
outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
|
||||
}
|
||||
tree_iterator::all(te->subtree, [&](TreeElement *te) {
|
||||
/* closed items may be displayed in row of parent, don't change their coordinate! */
|
||||
if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) {
|
||||
te->xs = 0;
|
||||
te->ys = 0;
|
||||
te->xend = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static bool element_should_draw_faded(const TreeViewContext *tvc,
|
||||
|
@ -3427,10 +3410,7 @@ static void outliner_draw_tree_element(bContext *C,
|
|||
}
|
||||
}
|
||||
else {
|
||||
LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
|
||||
outliner_set_coord_tree_element(ten, startx, *starty);
|
||||
}
|
||||
|
||||
outliner_set_subtree_coords(te);
|
||||
*starty -= UI_UNIT_Y;
|
||||
}
|
||||
}
|
||||
|
@ -3586,22 +3566,21 @@ static void outliner_draw_struct_marks(ARegion *region,
|
|||
}
|
||||
}
|
||||
|
||||
static void outliner_draw_highlights_recursive(uint pos,
|
||||
const ARegion *region,
|
||||
const SpaceOutliner *space_outliner,
|
||||
const ListBase *lb,
|
||||
const float col_selection[4],
|
||||
const float col_active[4],
|
||||
const float col_highlight[4],
|
||||
const float col_searchmatch[4],
|
||||
int start_x,
|
||||
int *io_start_y)
|
||||
static void outliner_draw_highlights(uint pos,
|
||||
const ARegion *region,
|
||||
const SpaceOutliner *space_outliner,
|
||||
const float col_selection[4],
|
||||
const float col_active[4],
|
||||
const float col_highlight[4],
|
||||
const float col_searchmatch[4],
|
||||
int start_x,
|
||||
int *io_start_y)
|
||||
{
|
||||
const bool is_searching = (SEARCHING_OUTLINER(space_outliner) ||
|
||||
(space_outliner->outlinevis == SO_DATA_API &&
|
||||
space_outliner->search_string[0] != 0));
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](const TreeElement *te) {
|
||||
const TreeStoreElem *tselem = TREESTORE(te);
|
||||
const int start_y = *io_start_y;
|
||||
|
||||
|
@ -3657,19 +3636,7 @@ static void outliner_draw_highlights_recursive(uint pos,
|
|||
}
|
||||
|
||||
*io_start_y -= UI_UNIT_Y;
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_draw_highlights_recursive(pos,
|
||||
region,
|
||||
space_outliner,
|
||||
&te->subtree,
|
||||
col_selection,
|
||||
col_active,
|
||||
col_highlight,
|
||||
col_searchmatch,
|
||||
start_x + UI_UNIT_X,
|
||||
io_start_y);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void outliner_draw_highlights(ARegion *region,
|
||||
|
@ -3691,16 +3658,15 @@ static void outliner_draw_highlights(ARegion *region,
|
|||
GPUVertFormat *format = immVertexFormat();
|
||||
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
||||
outliner_draw_highlights_recursive(pos,
|
||||
region,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
col_selection,
|
||||
col_active,
|
||||
col_highlight,
|
||||
col_searchmatch,
|
||||
startx,
|
||||
starty);
|
||||
outliner_draw_highlights(pos,
|
||||
region,
|
||||
space_outliner,
|
||||
col_selection,
|
||||
col_active,
|
||||
col_highlight,
|
||||
col_searchmatch,
|
||||
startx,
|
||||
starty);
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
@ -3924,12 +3890,12 @@ void draw_outliner(const bContext *C)
|
|||
outliner_draw_separator(region, buttons_start_x + OL_RNA_COL_SIZEX);
|
||||
|
||||
UI_block_emboss_set(block, UI_EMBOSS);
|
||||
outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x, &space_outliner->tree);
|
||||
outliner_draw_rnabuts(block, region, space_outliner, buttons_start_x);
|
||||
UI_block_emboss_set(block, UI_EMBOSS_NONE_OR_STATUS);
|
||||
}
|
||||
else if (space_outliner->outlinevis == SO_ID_ORPHANS) {
|
||||
/* draw user toggle columns */
|
||||
outliner_draw_userbuts(block, region, space_outliner, &space_outliner->tree);
|
||||
outliner_draw_userbuts(block, region, space_outliner);
|
||||
}
|
||||
else if (space_outliner->outlinevis == SO_OVERRIDES_LIBRARY) {
|
||||
const int x = region->v2d.cur.xmax - right_column_width;
|
||||
|
@ -3960,12 +3926,12 @@ void draw_outliner(const bContext *C)
|
|||
|
||||
/* Draw mode icons */
|
||||
if (use_mode_column) {
|
||||
outliner_draw_mode_column(C, block, &tvc, space_outliner, &space_outliner->tree);
|
||||
outliner_draw_mode_column(block, &tvc, space_outliner);
|
||||
}
|
||||
|
||||
/* Draw warning icons */
|
||||
if (use_warning_column) {
|
||||
outliner_draw_warning_column(C, block, space_outliner, use_mode_column, &space_outliner->tree);
|
||||
outliner_draw_warning_column(block, space_outliner, use_mode_column);
|
||||
}
|
||||
|
||||
UI_block_emboss_set(block, UI_EMBOSS);
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#include "outliner_intern.hh"
|
||||
#include "tree/tree_element_rna.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
using namespace blender::ed::outliner;
|
||||
|
||||
|
@ -107,7 +108,7 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
|
|||
if (!hovered_te || !is_over_icon || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED) ||
|
||||
!(icon_te->store_elem->flag & TSE_HIGHLIGHTED_ICON)) {
|
||||
/* Clear highlights when nothing is hovered or when a new item is hovered. */
|
||||
changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
changed = outliner_flag_set(*space_outliner, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
|
||||
if (hovered_te) {
|
||||
hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
|
||||
changed = true;
|
||||
|
@ -167,7 +168,7 @@ void outliner_item_openclose(SpaceOutliner *space_outliner,
|
|||
}
|
||||
|
||||
if (toggle_all) {
|
||||
outliner_flag_set(&te->subtree, TSE_CLOSED, !open);
|
||||
outliner_flag_set(te->subtree, TSE_CLOSED, !open);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,11 +1078,16 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool outliner_flag_set(ListBase *lb, short flag, short set)
|
||||
bool outliner_flag_set(const SpaceOutliner &space_outliner, const short flag, const short set)
|
||||
{
|
||||
return outliner_flag_set(space_outliner.tree, flag, set);
|
||||
}
|
||||
|
||||
bool outliner_flag_set(const ListBase &lb, const short flag, const short set)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all(lb, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
bool has_flag = (tselem->flag & flag);
|
||||
if (set == 0) {
|
||||
|
@ -1094,21 +1100,24 @@ bool outliner_flag_set(ListBase *lb, short flag, short set)
|
|||
tselem->flag |= flag;
|
||||
changed = true;
|
||||
}
|
||||
changed |= outliner_flag_set(&te->subtree, flag, set);
|
||||
}
|
||||
});
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool outliner_flag_flip(ListBase *lb, short flag)
|
||||
bool outliner_flag_flip(const SpaceOutliner &space_outliner, const short flag)
|
||||
{
|
||||
return outliner_flag_flip(space_outliner.tree, flag);
|
||||
}
|
||||
|
||||
bool outliner_flag_flip(const ListBase &lb, const short flag)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all(lb, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
tselem->flag ^= flag;
|
||||
changed |= outliner_flag_flip(&te->subtree, flag);
|
||||
}
|
||||
});
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
@ -1125,10 +1134,10 @@ static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
if (outliner_flag_is_any_test(&space_outliner->tree, TSE_CLOSED, 1)) {
|
||||
outliner_flag_set(&space_outliner->tree, TSE_CLOSED, 0);
|
||||
outliner_flag_set(*space_outliner, TSE_CLOSED, 0);
|
||||
}
|
||||
else {
|
||||
outliner_flag_set(&space_outliner->tree, TSE_CLOSED, 1);
|
||||
outliner_flag_set(*space_outliner, TSE_CLOSED, 1);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
@ -1169,13 +1178,13 @@ static int outliner_select_all_exec(bContext *C, wmOperator *op)
|
|||
|
||||
switch (action) {
|
||||
case SEL_SELECT:
|
||||
outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 1);
|
||||
outliner_flag_set(*space_outliner, TSE_SELECTED, 1);
|
||||
break;
|
||||
case SEL_DESELECT:
|
||||
outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 0);
|
||||
outliner_flag_set(*space_outliner, TSE_SELECTED, 0);
|
||||
break;
|
||||
case SEL_INVERT:
|
||||
outliner_flag_flip(&space_outliner->tree, TSE_SELECTED);
|
||||
outliner_flag_flip(*space_outliner, TSE_SELECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1211,32 +1220,16 @@ void OUTLINER_OT_select_all(wmOperatorType *ot)
|
|||
/** \name View Show Active (Outliner) Operator
|
||||
* \{ */
|
||||
|
||||
static void outliner_set_coordinates_element_recursive(SpaceOutliner *space_outliner,
|
||||
TreeElement *te,
|
||||
int startx,
|
||||
int *starty)
|
||||
{
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* store coord and continue, we need coordinates for elements outside view too */
|
||||
te->xs = (float)startx;
|
||||
te->ys = (float)(*starty);
|
||||
*starty -= UI_UNIT_Y;
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
|
||||
outliner_set_coordinates_element_recursive(space_outliner, ten, startx + UI_UNIT_X, starty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void outliner_set_coordinates(ARegion *region, SpaceOutliner *space_outliner)
|
||||
void outliner_set_coordinates(const ARegion *region, const SpaceOutliner *space_outliner)
|
||||
{
|
||||
int starty = (int)(region->v2d.tot.ymax) - UI_UNIT_Y;
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
|
||||
outliner_set_coordinates_element_recursive(space_outliner, te, 0, &starty);
|
||||
}
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
/* store coord and continue, we need coordinates for elements outside view too */
|
||||
te->xs = 0;
|
||||
te->ys = (float)starty;
|
||||
starty -= UI_UNIT_Y;
|
||||
});
|
||||
}
|
||||
|
||||
/* return 1 when levels were opened */
|
||||
|
@ -1624,11 +1617,11 @@ static int subtree_has_objects(ListBase *lb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* recursive helper function for Show Hierarchy operator */
|
||||
static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outliner, ListBase *lb)
|
||||
/* Helper function for Show Hierarchy operator */
|
||||
static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outliner)
|
||||
{
|
||||
/* open all object elems, close others */
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
if (ELEM(tselem->type,
|
||||
|
@ -1656,11 +1649,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outli
|
|||
else {
|
||||
tselem->flag |= TSE_CLOSED;
|
||||
}
|
||||
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
tree_element_show_hierarchy(scene, space_outliner, &te->subtree);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* show entire object level hierarchy */
|
||||
|
@ -1671,7 +1660,7 @@ static int outliner_show_hierarchy_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* recursively open/close levels */
|
||||
tree_element_show_hierarchy(scene, space_outliner, &space_outliner->tree);
|
||||
tree_element_show_hierarchy(scene, space_outliner);
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
|
@ -1873,79 +1862,75 @@ enum {
|
|||
DRIVERS_EDITMODE_REMOVE,
|
||||
} /*eDrivers_EditModes*/;
|
||||
|
||||
/* Recursively iterate over tree, finding and working on selected items */
|
||||
/* Iterate over tree, finding and working on selected items */
|
||||
static void do_outliner_drivers_editop(SpaceOutliner *space_outliner,
|
||||
ListBase *tree,
|
||||
ReportList *reports,
|
||||
short mode)
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, tree) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* if item is selected, perform operation */
|
||||
if (tselem->flag & TSE_SELECTED) {
|
||||
ID *id = nullptr;
|
||||
char *path = nullptr;
|
||||
int array_index = 0;
|
||||
short flag = 0;
|
||||
short groupmode = KSP_GROUP_KSNAME;
|
||||
if (!(tselem->flag & TSE_SELECTED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
|
||||
PointerRNA ptr = te_rna ? te_rna->getPointerRNA() : PointerRNA_NULL;
|
||||
PropertyRNA *prop = te_rna ? te_rna->getPropertyRNA() : nullptr;
|
||||
ID *id = nullptr;
|
||||
char *path = nullptr;
|
||||
int array_index = 0;
|
||||
short flag = 0;
|
||||
short groupmode = KSP_GROUP_KSNAME;
|
||||
|
||||
/* check if RNA-property described by this selected element is an animatable prop */
|
||||
if (prop && RNA_property_animateable(&ptr, prop)) {
|
||||
/* get id + path + index info from the selected element */
|
||||
tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
|
||||
TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
|
||||
PointerRNA ptr = te_rna ? te_rna->getPointerRNA() : PointerRNA_NULL;
|
||||
PropertyRNA *prop = te_rna ? te_rna->getPropertyRNA() : nullptr;
|
||||
|
||||
/* check if RNA-property described by this selected element is an animatable prop */
|
||||
if (prop && RNA_property_animateable(&ptr, prop)) {
|
||||
/* get id + path + index info from the selected element */
|
||||
tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
|
||||
}
|
||||
|
||||
/* only if ID and path were set, should we perform any actions */
|
||||
if (id && path) {
|
||||
short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
||||
int arraylen = 1;
|
||||
|
||||
/* array checks */
|
||||
if (flag & KSP_FLAG_WHOLE_ARRAY) {
|
||||
/* entire array was selected, so add drivers for all */
|
||||
arraylen = RNA_property_array_length(&ptr, prop);
|
||||
}
|
||||
else {
|
||||
arraylen = array_index;
|
||||
}
|
||||
|
||||
/* only if ID and path were set, should we perform any actions */
|
||||
if (id && path) {
|
||||
short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
||||
int arraylen = 1;
|
||||
/* we should do at least one step */
|
||||
if (arraylen == array_index) {
|
||||
arraylen++;
|
||||
}
|
||||
|
||||
/* array checks */
|
||||
if (flag & KSP_FLAG_WHOLE_ARRAY) {
|
||||
/* entire array was selected, so add drivers for all */
|
||||
arraylen = RNA_property_array_length(&ptr, prop);
|
||||
}
|
||||
else {
|
||||
arraylen = array_index;
|
||||
}
|
||||
|
||||
/* we should do at least one step */
|
||||
if (arraylen == array_index) {
|
||||
arraylen++;
|
||||
}
|
||||
|
||||
/* for each array element we should affect, add driver */
|
||||
for (; array_index < arraylen; array_index++) {
|
||||
/* action depends on mode */
|
||||
switch (mode) {
|
||||
case DRIVERS_EDITMODE_ADD: {
|
||||
/* add a new driver with the information obtained (only if valid) */
|
||||
ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
|
||||
break;
|
||||
}
|
||||
case DRIVERS_EDITMODE_REMOVE: {
|
||||
/* remove driver matching the information obtained (only if valid) */
|
||||
ANIM_remove_driver(reports, id, path, array_index, dflags);
|
||||
break;
|
||||
}
|
||||
/* for each array element we should affect, add driver */
|
||||
for (; array_index < arraylen; array_index++) {
|
||||
/* action depends on mode */
|
||||
switch (mode) {
|
||||
case DRIVERS_EDITMODE_ADD: {
|
||||
/* add a new driver with the information obtained (only if valid) */
|
||||
ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
|
||||
break;
|
||||
}
|
||||
case DRIVERS_EDITMODE_REMOVE: {
|
||||
/* remove driver matching the information obtained (only if valid) */
|
||||
ANIM_remove_driver(reports, id, path, array_index, dflags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* free path, since it had to be generated */
|
||||
MEM_freeN(path);
|
||||
}
|
||||
}
|
||||
|
||||
/* go over sub-tree */
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
do_outliner_drivers_editop(space_outliner, &te->subtree, reports, mode);
|
||||
/* free path, since it had to be generated */
|
||||
MEM_freeN(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1964,8 +1949,7 @@ static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* recursively go into tree, adding selected items */
|
||||
do_outliner_drivers_editop(
|
||||
space_outliner, &space_outliner->tree, op->reports, DRIVERS_EDITMODE_ADD);
|
||||
do_outliner_drivers_editop(space_outliner, op->reports, DRIVERS_EDITMODE_ADD);
|
||||
|
||||
/* send notifiers */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, nullptr); /* XXX */
|
||||
|
@ -2004,8 +1988,7 @@ static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* recursively go into tree, adding selected items */
|
||||
do_outliner_drivers_editop(
|
||||
space_outliner, &space_outliner->tree, op->reports, DRIVERS_EDITMODE_REMOVE);
|
||||
do_outliner_drivers_editop(space_outliner, op->reports, DRIVERS_EDITMODE_REMOVE);
|
||||
|
||||
/* send notifiers */
|
||||
WM_event_add_notifier(C, ND_KEYS, nullptr); /* XXX */
|
||||
|
@ -2072,68 +2055,64 @@ static KeyingSet *verify_active_keyingset(Scene *scene, short add)
|
|||
return ks;
|
||||
}
|
||||
|
||||
/* Recursively iterate over tree, finding and working on selected items */
|
||||
/* Iterate over tree, finding and working on selected items */
|
||||
static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner,
|
||||
KeyingSet *ks,
|
||||
ListBase *tree,
|
||||
short mode)
|
||||
const short mode)
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, tree) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
/* if item is selected, perform operation */
|
||||
if (tselem->flag & TSE_SELECTED) {
|
||||
ID *id = nullptr;
|
||||
char *path = nullptr;
|
||||
int array_index = 0;
|
||||
short flag = 0;
|
||||
short groupmode = KSP_GROUP_KSNAME;
|
||||
if (!(tselem->flag & TSE_SELECTED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* check if RNA-property described by this selected element is an animatable prop */
|
||||
const TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
|
||||
PointerRNA ptr = te_rna->getPointerRNA();
|
||||
if (te_rna && te_rna->getPropertyRNA() &&
|
||||
RNA_property_animateable(&ptr, te_rna->getPropertyRNA())) {
|
||||
/* get id + path + index info from the selected element */
|
||||
tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
|
||||
}
|
||||
ID *id = nullptr;
|
||||
char *path = nullptr;
|
||||
int array_index = 0;
|
||||
short flag = 0;
|
||||
short groupmode = KSP_GROUP_KSNAME;
|
||||
|
||||
/* only if ID and path were set, should we perform any actions */
|
||||
if (id && path) {
|
||||
/* action depends on mode */
|
||||
switch (mode) {
|
||||
case KEYINGSET_EDITMODE_ADD: {
|
||||
/* add a new path with the information obtained (only if valid) */
|
||||
/* TODO: what do we do with group name?
|
||||
* for now, we don't supply one, and just let this use the KeyingSet name */
|
||||
BKE_keyingset_add_path(ks, id, nullptr, path, array_index, flag, groupmode);
|
||||
ks->active_path = BLI_listbase_count(&ks->paths);
|
||||
break;
|
||||
}
|
||||
case KEYINGSET_EDITMODE_REMOVE: {
|
||||
/* find the relevant path, then remove it from the KeyingSet */
|
||||
KS_Path *ksp = BKE_keyingset_find_path(ks, id, nullptr, path, array_index, groupmode);
|
||||
/* check if RNA-property described by this selected element is an animatable prop */
|
||||
const TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
|
||||
PointerRNA ptr = te_rna->getPointerRNA();
|
||||
if (te_rna && te_rna->getPropertyRNA() &&
|
||||
RNA_property_animateable(&ptr, te_rna->getPropertyRNA())) {
|
||||
/* get id + path + index info from the selected element */
|
||||
tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
|
||||
}
|
||||
|
||||
if (ksp) {
|
||||
/* free path's data */
|
||||
BKE_keyingset_free_path(ks, ksp);
|
||||
|
||||
ks->active_path = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* only if ID and path were set, should we perform any actions */
|
||||
if (id && path) {
|
||||
/* action depends on mode */
|
||||
switch (mode) {
|
||||
case KEYINGSET_EDITMODE_ADD: {
|
||||
/* add a new path with the information obtained (only if valid) */
|
||||
/* TODO: what do we do with group name?
|
||||
* for now, we don't supply one, and just let this use the KeyingSet name */
|
||||
BKE_keyingset_add_path(ks, id, nullptr, path, array_index, flag, groupmode);
|
||||
ks->active_path = BLI_listbase_count(&ks->paths);
|
||||
break;
|
||||
}
|
||||
case KEYINGSET_EDITMODE_REMOVE: {
|
||||
/* find the relevant path, then remove it from the KeyingSet */
|
||||
KS_Path *ksp = BKE_keyingset_find_path(ks, id, nullptr, path, array_index, groupmode);
|
||||
|
||||
/* free path, since it had to be generated */
|
||||
MEM_freeN(path);
|
||||
if (ksp) {
|
||||
/* free path's data */
|
||||
BKE_keyingset_free_path(ks, ksp);
|
||||
|
||||
ks->active_path = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* go over sub-tree */
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
do_outliner_keyingset_editop(space_outliner, ks, &te->subtree, mode);
|
||||
/* free path, since it had to be generated */
|
||||
MEM_freeN(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -2158,7 +2137,7 @@ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* recursively go into tree, adding selected items */
|
||||
do_outliner_keyingset_editop(space_outliner, ks, &space_outliner->tree, KEYINGSET_EDITMODE_ADD);
|
||||
do_outliner_keyingset_editop(space_outliner, ks, KEYINGSET_EDITMODE_ADD);
|
||||
|
||||
/* send notifiers */
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, nullptr);
|
||||
|
@ -2199,8 +2178,7 @@ static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(o
|
|||
}
|
||||
|
||||
/* recursively go into tree, adding selected items */
|
||||
do_outliner_keyingset_editop(
|
||||
space_outliner, ks, &space_outliner->tree, KEYINGSET_EDITMODE_REMOVE);
|
||||
do_outliner_keyingset_editop(space_outliner, ks, KEYINGSET_EDITMODE_REMOVE);
|
||||
|
||||
/* send notifiers */
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, nullptr);
|
||||
|
|
|
@ -408,8 +408,12 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, int curlevel);
|
|||
* Set or unset \a flag for all outliner elements in \a lb and sub-trees.
|
||||
* \return if any flag was modified.
|
||||
*/
|
||||
bool outliner_flag_set(ListBase *lb, short flag, short set);
|
||||
bool outliner_flag_flip(ListBase *lb, short flag);
|
||||
extern "C++" {
|
||||
bool outliner_flag_set(const SpaceOutliner &space_outliner, short flag, short set);
|
||||
bool outliner_flag_set(const ListBase &lb, short flag, short set);
|
||||
bool outliner_flag_flip(const SpaceOutliner &space_outliner, short flag);
|
||||
bool outliner_flag_flip(const ListBase &lb, short flag);
|
||||
}
|
||||
|
||||
void item_rename_fn(struct bContext *C,
|
||||
struct ReportList *reports,
|
||||
|
@ -451,7 +455,8 @@ void id_remap_fn(struct bContext *C,
|
|||
/**
|
||||
* To retrieve coordinates with redrawing the entire tree.
|
||||
*/
|
||||
void outliner_set_coordinates(struct ARegion *region, struct SpaceOutliner *space_outliner);
|
||||
void outliner_set_coordinates(const struct ARegion *region,
|
||||
const struct SpaceOutliner *space_outliner);
|
||||
|
||||
/**
|
||||
* Open or close a tree element, optionally toggling all children recursively.
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "outliner_intern.hh"
|
||||
#include "tree/tree_display.hh"
|
||||
#include "tree/tree_element_seq.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
using namespace blender::ed::outliner;
|
||||
|
||||
|
@ -1457,7 +1458,7 @@ void outliner_item_select(bContext *C,
|
|||
/* 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(&space_outliner->tree, clear_flag, false);
|
||||
outliner_flag_set(*space_outliner, clear_flag, false);
|
||||
}
|
||||
|
||||
if (select_flag & OL_ITEM_SELECT) {
|
||||
|
@ -1531,7 +1532,7 @@ static void do_outliner_range_select(bContext *C,
|
|||
const bool active_selected = (tselem->flag & TSE_SELECTED);
|
||||
|
||||
if (!extend) {
|
||||
outliner_flag_set(&space_outliner->tree, TSE_SELECTED, false);
|
||||
outliner_flag_set(*space_outliner, TSE_SELECTED, false);
|
||||
}
|
||||
|
||||
/* Select active if under cursor */
|
||||
|
@ -1604,7 +1605,7 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
|
|||
|
||||
if (!(te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]))) {
|
||||
if (deselect_all) {
|
||||
changed |= outliner_flag_set(&space_outliner->tree, TSE_SELECTED, false);
|
||||
changed |= outliner_flag_set(*space_outliner, TSE_SELECTED, false);
|
||||
}
|
||||
}
|
||||
/* Don't allow toggle on scene collection */
|
||||
|
@ -1715,26 +1716,17 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
|
|||
/** \name Box Select Operator
|
||||
* \{ */
|
||||
|
||||
static void outliner_item_box_select(bContext *C,
|
||||
SpaceOutliner *space_outliner,
|
||||
Scene *scene,
|
||||
rctf *rectf,
|
||||
TreeElement *te,
|
||||
bool select)
|
||||
static void outliner_box_select(bContext *C,
|
||||
SpaceOutliner *space_outliner,
|
||||
const rctf *rectf,
|
||||
const bool select)
|
||||
{
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
|
||||
if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
|
||||
outliner_item_select(
|
||||
C, space_outliner, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND);
|
||||
}
|
||||
|
||||
/* Look at its children. */
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
|
||||
outliner_item_box_select(C, space_outliner, scene, rectf, te_sub, select);
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) {
|
||||
outliner_item_select(
|
||||
C, space_outliner, te, (select ? OL_ITEM_SELECT : OL_ITEM_DESELECT) | OL_ITEM_EXTEND);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static int outliner_box_select_exec(bContext *C, wmOperator *op)
|
||||
|
@ -1747,15 +1739,13 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
|
|||
const eSelectOp sel_op = (eSelectOp)RNA_enum_get(op->ptr, "mode");
|
||||
const bool select = (sel_op != SEL_OP_SUB);
|
||||
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
||||
outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 0);
|
||||
outliner_flag_set(*space_outliner, TSE_SELECTED, 0);
|
||||
}
|
||||
|
||||
WM_operator_properties_border_to_rctf(op, &rectf);
|
||||
UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf);
|
||||
|
||||
LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
|
||||
outliner_item_box_select(C, space_outliner, scene, &rectf, te, select);
|
||||
}
|
||||
outliner_box_select(C, space_outliner, &rectf, select);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "outliner_intern.hh"
|
||||
#include "tree/tree_element_rna.hh"
|
||||
#include "tree/tree_element_seq.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
static CLG_LogRef LOG = {"ed.outliner.tools"};
|
||||
|
||||
|
@ -412,11 +413,10 @@ static void outliner_do_libdata_operation(bContext *C,
|
|||
ReportList *reports,
|
||||
Scene *scene,
|
||||
SpaceOutliner *space_outliner,
|
||||
ListBase *lb,
|
||||
outliner_operation_fn operation_fn,
|
||||
void *user_data)
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (tselem->flag & TSE_SELECTED) {
|
||||
if (((tselem->type == TSE_SOME_ID) && (te->idcode != 0)) ||
|
||||
|
@ -425,11 +425,7 @@ static void outliner_do_libdata_operation(bContext *C,
|
|||
operation_fn(C, reports, scene, te, tsep, tselem, user_data);
|
||||
}
|
||||
}
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_do_libdata_operation(
|
||||
C, reports, scene, space_outliner, &te->subtree, operation_fn, user_data);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1602,21 +1598,17 @@ static void outliner_do_data_operation(
|
|||
SpaceOutliner *space_outliner,
|
||||
int type,
|
||||
int event,
|
||||
ListBase *lb,
|
||||
void (*operation_fn)(int, TreeElement *, TreeStoreElem *, void *),
|
||||
void *arg)
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (tselem->flag & TSE_SELECTED) {
|
||||
if (tselem->type == type) {
|
||||
operation_fn(event, te, tselem, arg);
|
||||
}
|
||||
}
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_do_data_operation(space_outliner, type, event, &te->subtree, operation_fn, arg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Base *outliner_batch_delete_hierarchy(
|
||||
|
@ -1780,8 +1772,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
|
|||
selection_changed = true;
|
||||
break;
|
||||
case OL_OP_REMAP:
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, id_remap_fn, nullptr);
|
||||
outliner_do_libdata_operation(C, op->reports, scene, space_outliner, id_remap_fn, nullptr);
|
||||
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
|
||||
* trick does not work here). */
|
||||
break;
|
||||
|
@ -2192,13 +2183,8 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
case OUTLINER_IDOP_UNLINK: {
|
||||
/* unlink datablock from its parent */
|
||||
if (objectlevel) {
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_object_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_object_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, nullptr);
|
||||
ED_undo_push(C, "Unlink Object");
|
||||
|
@ -2207,61 +2193,36 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
|
||||
switch (idlevel) {
|
||||
case ID_AC:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_action_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_action_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, nullptr);
|
||||
ED_undo_push(C, "Unlink action");
|
||||
break;
|
||||
case ID_MA:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_material_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_material_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, nullptr);
|
||||
ED_undo_push(C, "Unlink material");
|
||||
break;
|
||||
case ID_TE:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_texture_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_texture_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, nullptr);
|
||||
ED_undo_push(C, "Unlink texture");
|
||||
break;
|
||||
case ID_WO:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_world_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_world_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_WORLD, nullptr);
|
||||
ED_undo_push(C, "Unlink world");
|
||||
break;
|
||||
case ID_GR:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
unlink_collection_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, unlink_collection_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, nullptr);
|
||||
ED_undo_push(C, "Unlink Collection");
|
||||
|
@ -2274,20 +2235,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case OUTLINER_IDOP_LOCAL: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, id_local_fn, nullptr);
|
||||
outliner_do_libdata_operation(C, op->reports, scene, space_outliner, id_local_fn, nullptr);
|
||||
ED_undo_push(C, "Localized Data");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: {
|
||||
OutlinerLibOverrideData override_data{};
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_create_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_create_fn, &override_data);
|
||||
ED_undo_push(C, "Overridden Data");
|
||||
break;
|
||||
}
|
||||
|
@ -2298,16 +2253,10 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_create_hierarchy_pre_process_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_create_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_create_fn, &override_data);
|
||||
id_override_library_create_hierarchy_post_process(C, &override_data);
|
||||
|
||||
ED_undo_push(C, "Overridden Data Hierarchy");
|
||||
|
@ -2321,16 +2270,10 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_create_hierarchy_pre_process_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_create_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_create_fn, &override_data);
|
||||
id_override_library_create_hierarchy_post_process(C, &override_data);
|
||||
|
||||
ED_undo_push(C, "Overridden Data Hierarchy Fully Editable");
|
||||
|
@ -2341,7 +2284,6 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_toggle_flag_fn,
|
||||
POINTER_FROM_UINT(IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED));
|
||||
|
||||
|
@ -2350,39 +2292,24 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
|
||||
OutlinerLibOverrideData override_data{};
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_reset_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_reset_fn, &override_data);
|
||||
ED_undo_push(C, "Reset Overridden Data");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: {
|
||||
OutlinerLibOverrideData override_data{};
|
||||
override_data.do_hierarchy = true;
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_reset_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_reset_fn, &override_data);
|
||||
ED_undo_push(C, "Reset Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: {
|
||||
OutlinerLibOverrideData override_data{};
|
||||
override_data.do_hierarchy = true;
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_resync_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_resync_fn, &override_data);
|
||||
ED_undo_push(C, "Resync Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
|
@ -2390,35 +2317,20 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
OutlinerLibOverrideData override_data{};
|
||||
override_data.do_hierarchy = true;
|
||||
override_data.do_resync_hierarchy_enforce = true;
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_resync_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_resync_fn, &override_data);
|
||||
ED_undo_push(C, "Resync Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: {
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_clear_hierarchy_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_clear_hierarchy_fn, nullptr);
|
||||
ED_undo_push(C, "Clear Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: {
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_clear_single_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_clear_single_fn, nullptr);
|
||||
ED_undo_push(C, "Clear Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
|
@ -2426,26 +2338,16 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
/* make single user */
|
||||
switch (idlevel) {
|
||||
case ID_AC:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
singleuser_action_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, singleuser_action_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, nullptr);
|
||||
ED_undo_push(C, "Single-User Action");
|
||||
break;
|
||||
|
||||
case ID_WO:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
singleuser_world_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, singleuser_world_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_WORLD, nullptr);
|
||||
ED_undo_push(C, "Single-User World");
|
||||
|
@ -2460,15 +2362,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
case OUTLINER_IDOP_DELETE: {
|
||||
if (idlevel > 0) {
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, id_delete_fn, nullptr);
|
||||
C, op->reports, scene, space_outliner, id_delete_fn, nullptr);
|
||||
ED_undo_push(C, "Delete");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_REMAP: {
|
||||
if (idlevel > 0) {
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, id_remap_fn, nullptr);
|
||||
outliner_do_libdata_operation(C, op->reports, scene, space_outliner, id_remap_fn, nullptr);
|
||||
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
|
||||
* trick does not work here). */
|
||||
}
|
||||
|
@ -2491,13 +2392,8 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case OUTLINER_IDOP_FAKE_ADD: {
|
||||
/* set fake user */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_fake_user_set_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_fake_user_set_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr);
|
||||
ED_undo_push(C, "Add Fake User");
|
||||
|
@ -2505,13 +2401,8 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case OUTLINER_IDOP_FAKE_CLEAR: {
|
||||
/* clear fake user */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_fake_user_clear_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_fake_user_clear_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr);
|
||||
ED_undo_push(C, "Clear Fake User");
|
||||
|
@ -2520,20 +2411,15 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
case OUTLINER_IDOP_RENAME: {
|
||||
/* rename */
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn, nullptr);
|
||||
C, op->reports, scene, space_outliner, item_rename_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr);
|
||||
ED_undo_push(C, "Rename");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_SELECT_LINKED:
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_select_linked_fn,
|
||||
nullptr);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_select_linked_fn, nullptr);
|
||||
ED_outliner_select_sync_from_all_tag(C);
|
||||
ED_undo_push(C, "Select");
|
||||
break;
|
||||
|
@ -2616,21 +2502,19 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
|
|||
eOutlinerLibOpTypes event = (eOutlinerLibOpTypes)RNA_enum_get(op->ptr, "type");
|
||||
switch (event) {
|
||||
case OL_LIB_DELETE: {
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, id_delete_fn, nullptr);
|
||||
outliner_do_libdata_operation(C, op->reports, scene, space_outliner, id_delete_fn, nullptr);
|
||||
ED_undo_push(C, "Delete Library");
|
||||
break;
|
||||
}
|
||||
case OL_LIB_RELOCATE: {
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, lib_relocate_fn, nullptr);
|
||||
C, op->reports, scene, space_outliner, lib_relocate_fn, nullptr);
|
||||
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
|
||||
* trick does not work here). */
|
||||
break;
|
||||
}
|
||||
case OL_LIB_RELOAD: {
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, &space_outliner->tree, lib_reload_fn, nullptr);
|
||||
outliner_do_libdata_operation(C, op->reports, scene, space_outliner, lib_reload_fn, nullptr);
|
||||
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
|
||||
* trick does not work here). */
|
||||
break;
|
||||
|
@ -2673,11 +2557,10 @@ void OUTLINER_OT_lib_operation(wmOperatorType *ot)
|
|||
static void outliner_do_id_set_operation(
|
||||
SpaceOutliner *space_outliner,
|
||||
int type,
|
||||
ListBase *lb,
|
||||
ID *newid,
|
||||
void (*operation_fn)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
|
||||
{
|
||||
LISTBASE_FOREACH (TreeElement *, te, lb) {
|
||||
tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
|
||||
TreeStoreElem *tselem = TREESTORE(te);
|
||||
if (tselem->flag & TSE_SELECTED) {
|
||||
if (tselem->type == type) {
|
||||
|
@ -2685,10 +2568,7 @@ static void outliner_do_id_set_operation(
|
|||
operation_fn(te, tselem, tsep, newid);
|
||||
}
|
||||
}
|
||||
if (TSELEM_OPEN(tselem, space_outliner)) {
|
||||
outliner_do_id_set_operation(space_outliner, type, &te->subtree, newid, operation_fn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void actionset_id_fn(TreeElement *UNUSED(te),
|
||||
|
@ -2743,12 +2623,10 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
|
|||
|
||||
/* perform action if valid channel */
|
||||
if (datalevel == TSE_ANIM_DATA) {
|
||||
outliner_do_id_set_operation(
|
||||
space_outliner, datalevel, &space_outliner->tree, (ID *)act, actionset_id_fn);
|
||||
outliner_do_id_set_operation(space_outliner, datalevel, (ID *)act, actionset_id_fn);
|
||||
}
|
||||
else if (idlevel == ID_AC) {
|
||||
outliner_do_id_set_operation(
|
||||
space_outliner, idlevel, &space_outliner->tree, (ID *)act, actionset_id_fn);
|
||||
outliner_do_id_set_operation(space_outliner, idlevel, (ID *)act, actionset_id_fn);
|
||||
}
|
||||
else {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -2835,8 +2713,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
|
|||
switch (event) {
|
||||
case OUTLINER_ANIMOP_CLEAR_ADT:
|
||||
/* Remove Animation Data - this may remove the active action, in some cases... */
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, clear_animdata_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, clear_animdata_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, nullptr);
|
||||
ED_undo_push(C, "Clear Animation Data");
|
||||
|
@ -2853,32 +2730,23 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
|
|||
|
||||
case OUTLINER_ANIMOP_CLEAR_ACT:
|
||||
/* clear active action - using standard rules */
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, unlinkact_animdata_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, unlinkact_animdata_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, nullptr);
|
||||
ED_undo_push(C, "Unlink action");
|
||||
break;
|
||||
|
||||
case OUTLINER_ANIMOP_REFRESH_DRV:
|
||||
outliner_do_data_operation(space_outliner,
|
||||
datalevel,
|
||||
event,
|
||||
&space_outliner->tree,
|
||||
refreshdrivers_animdata_fn,
|
||||
nullptr);
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, refreshdrivers_animdata_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, nullptr);
|
||||
// ED_undo_push(C, "Refresh Drivers"); /* No undo needed - shouldn't have any impact? */
|
||||
break;
|
||||
|
||||
case OUTLINER_ANIMOP_CLEAR_DRV:
|
||||
outliner_do_data_operation(space_outliner,
|
||||
datalevel,
|
||||
event,
|
||||
&space_outliner->tree,
|
||||
cleardrivers_animdata_fn,
|
||||
nullptr);
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, cleardrivers_animdata_fn, nullptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, nullptr);
|
||||
ED_undo_push(C, "Clear Drivers");
|
||||
|
@ -2928,8 +2796,7 @@ static int outliner_constraint_operation_exec(bContext *C, wmOperator *op)
|
|||
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
|
||||
eOutliner_PropConstraintOps event = (eOutliner_PropConstraintOps)RNA_enum_get(op->ptr, "type");
|
||||
|
||||
outliner_do_data_operation(
|
||||
space_outliner, TSE_CONSTRAINT, event, &space_outliner->tree, constraint_fn, C);
|
||||
outliner_do_data_operation(space_outliner, TSE_CONSTRAINT, event, constraint_fn, C);
|
||||
|
||||
if (event == OL_CONSTRAINTOP_DELETE) {
|
||||
outliner_cleanup_tree(space_outliner);
|
||||
|
@ -2975,8 +2842,7 @@ static int outliner_modifier_operation_exec(bContext *C, wmOperator *op)
|
|||
SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
|
||||
eOutliner_PropModifierOps event = (eOutliner_PropModifierOps)RNA_enum_get(op->ptr, "type");
|
||||
|
||||
outliner_do_data_operation(
|
||||
space_outliner, TSE_MODIFIER, event, &space_outliner->tree, modifier_fn, C);
|
||||
outliner_do_data_operation(space_outliner, TSE_MODIFIER, event, modifier_fn, C);
|
||||
|
||||
if (event == OL_MODIFIER_OP_DELETE) {
|
||||
outliner_cleanup_tree(space_outliner);
|
||||
|
@ -3019,24 +2885,21 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
|
|||
eOutliner_PropDataOps event = (eOutliner_PropDataOps)RNA_enum_get(op->ptr, "type");
|
||||
switch (datalevel) {
|
||||
case TSE_POSE_CHANNEL: {
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, pchan_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, pchan_fn, nullptr);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
|
||||
ED_undo_push(C, "PoseChannel operation");
|
||||
|
||||
break;
|
||||
}
|
||||
case TSE_BONE: {
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, bone_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, bone_fn, nullptr);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
|
||||
ED_undo_push(C, "Bone operation");
|
||||
|
||||
break;
|
||||
}
|
||||
case TSE_EBONE: {
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, ebone_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, ebone_fn, nullptr);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, nullptr);
|
||||
ED_undo_push(C, "EditBone operation");
|
||||
|
||||
|
@ -3044,16 +2907,14 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case TSE_SEQUENCE: {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, sequence_fn, scene);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, sequence_fn, scene);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
|
||||
ED_undo_push(C, "Sequencer operation");
|
||||
|
||||
break;
|
||||
}
|
||||
case TSE_GP_LAYER: {
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, gpencil_layer_fn, nullptr);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, gpencil_layer_fn, nullptr);
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, nullptr);
|
||||
ED_undo_push(C, "Grease Pencil Layer operation");
|
||||
|
||||
|
@ -3061,8 +2922,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case TSE_RNA_STRUCT:
|
||||
if (event == OL_DOP_SELECT_LINKED) {
|
||||
outliner_do_data_operation(
|
||||
space_outliner, datalevel, event, &space_outliner->tree, data_select_linked_fn, C);
|
||||
outliner_do_data_operation(space_outliner, datalevel, event, data_select_linked_fn, C);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "UI_view2d.h"
|
||||
|
||||
#include "outliner_intern.hh"
|
||||
#include "tree/tree_iterator.hh"
|
||||
|
||||
using namespace blender::ed::outliner;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Tree View Context
|
||||
|
|
|
@ -438,7 +438,7 @@ static void outliner_deactivate(struct ScrArea *area)
|
|||
{
|
||||
/* Remove hover highlights */
|
||||
SpaceOutliner *space_outliner = reinterpret_cast<SpaceOutliner *>(area->spacedata.first);
|
||||
outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED_ANY, false);
|
||||
outliner_flag_set(*space_outliner, TSE_HIGHLIGHTED_ANY, false);
|
||||
ED_region_tag_redraw_no_rebuild(BKE_area_find_region_type(area, RGN_TYPE_WINDOW));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue