forked from bartvdbraak/blender
Outliner visibility unification: Implement 3 levels of viewport visibility
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.
This commit is contained in:
parent
e3f7f0c3eb
commit
897e047374
@ -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,
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
void BKE_layer_collection_set_visible(Scene *scene, ViewLayer *view_layer, LayerCollection *lc, bool extend)
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make all the children visible. */
|
||||
layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
|
||||
|
||||
BKE_layer_collection_activate(view_layer, lc);
|
||||
}
|
||||
else {
|
||||
lc->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);
|
||||
|
||||
BKE_layer_collection_activate(view_layer, lc);
|
||||
|
||||
BKE_layer_collection_sync(scene, view_layer);
|
||||
|
||||
return depsgraph_need_update;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
for (LayerCollection *lc_iter = lc->layer_collections.first; lc_iter; lc_iter = lc_iter->next) {
|
||||
layer_collection_bases_hide_recursive(view_layer, lc_iter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
Object *ob = base->object;
|
||||
bool freeze = (CTX_wm_window(C)->eventstate->alt != 0);
|
||||
bool changed_restrict_view = false;
|
||||
|
||||
/* Undo button toggle, let function do it. */
|
||||
base->flag ^= BASE_HIDDEN;
|
||||
|
||||
BKE_base_set_visible(scene, view_layer, base, extend);
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
/* Undo button toggle, let function do it. */
|
||||
lc->flag ^= LAYER_COLLECTION_RESTRICT_VIEW;
|
||||
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);
|
||||
}
|
||||
|
||||
BKE_layer_collection_set_visible(scene, view_layer, lc, 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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user