diff options
Diffstat (limited to 'source/blender/editors/space_outliner')
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"); |