Outliner visibility unification: Implement 3 levels of viewport visibility
authorDalai Felinto <dfelinto@gmail.com>
Fri, 30 Nov 2018 04:24:06 +0000 (02:24 -0200)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 5 Feb 2019 21:32:58 +0000 (19:32 -0200)
Now collection and objects can be either:
* Disabled for all the view layers.
* Hidden for a view layer but not necessarily for all others.
* Visible for a view layer but not necessarily for all others.

Regarding icons: Whatever we decide to use for the "Hidden for all view
layers" needs to be a toggle-like icon. Because when viewing "Scenes"
instead of "View Layer" in the outliner we should be able to edit the
collection "Hidden for all the view layers" as an on/off option.

The operators are accessible via a Visibility context menu or shortcuts:
* Ctrl + Click: Isolate collection (use shift to extend).
* Alt + Click: Disable collection.
* Shift + Click: Hide/Show collection and its children (objects and collections)

Things yet to be tackled:
* Object outliner context menu can also get a Visibility sub-menu.
* Get better icons for viewport enable/disable.

Note:
* When using emulate 3 button mouse alt+click is used for 2d panning.
  In this case users have to use the operator from the menu.

See T57857 for discussion.

Patch: https://developer.blender.org/D4011
Reviewers: brecht and sergey

Thanks to the reviewers and William Reynish and Julien Kasper in
particular for the feedback.

12 files changed:
release/scripts/startup/bl_ui/space_outliner.py
source/blender/blenkernel/BKE_layer.h
source/blender/blenkernel/intern/layer.c
source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
source/blender/editors/object/object_edit.c
source/blender/editors/space_outliner/outliner_collections.c
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/makesrna/intern/rna_layer.c

index 4ab990c451b7c2556066e09f082433488b638929..59fd47017489a42b1720ab7b10327524e3d824a4 100644 (file)
@@ -148,6 +148,29 @@ class OUTLINER_MT_collection_view_layer(Menu):
             layout.operator("outliner.collection_holdout_clear")
 
 
+class OUTLINER_MT_collection_visibility(Menu):
+    bl_label = "Visibility"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("outliner.collection_isolate", text="Isolate")
+        layout.operator("outliner.collection_show", text="Show")
+        layout.operator("outliner.collection_hide", text="Hide")
+
+        layout.separator()
+        layout.operator("outliner.collection_show_inside", text="Show All Inside")
+        layout.operator("outliner.collection_hide_inside", text="Hide All Inside")
+
+        layout.separator()
+        layout.operator("outliner.collection_enable", text="Enable in Viewports")
+        layout.operator("outliner.collection_disable", text="Disable in Viewports")
+
+        layout.separator()
+        layout.operator("outliner.collection_enable_render", text="Enable in Render")
+        layout.operator("outliner.collection_disable_render", text="Disable in Render")
+
+
 class OUTLINER_MT_collection(Menu):
     bl_label = "Collection"
 
@@ -177,6 +200,9 @@ class OUTLINER_MT_collection(Menu):
             layout.separator()
             layout.menu("OUTLINER_MT_collection_view_layer")
 
+        layout.separator()
+        layout.menu("OUTLINER_MT_collection_visibility")
+
         layout.separator()
         layout.operator_menu_enum("outliner.id_operation", "type", text="ID Data")
 
@@ -301,6 +327,7 @@ classes = (
     OUTLINER_MT_edit_datablocks,
     OUTLINER_MT_collection,
     OUTLINER_MT_collection_new,
+    OUTLINER_MT_collection_visibility,
     OUTLINER_MT_collection_view_layer,
     OUTLINER_MT_object,
     OUTLINER_MT_context,
index cff80ef3467cb092e91258a9cd3daebe7e878d82..65c0202ef664d00bf07246617061b7ea231c4598 100644 (file)
@@ -109,7 +109,8 @@ bool BKE_layer_collection_has_layer_collection(
         struct LayerCollection *lc_parent, struct LayerCollection *lc_child);
 
 void BKE_base_set_visible(struct Scene *scene, struct ViewLayer *view_layer, struct Base *base, bool extend);
-void BKE_layer_collection_set_visible(struct Scene *scene, struct ViewLayer *view_layer, struct LayerCollection *lc, bool extend);
+bool BKE_layer_collection_isolate(struct Scene *scene, struct ViewLayer *view_layer, struct LayerCollection *lc, bool extend);
+bool BKE_layer_collection_set_visible(struct ViewLayer *view_layer, struct LayerCollection *lc, const bool visible, const bool hierarchy);
 
 /* evaluation */
 
index 0b49a389ab11e5b4da712b2d58df5dc2b82a3aa4..f9d39c840e2858defc13e31c8ef5eff139744409 100644 (file)
@@ -669,7 +669,9 @@ static short layer_collection_sync(
                        lc->runtime_flag = child_runtime_flag;
                }
 
-               if ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0) {
+               if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) &&
+                   ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0))
+               {
                        lc->runtime_flag |= LAYER_COLLECTION_VISIBLE;
                }
 
@@ -701,15 +703,18 @@ static short layer_collection_sync(
                        int object_restrict = base->object->restrictflag;
 
                        if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) &&
-                           ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
                            ((object_restrict & OB_RESTRICT_VIEW) == 0))
                        {
-                               base->flag |= BASE_VISIBLE | BASE_ENABLED | BASE_ENABLED_VIEWPORT;
+                               base->flag |= BASE_ENABLED | BASE_ENABLED_VIEWPORT;
 
-                               if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) &&
-                                   ((object_restrict & OB_RESTRICT_SELECT) == 0))
-                               {
-                                       base->flag |= BASE_SELECTABLE;
+                               if ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0) {
+                                       base->flag |= BASE_VISIBLE;
+
+                                       if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) &&
+                                               ((object_restrict & OB_RESTRICT_SELECT) == 0))
+                                       {
+                                               base->flag |= BASE_SELECTABLE;
+                                       }
                                }
                        }
 
@@ -720,7 +725,7 @@ static short layer_collection_sync(
                        }
 
                        /* Update runtime flags used for display and tools. */
-                       if (base->flag & BASE_VISIBLE) {
+                       if (base->flag & BASE_ENABLED) {
                                lc->runtime_flag |= LAYER_COLLECTION_HAS_ENABLED_OBJECTS;
                        }
 
@@ -987,48 +992,124 @@ static void layer_collection_flag_unset_recursive(LayerCollection *lc, const int
 }
 
 /**
- * Set collection per-view layer visiblity.
- * When not extending, we show all the direct parents and all children of the layer collection.
+ * Return true if something changed. */
+static bool layer_collection_collection_flag_unset_recursive(LayerCollection *lc, const int flag)
+{
+       bool changed = (lc->collection->flag & flag) != 0;
+
+       lc->collection->flag &= ~flag;
+       for (LayerCollection *lc_iter = lc->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+               changed |= layer_collection_collection_flag_unset_recursive(lc_iter, flag);
+       }
+
+       return changed;
+}
+
+/**
+ * Isolate the collection - hide all other collections but this one.
+ * Make sure to show all the direct parents and all children of the layer collection as well.
+ * When extending we simply show the collections and its direct family.
+ *
+ * Return whether depsgraph needs update.
  */
-void BKE_layer_collection_set_visible(Scene *scene, ViewLayer *view_layer, LayerCollection *lc, bool extend)
+bool BKE_layer_collection_isolate(Scene *scene, ViewLayer *view_layer, LayerCollection *lc, bool extend)
 {
+       bool depsgraph_need_update = false;
        if (!extend) {
-               /* Make only this collection visible. */
+               /* Hide all collections . */
                for (LayerCollection *lc_iter = view_layer->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
                        layer_collection_flag_set_recursive(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
                }
+       }
 
-               /* Make all the direct parents visible. */
-               LayerCollection *lc_parent = lc;
-               LayerCollection *lc_master = view_layer->layer_collections.first;
-               for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+       /* Make all the direct parents visible. */
+       LayerCollection *lc_parent = lc;
+       LayerCollection *lc_master = view_layer->layer_collections.first;
+       for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+               if (BKE_layer_collection_has_layer_collection(lc_iter, lc)) {
+                       lc_parent = lc_iter;
+                       break;
+               }
+       }
+
+       while (lc_parent != lc) {
+               depsgraph_need_update |= (lc_parent->collection->flag & COLLECTION_RESTRICT_VIEW) != 0;
+               lc_parent->collection->flag &= ~COLLECTION_RESTRICT_VIEW;
+               lc_parent->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+
+               for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
                        if (BKE_layer_collection_has_layer_collection(lc_iter, lc)) {
                                lc_parent = lc_iter;
                                break;
                        }
                }
+       }
 
-               while (lc_parent != lc) {
-                       lc_parent->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+       /* Make all the children visible. */
+       layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+       depsgraph_need_update |= layer_collection_collection_flag_unset_recursive(lc, COLLECTION_RESTRICT_VIEW);
 
-                       for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
-                               if (BKE_layer_collection_has_layer_collection(lc_iter, lc)) {
-                                       lc_parent = lc_iter;
-                                       break;
-                               }
-                       }
-               }
+       BKE_layer_collection_activate(view_layer, lc);
+
+       BKE_layer_collection_sync(scene, view_layer);
+
+       return depsgraph_need_update;
+}
 
-               /* Make all the children visible. */
-               layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+static void layer_collection_bases_show_recursive(ViewLayer *view_layer, LayerCollection *lc)
+{
+       for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+               Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
+               base->flag &= ~BASE_HIDDEN;
+               base->object->restrictflag &= ~OB_RESTRICT_VIEW;
+       }
+       for (LayerCollection *lc_iter = lc->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+               layer_collection_bases_show_recursive(view_layer, lc_iter);
+       }
+}
 
-               BKE_layer_collection_activate(view_layer, lc);
+static void layer_collection_bases_hide_recursive(ViewLayer *view_layer, LayerCollection *lc)
+{
+       for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+               Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
+               base->flag |= BASE_HIDDEN;
        }
-       else {
-               lc->flag ^= LAYER_COLLECTION_RESTRICT_VIEW;
+       for (LayerCollection *lc_iter = lc->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+               layer_collection_bases_hide_recursive(view_layer, lc_iter);
        }
+}
 
-       BKE_layer_collection_sync(scene, view_layer);
+/**
+ * Hide/show all the elements of a collection.
+ * Enable a disable collection if needs be.
+ *
+ * Return true if depsgraph needs update.
+ */
+bool BKE_layer_collection_set_visible(ViewLayer *view_layer, LayerCollection *lc, const bool visible, const bool hierarchy)
+{
+       bool depsgraph_changed = false;
+       if (hierarchy) {
+               if (visible) {
+                       depsgraph_changed |= layer_collection_collection_flag_unset_recursive(lc, COLLECTION_RESTRICT_VIEW);
+                       layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+                       layer_collection_bases_show_recursive(view_layer, lc);
+               }
+               else {
+                       layer_collection_flag_set_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+                       layer_collection_bases_hide_recursive(view_layer, lc);
+               }
+       }
+       else {
+               if (visible) {
+                       depsgraph_changed |= (lc->collection->flag & COLLECTION_RESTRICT_VIEW) != 0;
+                       lc->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+                       lc->collection->flag &= ~COLLECTION_RESTRICT_VIEW;
+               }
+               else {
+                       lc->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
+               }
+       }
+       return depsgraph_changed;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -1384,7 +1465,7 @@ void BKE_layer_eval_view_layer(
 
        /* Visibility based on depsgraph mode. */
        const eEvaluationMode mode = DEG_get_mode(depsgraph);
-       const int base_visible_flag = (mode == DAG_EVAL_VIEWPORT)
+       const int base_enabled_flag = (mode == DAG_EVAL_VIEWPORT)
                ? BASE_ENABLED_VIEWPORT
                : BASE_ENABLED_RENDER;
        /* Create array of bases, for fast index-based lookup. */
@@ -1395,10 +1476,12 @@ void BKE_layer_eval_view_layer(
        int base_index = 0;
        for (Base *base = view_layer->object_bases.first; base; base = base->next) {
                /* Compute visibility for depsgraph evaluation mode. */
-               if (base->flag & base_visible_flag) {
-                       base->flag |= BASE_ENABLED | BASE_VISIBLE;
-                       if (mode == DAG_EVAL_VIEWPORT && (base->flag & BASE_HIDDEN)) {
-                               base->flag &= ~BASE_VISIBLE;
+               if (base->flag & base_enabled_flag) {
+                       base->flag |= BASE_ENABLED;
+
+                       /* When rendering, visibility is controlled by the enable/disable option. */
+                       if (mode == DAG_EVAL_RENDER) {
+                               base->flag |= BASE_VISIBLE;
                        }
                }
                else {
@@ -1416,7 +1499,7 @@ void BKE_layer_eval_view_layer(
                Base *base_orig = view_layer_orig->object_bases.first;
                const Base *base_eval = view_layer->object_bases.first;
                while (base_orig != NULL) {
-                       if (base_orig->flag & base_visible_flag) {
+                       if (base_orig->flag & base_enabled_flag) {
                                base_orig->flag = base_eval->flag;
                                base_eval = base_eval->next;
                        }
index 00981d7566503f9fc23fbeb9cd87320b8f7e426d..cc2d58dbe51aa9a6473bc8dea51fc6a8b6b8462d 100644 (file)
@@ -64,11 +64,6 @@ void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb)
                COLLECTION_RESTRICT_VIEW : COLLECTION_RESTRICT_RENDER;
 
        for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
-               if ((graph_->mode == DAG_EVAL_VIEWPORT) &&
-                   ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0))
-               {
-                       continue;
-               }
                if (lc->collection->flag & restrict_flag) {
                        continue;
                }
index 7f4a388718f8303065bdc86dcf468bdaed7bf22b..c0fe5243e583066bf34bf3b2ea7662a35828d316 100644 (file)
@@ -65,11 +65,6 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
                COLLECTION_RESTRICT_VIEW : COLLECTION_RESTRICT_RENDER;
 
        for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
-               if ((graph_->mode == DAG_EVAL_VIEWPORT) &&
-                   ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0))
-               {
-                       continue;
-               }
                if ((lc->collection->flag & restrict_flag)) {
                        continue;
                }
index ff3128a2fb695c03a365a7bbc7787a291ae55d87..c705026b6403ba168c49523089444e6dba78b87c 100644 (file)
@@ -359,23 +359,23 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
        scene_cow->view_layers.last = view_layer_eval;
 }
 
-/* Makes it so given view layer only has bases corresponding to a visible
+/* Makes it so given view layer only has bases corresponding to enabled
  * objects. */
-void view_layer_remove_invisible_bases(const Depsgraph *depsgraph,
-                                       ViewLayer *view_layer)
+void view_layer_remove_disabled_bases(const Depsgraph *depsgraph,
+                                      ViewLayer *view_layer)
 {
-       const int base_visible_flag = (depsgraph->mode == DAG_EVAL_VIEWPORT) ?
+       const int base_enabled_flag = (depsgraph->mode == DAG_EVAL_VIEWPORT) ?
                BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER;
-       ListBase visible_bases = {NULL, NULL};
+       ListBase enabled_bases = {NULL, NULL};
        for (Base *base = reinterpret_cast<Base *>(view_layer->object_bases.first),
                  *base_next;
             base != NULL;
             base = base_next)
        {
                base_next = base->next;
-               const bool is_object_visible = (base->flag & base_visible_flag);
-               if (is_object_visible) {
-                       BLI_addtail(&visible_bases, base);
+               const bool is_object_enabled = (base->flag & base_enabled_flag);
+               if (is_object_enabled) {
+                       BLI_addtail(&enabled_bases, base);
                }
                else {
                        if (base == view_layer->basact) {
@@ -384,13 +384,13 @@ void view_layer_remove_invisible_bases(const Depsgraph *depsgraph,
                        MEM_freeN(base);
                }
        }
-       view_layer->object_bases = visible_bases;
+       view_layer->object_bases = enabled_bases;
 }
 
 void scene_cleanup_view_layers(const Depsgraph *depsgraph, Scene *scene_cow)
 {
        scene_remove_unused_view_layers(depsgraph, scene_cow);
-       view_layer_remove_invisible_bases(
+       view_layer_remove_disabled_bases(
                depsgraph,
                reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first));
        /* TODO(sergey): Remove objects from collections as well.
index 686c03b3e16d10e37596f1a57eb935faba20ec3c..9bd0de83ca5b461e573d9871e294d206170853ac 100644 (file)
@@ -283,10 +283,12 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
-       BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
-
-       DEG_relations_tag_update(CTX_data_main(C));
        DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+       if (BKE_layer_collection_isolate(scene, view_layer, lc, extend)) {
+               DEG_relations_tag_update(CTX_data_main(C));
+       }
+
        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 
        return OPERATOR_FINISHED;
index 772f3f8b3ff6df0970455962ee2bf2e3764462ae..0d8c88ecede6196c198e848b43d0f968b6655fc4 100644 (file)
@@ -820,6 +820,348 @@ void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/************************** Visibility Operators ******************************/
+
+static int collection_isolate_exec(bContext *C, wmOperator *op) {
+       Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+       const bool extend = RNA_boolean_get(op->ptr, "extend");
+       bool depsgraph_changed = false;
+       struct CollectionEditData data = {.scene = scene, .soops = soops,};
+       data.collections_to_edit = BLI_gset_ptr_new(__func__);
+
+       /* Hide all collections before the isolate function - needed in order to support. */
+       if (!extend) {
+               for (LayerCollection *lc_iter = view_layer->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
+                       lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
+                       layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+               }
+       }
+
+       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 *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+               depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, layer_collection, true);
+       }
+       BLI_gset_free(data.collections_to_edit, NULL);
+
+       BKE_layer_collection_sync(scene, view_layer);
+       DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+       if (depsgraph_changed) {
+               DEG_relations_tag_update(CTX_data_main(C));
+       }
+
+       WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+       return OPERATOR_FINISHED;
+}
+
+static int collection_isolate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       PropertyRNA *prop = RNA_struct_find_property(op->ptr, "extend");
+       if (!RNA_property_is_set(op->ptr, prop) && (event->shift)) {
+               RNA_property_boolean_set(op->ptr, prop, true);
+       }
+       return collection_isolate_exec(C, op);
+}
+
+void OUTLINER_OT_collection_isolate(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Isolate Collection";
+       ot->idname = "OUTLINER_OT_collection_isolate";
+       ot->description = "Hide all but this collection and its parents";
+
+       /* api callbacks */
+       ot->exec = collection_isolate_exec;
+       ot->invoke = collection_isolate_invoke;
+       ot->poll = ED_outliner_collections_editor_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+       /* properties */
+       PropertyRNA *prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend current visible collections");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+static bool collection_show_poll(bContext *C)
+{
+       return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW);
+}
+
+static bool collection_hide_poll(bContext *C)
+{
+       return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW);
+}
+
+static bool collection_inside_poll(bContext *C)
+{
+       if (!ED_outliner_collections_editor_poll(C)) {
+               return false;
+       }
+       return outliner_active_layer_collection(C) != NULL;
+}
+
+static int collection_visibility_exec(bContext *C, wmOperator *op) {
+       Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+       const bool is_inside = strstr(op->idname, "inside") != NULL;
+       const bool show = strstr(op->idname, "show") != NULL;
+       bool depsgraph_changed = false;
+       struct CollectionEditData data = {.scene = scene, .soops = soops,};
+       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 *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+               depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, layer_collection, show, is_inside);
+       }
+       BLI_gset_free(data.collections_to_edit, NULL);
+
+       BKE_layer_collection_sync(scene, view_layer);
+       DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+       if (depsgraph_changed) {
+               DEG_relations_tag_update(CTX_data_main(C));
+       }
+
+       WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+       return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_show(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Show Collection";
+       ot->idname = "OUTLINER_OT_collection_show";
+       ot->description = "Show the collection in this view layer";
+
+       /* api callbacks */
+       ot->exec = collection_visibility_exec;
+       ot->poll = collection_show_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_hide(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Hide Collection";
+       ot->idname = "OUTLINER_OT_collection_hide";
+       ot->description = "Hide the collection in this view layer";
+
+       /* api callbacks */
+       ot->exec = collection_visibility_exec;
+       ot->poll = collection_hide_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_show_inside(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Show Inside Collection";
+       ot->idname = "OUTLINER_OT_collection_show_inside";
+       ot->description = "Show all the objects and collections inside the collection";
+
+       /* api callbacks */
+       ot->exec = collection_visibility_exec;
+       ot->poll = collection_inside_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_hide_inside(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Hide Inside Collection";
+       ot->idname = "OUTLINER_OT_collection_hide_inside";
+       ot->description = "Hide all the objects and collections inside the collection";
+
+       /* api callbacks */
+       ot->exec = collection_visibility_exec;
+       ot->poll = collection_inside_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static bool collection_flag_poll(bContext *C, bool clear, int flag)
+{
+       if (!ED_outliner_collections_editor_poll(C)) {
+               return false;
+       }
+
+       TreeElement *te = outliner_active_collection(C);
+       if (te == NULL) {
+               return false;
+       }
+
+       Collection *collection = outliner_collection_from_tree_element(te);
+       if (collection == NULL) {
+               return false;
+       }
+
+       if (clear && (collection->flag & flag)) {
+               return true;
+       }
+       else if (!clear && !(collection->flag & flag)) {
+               return true;
+       }
+
+       return false;
+}
+
+static bool collection_enable_poll(bContext *C)
+{
+       return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW);
+}
+
+static bool collection_disable_poll(bContext *C)
+{
+       return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW);
+}
+
+static bool collection_enable_render_poll(bContext *C)
+{
+       return collection_flag_poll(C, true, COLLECTION_RESTRICT_RENDER);
+}
+
+static bool collection_disable_render_poll(bContext *C)
+{
+       return collection_flag_poll(C, false, COLLECTION_RESTRICT_RENDER);
+}
+
+static int collection_flag_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       SpaceOops *soops = CTX_wm_space_outliner(C);
+       const bool is_render = strstr(op->idname, "render");
+       const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable");
+       int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW;
+       struct CollectionEditData data = {.scene = scene, .soops = soops,};
+       data.collections_to_edit = BLI_gset_ptr_new(__func__);
+       const bool has_layer_collection = soops->outlinevis == SO_VIEW_LAYER;
+
+       if (has_layer_collection) {
+               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 *layer_collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+                       Collection *collection = layer_collection->collection;
+
+                       if (clear) {
+                               collection->flag &= ~flag;
+                       }
+                       else {
+                               collection->flag |= flag;
+                       }
+
+                       /* Make sure (at least for this view layer) the collection is visible. */
+                       if (clear && !is_render) {
+                               layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+                       }
+               }
+               BLI_gset_free(data.collections_to_edit, NULL);
+       }
+       else {
+               outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
+               GSetIterator collections_to_edit_iter;
+               GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+                       Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+                       if (clear) {
+                               collection->flag &= ~flag;
+                       }
+                       else {
+                               collection->flag |= flag;
+                       }
+               }
+               BLI_gset_free(data.collections_to_edit, NULL);
+       }
+
+       BKE_layer_collection_sync(scene, view_layer);
+       DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+       if (!is_render) {
+               DEG_relations_tag_update(CTX_data_main(C));
+       }
+
+       WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+       return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_enable(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Enable Collection";
+       ot->idname = "OUTLINER_OT_collection_enable";
+       ot->description = "Enable viewport drawing in the view layers";
+
+       /* api callbacks */
+       ot->exec = collection_flag_exec;
+       ot->poll = collection_enable_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_disable(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Disable Collection";
+       ot->idname = "OUTLINER_OT_collection_disable";
+       ot->description = "Disable viewport drawing in the view layers";
+
+       /* api callbacks */
+       ot->exec = collection_flag_exec;
+       ot->poll = collection_disable_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_enable_render(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Enable Collection in Render";
+       ot->idname = "OUTLINER_OT_collection_enable_render";
+       ot->description = "Render the collection";
+
+       /* api callbacks */
+       ot->exec = collection_flag_exec;
+       ot->poll = collection_enable_render_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_disable_render(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Disable Collection in Render";
+       ot->idname = "OUTLINER_OT_collection_disable_render";
+       ot->description = "Do not render this collection";
+
+       /* api callbacks */
+       ot->exec = collection_flag_exec;
+       ot->poll = collection_disable_render_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /**
  * Populates the \param objects: ListBase with all the outliner selected objects
  * We store it as (Object *)LinkData->data
index 7a2ac82cf54073b0a25fae84bf85a6c113cbffac..f0befd1df49e53a07f178e6ad7ff7c6d0d989063 100644 (file)
@@ -267,41 +267,72 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
 
 static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        ViewLayer *view_layer = poin;
        Base *base = poin2;
-       bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
-
-       /* Undo button toggle, let function do it. */
-       base->flag ^= BASE_HIDDEN;
-
-       BKE_base_set_visible(scene, view_layer, base, extend);
+       Object *ob = base->object;
+       bool freeze = (CTX_wm_window(C)->eventstate->alt != 0);
+       bool changed_restrict_view = false;
 
-       if (!extend && (base->flag & BASE_VISIBLE)) {
-               /* Auto select solo-ed object. */
-               ED_object_base_select(base, BA_SELECT);
-               view_layer->basact = base;
+       if (freeze) {
+               ob->restrictflag |= OB_RESTRICT_VIEW;
+               changed_restrict_view = true;
+       }
+       else if (ob->restrictflag & OB_RESTRICT_VIEW) {
+               ob->restrictflag &= ~OB_RESTRICT_VIEW;
+               base->flag &= ~BASE_HIDDEN;
+               changed_restrict_view = true;
+       }
+       else {
+               base->flag ^= BASE_HIDDEN;
        }
 
-       DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-       WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+       if (changed_restrict_view) {
+               BKE_main_collection_sync(bmain);
+               DEG_id_tag_update(&ob->id, LIB_TAG_COPIED_ON_WRITE);
+               DEG_relations_tag_update(bmain);
+               WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
+       }
+       if (!freeze) {
+               BKE_layer_collection_sync(scene, view_layer);
+               DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+               WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+       }
 }
 
 static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
 {
+       wmWindow *win = CTX_wm_window(C);
        Scene *scene = CTX_data_scene(C);
        ViewLayer *view_layer = poin;
        LayerCollection *lc = poin2;
-       bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
-
-       /* Undo button toggle, let function do it. */
-       lc->flag ^= LAYER_COLLECTION_RESTRICT_VIEW;
-
-       BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
+       Collection *collection = lc->collection;
+       bool do_disable = (win->eventstate->alt != 0);
+       bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
+       bool extend = (win->eventstate->shift != 0);
+       bool depsgraph_changed = false;
+
+       if (do_disable) {
+               collection->flag |= COLLECTION_RESTRICT_VIEW;
+               depsgraph_changed = true;
+       }
+       else if (do_isolate) {
+               depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+       }
+       else {
+               bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) ||
+                                   ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0);
+               depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend);
+       }
 
-       DEG_relations_tag_update(CTX_data_main(C));
+       BKE_layer_collection_sync(scene, view_layer);
        DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
-       WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+       if (depsgraph_changed) {
+               DEG_relations_tag_update(CTX_data_main(C));
+       }
+       WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
 }
 
 static void namebutton_cb(bContext *C, void *tsep, char *oldname)
@@ -517,27 +548,32 @@ static void outliner_draw_restrictbuts(
                                UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
                        }
                        else if (tselem->type == 0 && te->idcode == ID_OB) {
+                               PointerRNA ptr;
                                Object *ob = (Object *)tselem->id;
+                               RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
                                Base *base = BKE_view_layer_base_find(view_layer, ob);
 
                                if (base) {
-                                       bt = uiDefIconButBitS(
-                                               block, UI_BTYPE_ICON_TOGGLE, BASE_HIDDEN, 0, ICON_HIDE_OFF,
-                                               (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
-                                               UI_UNIT_Y, &base->flag, 0, 0, 0, 0,
-                                               TIP_("Hide object in viewport (Ctrl to isolate)"));
+                                       int icon = ICON_RESTRICT_VIEW_ON;
+                                       if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
+                                               icon = (base->flag & BASE_HIDDEN) != 0 ?
+                                                      ICON_HIDE_ON :
+                                                      ICON_HIDE_OFF;
+                                       }
+                                       bt = uiDefIconBut(
+                                               block, UI_BTYPE_ICON_TOGGLE, 0, icon,
+                                               (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+                                               NULL, 0, 0, 0, 0,
+                                               TIP_("Hide object in viewport (Alt to disable for all viewports)"));
                                        UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
                                        UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-                                       UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
                                }
-
-                               PointerRNA ptr;
-                               RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
-
-                               bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
-                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
-                                                       &ptr, props.object_hide_viewport, -1, 0, 0, -1, -1, NULL);
-                               UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+                               else {
+                                       bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
+                                               (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+                                               &ptr, props.object_hide_viewport, -1, 0, 0, -1, -1, NULL);
+                                       UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+                               }
 
                                bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0,
                                                        (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
@@ -641,23 +677,34 @@ static void outliner_draw_restrictbuts(
                                if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
                                    !(collection->flag & COLLECTION_IS_MASTER))
                                {
-                                       bt = uiDefIconButBitS(
-                                               block, UI_BTYPE_ICON_TOGGLE, LAYER_COLLECTION_RESTRICT_VIEW, 0, ICON_HIDE_OFF,
-                                               (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
-                                               UI_UNIT_Y, &lc->flag, 0, 0, 0, 0,
-                                               TIP_("Hide collection in viewport (Ctrl to isolate)"));
-                                       UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
-                                       UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-                                       UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
                                        PointerRNA collection_ptr;
                                        RNA_id_pointer_create(&collection->id, &collection_ptr);
 
-                                       bt = uiDefIconButR_prop(
-                                               block, UI_BTYPE_ICON_TOGGLE, 0, 0,
-                                               (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
-                                               UI_UNIT_Y, &collection_ptr, props.collection_hide_viewport, -1, 0, 0, 0, 0, NULL);
-                                       UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+                                       if (lc != NULL) {
+                                               int icon = ICON_RESTRICT_VIEW_ON;
+                                               if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) {
+                                                       icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ?
+                                                               ICON_HIDE_ON :
+                                                               ICON_HIDE_OFF;
+                                               }
+                                               bt = uiDefIconBut(
+                                                       block, UI_BTYPE_TOGGLE, 0, icon,
+                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+                                                       NULL, 0, 0, 0, 0,
+                                                       TIP_("Hide collection in viewport\n"
+                                                            "* Alt to disable for all viewports\n"
+                                                            "* Ctrl to isolate visibility\n"
+                                                            "* Shift to hide inside objects and collections"));
+                                               UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
+                                               UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+                                       }
+                                       else {
+                                               bt = uiDefIconButR_prop(
+                                                       block, UI_BTYPE_ICON_TOGGLE, 0, 0,
+                                                       (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+                                                       UI_UNIT_Y, &collection_ptr, props.collection_hide_viewport, -1, 0, 0, 0, 0, NULL);
+                                               UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+                                       }
 
                                        bt = uiDefIconButR_prop(
                                                block, UI_BTYPE_ICON_TOGGLE, 0, 0,
@@ -2115,10 +2162,7 @@ static void outliner_draw_restrictcols(ARegion *ar)
        uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
        immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
        immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
-       immBegin(GPU_PRIM_LINES, 8);
-
-       immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax);
-       immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymin);
+       immBegin(GPU_PRIM_LINES, 6);
 
        immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
        immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
index 96399d3c1290c77d35c3ddb01b04ced03318f638..d978acb60629d7cc95dfece9562086781e49a9dc 100644 (file)
@@ -123,12 +123,11 @@ typedef enum {
 /* size constants */
 #define OL_Y_OFFSET 2
 
-#define OL_TOG_HIDEX            (UI_UNIT_X * 4.0f + V2D_SCROLL_WIDTH)
 #define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
 #define OL_TOG_RESTRICT_VIEWX   (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
 #define OL_TOG_RESTRICT_RENDERX (UI_UNIT_X + V2D_SCROLL_WIDTH)
 
-#define OL_TOGW OL_TOG_HIDEX
+#define OL_TOGW OL_TOG_RESTRICT_SELECTX
 
 #define OL_RNA_COLX         (UI_UNIT_X * 15)
 #define OL_RNA_COL_SIZEX    (UI_UNIT_X * 7.5f)
@@ -329,6 +328,16 @@ void OUTLINER_OT_collection_holdout_clear(struct wmOperatorType *ot);
 void OUTLINER_OT_collection_indirect_only_set(struct wmOperatorType *ot);
 void OUTLINER_OT_collection_indirect_only_clear(struct wmOperatorType *ot);
 
+void OUTLINER_OT_collection_isolate(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_show(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_hide(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_show_inside(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_hide_inside(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_enable(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_disable(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_enable_render(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_disable_render(struct wmOperatorType *ot);
+
 /* outliner_utils.c ---------------------------------------------- */
 
 TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
index d01fa066500c3baabc19be605877f87860fd1bbc..3334206beac029bc99f807376e28bf3e4c5be4db 100644 (file)
@@ -105,6 +105,16 @@ void outliner_operatortypes(void)
        WM_operatortype_append(OUTLINER_OT_collection_holdout_clear);
        WM_operatortype_append(OUTLINER_OT_collection_indirect_only_set);
        WM_operatortype_append(OUTLINER_OT_collection_indirect_only_clear);
+
+       WM_operatortype_append(OUTLINER_OT_collection_isolate);
+       WM_operatortype_append(OUTLINER_OT_collection_disable);
+       WM_operatortype_append(OUTLINER_OT_collection_enable);
+       WM_operatortype_append(OUTLINER_OT_collection_hide);
+       WM_operatortype_append(OUTLINER_OT_collection_show);
+       WM_operatortype_append(OUTLINER_OT_collection_disable_render);
+       WM_operatortype_append(OUTLINER_OT_collection_enable_render);
+       WM_operatortype_append(OUTLINER_OT_collection_hide_inside);
+       WM_operatortype_append(OUTLINER_OT_collection_show_inside);
 }
 
 void outliner_keymap(wmKeyConfig *keyconf)
index 82082ec6022fce2c0a7e639c0fc0746b20512553..0fb48652c2cda9e76f0d2f6c180e7e6db969a737 100644 (file)
@@ -196,7 +196,7 @@ int rna_LayerCollection_name_length(PointerRNA *ptr)
        return strlen(id->name + 2);
 }
 
-static void rna_LayerCollection_use_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
 {
        Scene *scene = (Scene *)ptr->id.data;
        LayerCollection *lc = (LayerCollection *)ptr->data;
@@ -209,6 +209,19 @@ static void rna_LayerCollection_use_update(Main *bmain, Scene *UNUSED(scene), Po
        WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
 }
 
+static void rna_LayerCollection_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       Scene *scene = (Scene *)ptr->id.data;
+       LayerCollection *lc = (LayerCollection *)ptr->data;
+       ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
+
+       BKE_layer_collection_sync(scene, view_layer);
+
+       DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+
+       WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+}
+
 static bool rna_LayerCollection_has_objects(LayerCollection *lc)
 {
        return (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) != 0;
@@ -273,13 +286,13 @@ static void rna_def_layer_collection(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_EXCLUDE);
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer");
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_exclude_update");
 
        prop = RNA_def_property(srna, "holdout", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HOLDOUT);
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_ui_text(prop, "Holdout", "Mask out objects in collection from view layer");
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update");
 
        prop = RNA_def_property(srna, "indirect_only", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_INDIRECT_ONLY);
@@ -287,14 +300,14 @@ static void rna_def_layer_collection(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Indirect Only",
                                 "Objects in collection only contribute indirectly (through shadows and reflections) "
                                 "in the view layer");
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_use_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update");
 
        prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_RESTRICT_VIEW);
        RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
        RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
        RNA_def_property_ui_text(prop, "Disable Viewport", "Disable collection in viewport for this view layer");
-       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_use_update");
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_update");
 
        prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE);