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')
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c187
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c81
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h4
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c34
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c17
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c195
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c5
9 files changed, 337 insertions, 202 deletions
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index e0041d36a24..206cdd57342 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -65,7 +65,7 @@ bool outliner_is_collection_tree_element(const TreeElement *te)
return false;
}
- if (tselem->type == TSE_LAYER_COLLECTION) {
+ if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
return true;
}
else if (tselem->type == 0 && te->idcode == ID_GR) {
@@ -87,7 +87,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
LayerCollection *lc = te->directdata;
return lc->collection;
}
- else if (ELEM(tselem->type, TSE_R_LAYER, TSE_SCENE_COLLECTION_BASE)) {
+ else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
Scene *scene = (Scene*)tselem->id;
return BKE_collection_master(scene);
}
@@ -104,7 +104,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
static int collections_editor_poll(bContext *C)
{
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so != NULL) && ELEM(so->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER, SO_SCENES);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES);
}
@@ -145,19 +145,17 @@ static int collection_new_exec(bContext *C, wmOperator *op)
.collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
- return OPERATOR_CANCELLED;
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
}
- if (!data.collection) {
- if (!(soops->outlinevis == SO_COLLECTIONS &&
- ELEM(soops->filter_collection, SO_FILTER_COLLECTION_UNLINKED, SO_FILTER_COLLECTION_ALL)))
- {
- data.collection = BKE_collection_master(scene);
- }
+ if (!data.collection && (soops->outlinevis == SO_VIEW_LAYER)) {
+ data.collection = BKE_collection_master(scene);
}
BKE_collection_add(
@@ -184,6 +182,10 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "nested", true, "Nested", "Add as child of selected collection");;
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**************************** Delete Collection ******************************/
@@ -265,7 +267,8 @@ void OUTLINER_OT_collection_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/****************************** Select Objects *******************************/
@@ -285,6 +288,8 @@ static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeEle
data->layer_collection = te->directdata;
return TRAVERSE_BREAK;
case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
return TRAVERSE_CONTINUE;
default:
return TRAVERSE_SKIP_CHILDS;
@@ -365,6 +370,8 @@ static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *
data->te = te;
return TRAVERSE_BREAK;
case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
default:
return TRAVERSE_CONTINUE;
}
@@ -400,7 +407,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
switch (soops->outlinevis) {
case SO_SCENES:
case SO_VIEW_LAYER:
- case SO_COLLECTIONS:
+ case SO_LIBRARIES:
BKE_collection_copy(bmain, parent, collection);
break;
}
@@ -538,3 +545,153 @@ void OUTLINER_OT_collection_instance(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/************************** Exclude Collection ******************************/
+
+static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
+{
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
+ }
+
+ LayerCollection *lc = te->directdata;
+
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+static int collections_view_layer_poll(bContext *C, bool include)
+{
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ }
+
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
+}
+
+static int collections_exclude_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, false);
+}
+
+static int collections_include_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, true);
+}
+
+static void layer_collection_exclude_recursive_set(LayerCollection *lc)
+{
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+
+ layer_collection_exclude_recursive_set(nlc);
+ }
+}
+
+static int collection_view_layer_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
+
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ if (include) {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+
+ layer_collection_exclude_recursive_set(lc);
+ }
+ }
+
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Exclude from View Layer";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Include in View Layer";
+ ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->description = "Include collection in the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_include_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d92b5df56be..90b137bcd7d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -262,38 +262,6 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-static void layer_collection_exclude_recursive_set(LayerCollection *lc)
-{
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- nlc->flag |= LAYER_COLLECTION_EXCLUDE;
- }
- else {
- nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
- }
-
- layer_collection_exclude_recursive_set(nlc);
- }
-}
-
-static void layer_collection_exclude_cb(bContext *C, void *poin, void *poin2)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = (Scene *)poin;
- LayerCollection *lc = (LayerCollection *)poin2;
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
-
- layer_collection_exclude_recursive_set(lc);
-
- BKE_layer_collection_sync(scene, view_layer);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
-}
-
-
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
Main *bmain = CTX_data_main(C);
@@ -423,10 +391,6 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
break;
}
- case TSE_R_LAYER:
- {
- break;
- }
case TSE_LAYER_COLLECTION:
{
BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
@@ -450,15 +414,12 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
PropertyRNA *collection_prop_hide_viewport;
PropertyRNA *collection_prop_hide_select;
PropertyRNA *collection_prop_hide_render;
- PropertyRNA *collection_prop_exclude;
collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
- collection_prop_exclude = RNA_struct_type_find_property(&RNA_LayerCollection, "use");
BLI_assert(collection_prop_hide_viewport &&
collection_prop_hide_select &&
- collection_prop_hide_render &&
- collection_prop_exclude);
+ collection_prop_hide_render);
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
@@ -568,20 +529,9 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- if (soops->outlinevis == SO_VIEW_LAYER) {
- if (lc && !(collection->flag & COLLECTION_IS_MASTER)) {
- PointerRNA layer_collection_ptr;
- RNA_pointer_create(&scene->id, &RNA_LayerCollection, lc, &layer_collection_ptr);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0,
- (lc->flag & LAYER_COLLECTION_EXCLUDE) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &layer_collection_ptr, collection_prop_exclude, -1, 0, 0, 0, 0, NULL);
- UI_but_func_set(bt, layer_collection_exclude_cb, scene, lc);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- }
- else if (!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER))
+ {
PointerRNA collection_ptr;
RNA_id_pointer_create(&collection->id, &collection_ptr);
@@ -1111,6 +1061,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
break;
case TSE_LAYER_COLLECTION:
case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
ICON_DRAW(ICON_GROUP);
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
@@ -1249,6 +1200,11 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
}
+ case ID_BR:
+ tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break;
+ case ID_SCR:
+ case ID_WS:
+ tselem_draw_icon_uibut(&arg, ICON_SPLITSCREEN); break;
default:
break;
}
@@ -1320,10 +1276,11 @@ static void outliner_draw_iconrow(
}
/* this tree element always has same amount of branches, so don't draw */
- if (tselem->type != TSE_R_LAYER)
+ if (tselem->type != TSE_R_LAYER) {
outliner_draw_iconrow(
C, block, scene, view_layer, obedit, soops,
&te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
+ }
}
}
@@ -1442,8 +1399,8 @@ static void outliner_draw_tree_element(
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
- if (tselem->type == TSE_R_LAYER && ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_OBJECTS)) {
- /* View layer in collections can't expand/collapse. */
+ if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
+ /* Scene collection in view layer can't expand/collapse. */
}
else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
@@ -1461,7 +1418,7 @@ static void outliner_draw_tree_element(
/* datatype icon */
- if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
+ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
}
@@ -1746,7 +1703,7 @@ static void outliner_draw_highlights_recursive(
int start_x, int *io_start_y)
{
const bool is_searching = SEARCHING_OUTLINER(soops) ||
- (soops->outlinevis == SO_DATABLOCKS &&
+ (soops->outlinevis == SO_DATA_API &&
(soops->filter & SO_FILTER_SEARCH) &&
soops->search_string[0] != 0);
@@ -1814,7 +1771,7 @@ static void outliner_draw_tree(
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // only once
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* struct marks */
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
@@ -1940,7 +1897,7 @@ void draw_outliner(const bContext *C)
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* RNA has two columns:
* - column 1 is (max_width + OL_RNA_COL_SPACEX) or
* (OL_RNA_COL_X), whichever is wider...
@@ -1990,7 +1947,7 @@ void draw_outliner(const bContext *C)
(bContext *)C, block, scene, view_layer, obedit,
ar, soops, has_restrict_icons, &te_edit);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* draw rna buttons */
outliner_draw_rnacols(ar, sizex_rna);
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4bb2f49fd08..5922e208f36 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -264,7 +264,8 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
/* do nothing */;
}
else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE))
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
@@ -1338,7 +1339,7 @@ static int ed_operator_outliner_datablocks_active(bContext *C)
ScrArea *sa = CTX_wm_area(C);
if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_DATABLOCKS);
+ return (so->outlinevis == SO_DATA_API);
}
return 0;
}
@@ -2063,7 +2064,12 @@ static int outliner_parenting_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
if (soops) {
- if (ELEM(soops->outlinevis, SO_SCENES, SO_OBJECTS)) {
+ if (soops->outlinevis == SO_SCENES) {
+ return true;
+ }
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
return true;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 86208dcb22d..73494b890ed 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -163,7 +163,7 @@ typedef enum {
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
-#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_COLLECTIONS, SO_OBJECTS))
+#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_VIEW_LAYER))
/* Outliner Searching --
*
@@ -345,6 +345,8 @@ void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index d7a158b92a6..9c1b9bf2630 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -69,7 +69,7 @@ static int outliner_item_drag_drop_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
return ED_operator_outliner_active(C) &&
/* Only collection display modes supported for now. Others need more design work */
- ELEM(soops->outlinevis, SO_COLLECTIONS, SO_OBJECTS);
+ ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -455,6 +455,8 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
WM_operatortype_append(OUTLINER_OT_collection_link);
WM_operatortype_append(OUTLINER_OT_collection_instance);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
+ WM_operatortype_append(OUTLINER_OT_collection_include_set);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 810b7815214..42fe70be527 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -681,6 +681,27 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState tree_element_active_master_collection(
+ bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == view_layer->layer_collections.first) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = view_layer->layer_collections.first;
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ return OL_DRAWSEL_NONE;
+}
+
static eOLDrawState tree_element_active_layer_collection(
bContext *C, TreeElement *te, const eOLSetState set)
{
@@ -695,7 +716,7 @@ static eOLDrawState tree_element_active_layer_collection(
Scene *scene = CTX_data_scene(C);
LayerCollection *layer_collection = te->directdata;
ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
- view_layer->active_collection = layer_collection;
+ BKE_layer_collection_activate(view_layer, layer_collection);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -763,12 +784,7 @@ eOLDrawState tree_element_type_active(
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- if (soops->outlinevis == SO_SCENES) {
- return active_viewlayer(C, scene, view_layer, te, tselem, set);
- }
- else {
- return OL_DRAWSEL_NONE;
- }
+ return active_viewlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
@@ -780,6 +796,8 @@ eOLDrawState tree_element_type_active(
case TSE_GP_LAYER:
//return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
case TSE_LAYER_COLLECTION:
return tree_element_active_layer_collection(C, te, set);
}
@@ -905,7 +923,7 @@ static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_
static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
{
- return ((soops->outlinevis != SO_DATABLOCKS) &&
+ return ((soops->outlinevis != SO_DATA_API) &&
!(soops->flag & SO_HIDE_RESTRICTCOLS) &&
(view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 6ee8b354772..5ae6cec84ba 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -105,11 +105,8 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == TSE_R_LAYER && soops->outlinevis == SO_COLLECTIONS) {
- /* Don't let immutable render layer item affect menu. */
- }
- else if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
- /* Layer collection points to collection ID. */
+ /* Layer collection points to collection ID. */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0)
*datalevel = tselem->type;
else if (*datalevel != tselem->type)
@@ -133,6 +130,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LI:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
break;
}
}
@@ -1824,12 +1824,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_LAYER_COLLECTION) {
WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
}
- else if (datalevel == TSE_R_LAYER && ELEM(soops->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER)) {
+ else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
- else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER)) {
- /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
- }
else if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
}
@@ -1880,7 +1877,7 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
if (!found) {
/* Menus for clicking in empty space. */
- if (ELEM(soops->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER)) {
+ if (soops->outlinevis == SO_VIEW_LAYER) {
WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 22d70a12261..58ab8f3735e 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -299,7 +299,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
/* Collections */
ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
- ten->name = IFACE_("Collections");
+ ten->name = IFACE_("Scene Collection");
outliner_add_collection_recursive(soops, sce->master_collection, ten);
/* Objects */
@@ -877,7 +877,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE)) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -896,8 +896,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID datablock */
- if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
outliner_add_id_contents(soops, te, tselem, id);
+ }
}
else if (type == TSE_ANIM_DATA) {
IdAdtTemplate *iat = (IdAdtTemplate *)idv;
@@ -1252,16 +1253,56 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
/* ----------------------------------------------- */
+static const char *outliner_idcode_to_plural(short idcode)
+{
+ const char *propname = BKE_idcode_to_name_plural(idcode);
+ PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
+ return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
+}
+
+static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
+{
+ if (id->lib != lib) {
+ return false;
+ }
+
+ if (filter_id_type == ID_GR) {
+ /* Don't show child collections of non-scene master collection,
+ * they are already shown as children. */
+ Collection *collection = (Collection *)id;
+ bool has_non_scene_parent = false;
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
+ has_non_scene_parent = true;
+ }
+ }
+
+ if (has_non_scene_parent) {
+ return false;
+ }
+ }
+
+ return true;
+}
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
{
TreeElement *ten;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
- tot = set_listbasepointers(mainvar, lbarray);
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
for (a = 0; a < tot; a++) {
- if (lbarray[a]->first) {
+ if (lbarray[a] && lbarray[a]->first) {
ID *id = lbarray[a]->first;
/* check if there's data in current lib */
@@ -1270,21 +1311,23 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
break;
if (id) {
- ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
+ if (filter_id_type) {
+ ten = te;
+ }
+ else {
+ ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
for (id = lbarray[a]->first; id; id = id->next) {
- if (id->lib == lib)
+ if (outliner_library_id_show(lib, id, filter_id_type)) {
outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
}
}
}
}
-
}
static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
@@ -1292,10 +1335,18 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
TreeElement *ten;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
- tot = set_listbasepointers(mainvar, lbarray);
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
for (a = 0; a < tot; a++) {
- if (lbarray[a]->first) {
+ if (lbarray[a] && lbarray[a]->first) {
ID *id = lbarray[a]->first;
/* check if there are any datablocks of this type which are orphans */
@@ -1306,21 +1357,19 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
if (id) {
/* header for this type of datablock */
- /* TODO's:
- * - Add a parameter to BKE_idcode_to_name_plural to get a sane "user-visible" name instead?
- * - Ensure that this uses nice icons for the datablock type involved instead of the dot?
- */
- ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
+ if (filter_id_type) {
+ ten = NULL;
+ }
+ else {
+ ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
/* add the orphaned datablocks - these will not be added with any subtrees attached */
for (id = lbarray[a]->first; id; id = id->next) {
if (ID_REAL_USERS(id) <= 0)
- outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
}
}
}
@@ -1412,33 +1461,12 @@ static void outliner_add_layer_collection_objects(
}
}
-static bool outliner_layer_collection_is_visible(LayerCollection *lc)
-{
- if (!(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
- return true;
- }
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (outliner_layer_collection_is_visible(nlc)) {
- return true;
- }
- }
-
- return false;
-}
-
static void outliner_add_layer_collections_recursive(
SpaceOops *soops, ListBase *tree, ViewLayer *layer,
ListBase *layer_collections, TreeElement *parent_ten,
const bool show_objects)
{
for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
- if ((soops->outlinevis != SO_VIEW_LAYER) &&
- !outliner_layer_collection_is_visible(lc))
- {
- continue;
- }
-
ID *id = &lc->collection->id;
TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
@@ -1477,7 +1505,7 @@ static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElemen
BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
if (collection->flag & COLLECTION_IS_MASTER) {
- te->name = IFACE_("Collections");
+ te->name = IFACE_("Scene Collection");
}
else {
te->name = collection->id.name + 2;
@@ -1776,7 +1804,8 @@ static TreeElement *outliner_find_first_desired_element_at_y(
te = outliner_find_item_at_y(soops, &soops->tree, view_co);
bool (*callback_test)(TreeElement *);
- if (soops->outlinevis == SO_OBJECTS) {
+ if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION)) {
callback_test = test_object_callback;
}
else {
@@ -1855,7 +1884,7 @@ static int outliner_exclude_filter_get(SpaceOops *soops)
return (exclude_filter & SO_FILTER_SEARCH);
}
- if (soops->outlinevis == SO_COLLECTIONS && (soops->filter & SO_FILTER_NO_OBJECT)) {
+ if (soops->filter & SO_FILTER_NO_OBJECT) {
exclude_filter |= SO_FILTER_OB_TYPE;
}
@@ -2070,7 +2099,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
/* Are we looking for something - we want to tag parents to filter child matches
* - NOT in datablocks view - searching all datablocks takes way too long to be useful
* - this variable is only set once per tree build */
- if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATABLOCKS)
+ if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATA_API)
soops->search_flags |= SO_SEARCH_RECURSIVE;
else
soops->search_flags &= ~SO_SEARCH_RECURSIVE;
@@ -2177,7 +2206,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
seq = seq->next;
}
}
- else if (soops->outlinevis == SO_DATABLOCKS) {
+ else if (soops->outlinevis == SO_DATA_API) {
PointerRNA mainptr;
RNA_main_pointer_create(mainvar, &mainptr);
@@ -2192,59 +2221,25 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
- else if (soops->outlinevis == SO_COLLECTIONS &&
- soops->filter_collection != SO_FILTER_COLLECTION_SCENE) {
- Collection *collection;
- for (collection = mainvar->collection.first; collection; collection = collection->id.next) {
- if (soops->filter_collection == SO_FILTER_COLLECTION_UNLINKED) {
- /* Skip collections used in a scene */
- if (BKE_collection_is_in_scene(collection)) {
- continue;
- }
- }
-
- if (collection->parents.first) {
- /* Don't show child collections of non-scene master collection,
- * they are already shown as children. */
- bool has_non_scene_parent = false;
-
- for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
- if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
- has_non_scene_parent = true;
- }
- }
-
- if (has_non_scene_parent) {
- continue;
- }
+ else if (soops->outlinevis == SO_VIEW_LAYER) {
+ if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ /* Show objects in the view layer. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ te_object->directdata = base;
}
- te = outliner_add_element(soops, &soops->tree, collection, NULL, 0, 0);
+ outliner_make_object_parent_hierarchy(&soops->tree);
}
- }
- else if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS)) {
- /* Show collections and objects in the view layer. */
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
-
- bool show_objects = (soops->outlinevis == SO_COLLECTIONS) &&
- !(soops->filter & SO_FILTER_NO_OBJECT);
- outliner_add_view_layer(soops, &tenlay->subtree, tenlay, view_layer, show_objects);
- }
- else { /* SO_OBJECTS */
- /* Show objects in the view layer. */
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
+ else {
+ /* Show collections in the view layer. */
+ ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- TreeElement *te_object = outliner_add_element(soops, &tenlay->subtree, base->object, NULL, 0, 0);
- te_object->directdata = base;
+ bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
+ outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
}
- outliner_make_object_parent_hierarchy(&tenlay->subtree);
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index dc6406fcc18..72ce24aaff5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -159,7 +159,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM(soops->outlinevis, SO_SCENES, SO_COLLECTIONS, SO_OBJECTS)) {
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
return false;
}
@@ -434,7 +434,7 @@ static void outliner_main_region_message_subscribe(
.notify = ED_region_do_msg_notify_tag_redraw,
};
- if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_OBJECTS)) {
+ if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
}
}
@@ -483,6 +483,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner = MEM_callocN(sizeof(SpaceOops), "initoutliner");
soutliner->spacetype = SPACE_OUTLINER;
+ soutliner->filter_id_type = ID_GR;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");