Per-Viewport Collection Visibility
Support per-viewport collection visibility options. Note 1: There is no way to show a collection that was not visible before due to depsgraph. Otherwise we would risk having all the collections in the depsgraph and I believe this is not the idea. An alternative would be to have a new depsgraph for viewports that are not local. Something to keep in mind if we do per-viewport current frame in the future. So for now what we do is to only allow collections visibility to be disabled/hidden in this mode. Note 2: hide_viewport (the eye icon) doesn't really matter for depsgraph. So after the merge we can still ignore it to show the collections locally in a viewport with no problems for the depsgraph. Reviewers: brecht, sergey Subscribers: billreynish Related task: T61327 Differential Revision: https://developer.blender.org/D5611
This commit is contained in:
parent
ce34a6b0d7
commit
92736a7b75
Notes:
blender-bot
2023-02-14 03:48:06 +01:00
Referenced by issue #97069, Crash deleting a scene after moving object between collections (from a collection that is hidden in the Outliner, but visible in a viewport) Referenced by issue #69859, Crash when switching the 3D View to Rendered with EEVEE. Referenced by issue #61327, Per-Viewport Collection Visibility
|
@ -4997,7 +4997,7 @@ class VIEW3D_PT_collections(Panel):
|
|||
bl_label = "Collections"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def _draw_collection(self, layout, view_layer, collection, index):
|
||||
def _draw_collection(self, layout, view_layer, use_local_collections, collection, index):
|
||||
need_separator = index
|
||||
for child in collection.children:
|
||||
index += 1
|
||||
|
@ -5023,6 +5023,7 @@ class VIEW3D_PT_collections(Panel):
|
|||
pass
|
||||
|
||||
row = layout.row()
|
||||
row.use_property_decorate = False
|
||||
sub = row.split(factor=0.98)
|
||||
subrow = sub.row()
|
||||
subrow.alignment = 'LEFT'
|
||||
|
@ -5033,11 +5034,21 @@ class VIEW3D_PT_collections(Panel):
|
|||
sub = row.split()
|
||||
subrow = sub.row(align=True)
|
||||
subrow.alignment = 'RIGHT'
|
||||
subrow.active = collection.is_visible # Parent collection runtime visibility
|
||||
subrow.prop(child, "hide_viewport", text="", emboss=False)
|
||||
if not use_local_collections:
|
||||
subrow.active = collection.is_visible # Parent collection runtime visibility
|
||||
subrow.prop(child, "hide_viewport", text="", emboss=False)
|
||||
elif not child.is_visible:
|
||||
subrow.active = False
|
||||
subrow.label(text="", icon='REMOVE')
|
||||
else:
|
||||
subrow.active = collection.visible_get() # Parent collection runtime visibility
|
||||
icon = 'HIDE_OFF' if child.visible_get() else 'HIDE_ON'
|
||||
props = subrow.operator("object.hide_collection", text="", icon=icon, emboss=False)
|
||||
props.collection_index = index
|
||||
props.toggle = True
|
||||
|
||||
for child in collection.children:
|
||||
index = self._draw_collection(layout, view_layer, child, index)
|
||||
index = self._draw_collection(layout, view_layer, use_local_collections, child, index)
|
||||
|
||||
return index
|
||||
|
||||
|
@ -5045,11 +5056,17 @@ class VIEW3D_PT_collections(Panel):
|
|||
layout = self.layout
|
||||
layout.use_property_split = False
|
||||
|
||||
view = context.space_data
|
||||
view_layer = context.view_layer
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.prop(view, "use_local_collections")
|
||||
layout.separator()
|
||||
|
||||
# We pass index 0 here because the index is increased
|
||||
# so the first real index is 1
|
||||
# And we start with index as 1 because we skip the master collection
|
||||
self._draw_collection(layout, view_layer, view_layer.layer_collection, 0)
|
||||
self._draw_collection(layout, view_layer, view.use_local_collections, view_layer.layer_collection, 0)
|
||||
|
||||
|
||||
class VIEW3D_PT_object_type_visibility(Panel):
|
||||
|
|
|
@ -90,6 +90,7 @@ int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct La
|
|||
void BKE_main_collection_sync(const struct Main *bmain);
|
||||
void BKE_scene_collection_sync(const struct Scene *scene);
|
||||
void BKE_layer_collection_sync(const struct Scene *scene, struct ViewLayer *view_layer);
|
||||
void BKE_layer_collection_local_sync(struct ViewLayer *view_layer, struct View3D *v3d);
|
||||
|
||||
void BKE_main_collection_sync_remap(const struct Main *bmain);
|
||||
|
||||
|
@ -117,6 +118,10 @@ void BKE_layer_collection_isolate(struct Scene *scene,
|
|||
struct ViewLayer *view_layer,
|
||||
struct LayerCollection *lc,
|
||||
bool extend);
|
||||
void BKE_layer_collection_local_isolate(struct ViewLayer *view_layer,
|
||||
struct View3D *v3d,
|
||||
struct LayerCollection *lc,
|
||||
bool extend);
|
||||
void BKE_layer_collection_set_visible(struct ViewLayer *view_layer,
|
||||
struct LayerCollection *lc,
|
||||
const bool visible,
|
||||
|
|
|
@ -68,6 +68,7 @@ static LayerCollection *layer_collection_add(ListBase *lb_parent, Collection *co
|
|||
{
|
||||
LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
|
||||
lc->collection = collection;
|
||||
lc->local_collections_bits = ~(0);
|
||||
BLI_addtail(lb_parent, lc);
|
||||
|
||||
return lc;
|
||||
|
@ -1083,6 +1084,117 @@ void BKE_layer_collection_isolate(Scene *scene,
|
|||
BKE_layer_collection_sync(scene, view_layer);
|
||||
}
|
||||
|
||||
static void layer_collection_local_visibility_set_recursive(LayerCollection *layer_collection,
|
||||
const int local_collections_uuid)
|
||||
{
|
||||
layer_collection->local_collections_bits |= local_collections_uuid;
|
||||
for (LayerCollection *child = layer_collection->layer_collections.first; child;
|
||||
child = child->next) {
|
||||
layer_collection_local_visibility_set_recursive(child, local_collections_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
static void layer_collection_local_visibility_unset_recursive(LayerCollection *layer_collection,
|
||||
const int local_collections_uuid)
|
||||
{
|
||||
layer_collection->local_collections_bits &= ~local_collections_uuid;
|
||||
for (LayerCollection *child = layer_collection->layer_collections.first; child;
|
||||
child = child->next) {
|
||||
layer_collection_local_visibility_unset_recursive(child, local_collections_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
static void layer_collection_local_sync(ViewLayer *view_layer,
|
||||
LayerCollection *layer_collection,
|
||||
const unsigned short local_collections_uuid,
|
||||
bool visible)
|
||||
{
|
||||
if ((layer_collection->local_collections_bits & local_collections_uuid) == 0) {
|
||||
visible = false;
|
||||
}
|
||||
|
||||
if (visible) {
|
||||
for (CollectionObject *cob = layer_collection->collection->gobject.first; cob;
|
||||
cob = cob->next) {
|
||||
BLI_assert(cob->ob);
|
||||
Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
|
||||
base->local_collections_bits |= local_collections_uuid;
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
|
||||
layer_collection_local_sync(view_layer, child, local_collections_uuid, visible);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_layer_collection_local_sync(ViewLayer *view_layer, View3D *v3d)
|
||||
{
|
||||
const unsigned short local_collections_uuid = v3d->local_collections_uuid;
|
||||
|
||||
/* Reset flags and set the bases visible by default. */
|
||||
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
|
||||
base->local_collections_bits &= ~local_collections_uuid;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
|
||||
layer_collection_local_sync(view_layer, layer_collection, local_collections_uuid, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Isolate the collection locally
|
||||
*
|
||||
* Same as BKE_layer_collection_local_isolate but for a viewport
|
||||
*/
|
||||
void BKE_layer_collection_local_isolate(ViewLayer *view_layer,
|
||||
View3D *v3d,
|
||||
LayerCollection *lc,
|
||||
bool extend)
|
||||
{
|
||||
LayerCollection *lc_master = view_layer->layer_collections.first;
|
||||
bool hide_it = extend && ((v3d->local_collections_uuid & lc->local_collections_bits) != 0);
|
||||
|
||||
if (!extend) {
|
||||
/* Hide all collections. */
|
||||
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
|
||||
lc_iter = lc_iter->next) {
|
||||
layer_collection_local_visibility_unset_recursive(lc_iter, v3d->local_collections_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make all the direct parents visible. */
|
||||
if (hide_it) {
|
||||
lc->local_collections_bits &= ~(v3d->local_collections_uuid);
|
||||
}
|
||||
else {
|
||||
LayerCollection *lc_parent = lc;
|
||||
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) {
|
||||
lc_parent->local_collections_bits |= v3d->local_collections_uuid;
|
||||
|
||||
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_local_visibility_set_recursive(lc, v3d->local_collections_uuid);
|
||||
}
|
||||
|
||||
BKE_layer_collection_local_sync(view_layer, v3d);
|
||||
}
|
||||
|
||||
static void layer_collection_bases_show_recursive(ViewLayer *view_layer, LayerCollection *lc)
|
||||
{
|
||||
if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
|
||||
|
|
|
@ -453,6 +453,7 @@ void BKE_object_eval_eval_base_flags(Depsgraph *depsgraph,
|
|||
object->base_flag &= ~(BASE_SELECTED | BASE_SELECTABLE);
|
||||
}
|
||||
object->base_local_view_bits = base->local_view_bits;
|
||||
object->runtime.local_collections_bits = base->local_collections_bits;
|
||||
|
||||
if (object->mode == OB_MODE_PARTICLE_EDIT) {
|
||||
for (ParticleSystem *psys = object->particlesystem.first; psys != NULL; psys = psys->next) {
|
||||
|
|
|
@ -849,6 +849,14 @@ static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, cha
|
|||
}
|
||||
}
|
||||
|
||||
static void do_versions_local_collection_bits_set(LayerCollection *layer_collection)
|
||||
{
|
||||
layer_collection->local_collections_bits = ~(0);
|
||||
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
|
||||
do_versions_local_collection_bits_set(child);
|
||||
}
|
||||
}
|
||||
|
||||
void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
|
||||
{
|
||||
bool use_collection_compat_28 = true;
|
||||
|
@ -2919,7 +2927,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
case SPACE_VIEW3D: {
|
||||
View3D *v3d = (View3D *)sl;
|
||||
v3d->flag &= ~(V3D_FLAG_UNUSED_0 | V3D_FLAG_UNUSED_1 | V3D_FLAG_UNUSED_10 |
|
||||
v3d->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_FLAG_UNUSED_1 | V3D_FLAG_UNUSED_10 |
|
||||
V3D_FLAG_UNUSED_12);
|
||||
v3d->flag2 &= ~(V3D_FLAG2_UNUSED_3 | V3D_FLAG2_UNUSED_6 | V3D_FLAG2_UNUSED_12 |
|
||||
V3D_FLAG2_UNUSED_13 | V3D_FLAG2_UNUSED_14 | V3D_FLAG2_UNUSED_15);
|
||||
|
@ -3854,5 +3862,16 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
|
||||
{
|
||||
/* Versioning code until next subversion bump goes here. */
|
||||
|
||||
if (!DNA_struct_elem_find(
|
||||
fd->filesdna, "LayerCollection", "short", "local_collections_bits")) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
|
||||
LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
|
||||
do_versions_local_collection_bits_set(layer_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1565,6 +1565,20 @@ void DRW_draw_view(const bContext *C)
|
|||
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
|
||||
}
|
||||
|
||||
static bool is_object_visible_in_viewport(View3D *v3d, Object *ob)
|
||||
{
|
||||
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((v3d->flag & V3D_LOCAL_COLLECTIONS) &&
|
||||
((v3d->local_collections_uuid & ob->runtime.local_collections_bits) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for both regular and off-screen drawing.
|
||||
* Need to reset DST before calling this function
|
||||
|
@ -1640,7 +1654,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
|
|||
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
||||
if (!is_object_visible_in_viewport(v3d, ob)) {
|
||||
continue;
|
||||
}
|
||||
DST.dupli_parent = data_.dupli_parent;
|
||||
|
@ -2336,10 +2350,9 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|||
v3d->object_type_exclude_select);
|
||||
bool filter_exclude = false;
|
||||
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
||||
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
||||
if (!is_object_visible_in_viewport(v3d, ob)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ob->base_flag & BASE_SELECTABLE) &&
|
||||
(object_type_exclude_select & (1 << ob->type)) == 0) {
|
||||
if (object_filter_fn != NULL) {
|
||||
|
@ -2458,11 +2471,9 @@ static void drw_draw_depth_loop_imp(void)
|
|||
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
||||
if (!is_object_visible_in_viewport(v3d, ob)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DST.dupli_parent = data_.dupli_parent;
|
||||
DST.dupli_source = data_.dupli_object_current;
|
||||
drw_duplidata_load(DST.dupli_source);
|
||||
|
|
|
@ -741,4 +741,8 @@ void ED_view3d_buttons_region_layout_ex(const struct bContext *C,
|
|||
struct ARegion *ar,
|
||||
const char *category_override);
|
||||
|
||||
/* view3d_view.c */
|
||||
bool ED_view3d_local_collections_set(struct Main *bmain, struct View3D *v3d);
|
||||
void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all);
|
||||
|
||||
#endif /* __ED_VIEW3D_H__ */
|
||||
|
|
|
@ -271,9 +271,11 @@ void OBJECT_OT_hide_view_set(wmOperatorType *ot)
|
|||
static int object_hide_collection_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
int index = RNA_int_get(op->ptr, "collection_index");
|
||||
const bool extend = (win->eventstate->shift != 0) || RNA_boolean_get(op->ptr, "toggle");
|
||||
const bool extend = (win->eventstate->shift != 0);
|
||||
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
||||
|
||||
if (win->eventstate->alt != 0) {
|
||||
index += 10;
|
||||
|
@ -289,7 +291,21 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op)
|
|||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
|
||||
|
||||
BKE_layer_collection_isolate(scene, view_layer, lc, extend);
|
||||
if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
|
||||
if ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (toggle) {
|
||||
lc->local_collections_bits ^= v3d->local_collections_uuid;
|
||||
BKE_layer_collection_local_sync(view_layer, v3d);
|
||||
}
|
||||
else {
|
||||
BKE_layer_collection_local_isolate(view_layer, v3d, lc, extend);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_layer_collection_isolate(scene, view_layer, lc, extend);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -1187,7 +1188,7 @@ finally:
|
|||
/** \name Local View Operators
|
||||
* \{ */
|
||||
|
||||
static uint free_localbit(Main *bmain)
|
||||
static uint free_localview_bit(Main *bmain)
|
||||
{
|
||||
ScrArea *sa;
|
||||
bScreen *sc;
|
||||
|
@ -1242,7 +1243,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
|
|||
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
local_view_bit = free_localbit(bmain);
|
||||
local_view_bit = free_localview_bit(bmain);
|
||||
|
||||
if (local_view_bit == 0) {
|
||||
/* TODO(dfelinto): We can kick one of the other 3D views out of local view
|
||||
|
@ -1534,3 +1535,134 @@ void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Local Collections
|
||||
* \{ */
|
||||
|
||||
static uint free_localcollection_bit(Main *bmain,
|
||||
unsigned short local_collections_uuid,
|
||||
bool *reset)
|
||||
{
|
||||
ScrArea *sa;
|
||||
bScreen *sc;
|
||||
|
||||
ushort local_view_bits = 0;
|
||||
|
||||
/* Check all areas: which localviews are in use? */
|
||||
for (sc = bmain->screens.first; sc; sc = sc->id.next) {
|
||||
for (sa = sc->areabase.first; sa; sa = sa->next) {
|
||||
SpaceLink *sl = sa->spacedata.first;
|
||||
for (; sl; sl = sl->next) {
|
||||
if (sl->spacetype == SPACE_VIEW3D) {
|
||||
View3D *v3d = (View3D *)sl;
|
||||
if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
|
||||
local_view_bits |= v3d->local_collections_uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* First try to keep the old uuid. */
|
||||
if (local_collections_uuid && ((local_collections_uuid & local_view_bits) == 0)) {
|
||||
return local_collections_uuid;
|
||||
}
|
||||
|
||||
/* Otherwise get the first free available. */
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((local_view_bits & (1 << i)) == 0) {
|
||||
*reset = true;
|
||||
return (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void local_collections_reset_uuid(LayerCollection *layer_collection,
|
||||
const unsigned short local_view_bit)
|
||||
{
|
||||
layer_collection->local_collections_bits |= local_view_bit;
|
||||
LISTBASE_FOREACH (LayerCollection *, child, &layer_collection->layer_collections) {
|
||||
local_collections_reset_uuid(child, local_view_bit);
|
||||
}
|
||||
}
|
||||
|
||||
static void view3d_local_collections_reset(Main *bmain, const uint local_view_bit)
|
||||
{
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
|
||||
LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
|
||||
local_collections_reset_uuid(layer_collection, local_view_bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See if current uuid is valid, otherwise set a valid uuid to v3d,
|
||||
* Try to keep the same uuid previously used to allow users to
|
||||
* quickly toggle back and forth.
|
||||
*/
|
||||
bool ED_view3d_local_collections_set(Main *bmain, struct View3D *v3d)
|
||||
{
|
||||
if ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reset = false;
|
||||
v3d->flag &= ~V3D_LOCAL_COLLECTIONS;
|
||||
uint local_view_bit = free_localcollection_bit(bmain, v3d->local_collections_uuid, &reset);
|
||||
|
||||
if (local_view_bit == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
v3d->local_collections_uuid = local_view_bit;
|
||||
v3d->flag |= V3D_LOCAL_COLLECTIONS;
|
||||
|
||||
if (reset) {
|
||||
view3d_local_collections_reset(bmain, local_view_bit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
uint local_view_bit = ~(0);
|
||||
bool do_reset = false;
|
||||
|
||||
/* Reset only the ones that are not in use. */
|
||||
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
|
||||
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
|
||||
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
|
||||
if (sl->spacetype == SPACE_VIEW3D) {
|
||||
View3D *v3d = (View3D *)sl;
|
||||
if (v3d->local_collections_uuid) {
|
||||
if (v3d->flag & V3D_LOCAL_COLLECTIONS) {
|
||||
local_view_bit &= ~v3d->local_collections_uuid;
|
||||
}
|
||||
else {
|
||||
do_reset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_reset) {
|
||||
view3d_local_collections_reset(bmain, local_view_bit);
|
||||
}
|
||||
else if (reset_all && (do_reset || (local_view_bit != ~(0)))) {
|
||||
view3d_local_collections_reset(bmain, ~(0));
|
||||
View3D v3d = {.local_collections_uuid = ~(0)};
|
||||
BKE_layer_collection_local_sync(CTX_data_view_layer(C), &v3d);
|
||||
DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -45,6 +45,8 @@ typedef struct Base {
|
|||
struct Object *object;
|
||||
unsigned int lay DNA_DEPRECATED;
|
||||
int flag_legacy;
|
||||
unsigned short local_collections_bits;
|
||||
short _pad2[3];
|
||||
|
||||
/* Pointer to an original base. Is initialized for evaluated view layer.
|
||||
* NOTE: Only allowed to be accessed from within active dependency graph. */
|
||||
|
@ -66,8 +68,12 @@ typedef struct LayerCollection {
|
|||
short flag;
|
||||
short runtime_flag;
|
||||
char _pad[4];
|
||||
|
||||
/** Synced with collection->children. */
|
||||
ListBase layer_collections;
|
||||
|
||||
unsigned short local_collections_bits;
|
||||
short _pad2[3];
|
||||
} LayerCollection;
|
||||
|
||||
typedef struct ViewLayer {
|
||||
|
|
|
@ -183,7 +183,8 @@ typedef struct Object_Runtime {
|
|||
/** Runtime grease pencil evaluated data created by modifiers */
|
||||
struct bGPDframe *gpencil_evaluated_frames;
|
||||
|
||||
void *_pad2; /* Padding is here for win32s unconventional struct alignment rules. */
|
||||
unsigned short local_collections_bits;
|
||||
short _pad2[3];
|
||||
} Object_Runtime;
|
||||
|
||||
typedef struct Object {
|
||||
|
|
|
@ -1979,6 +1979,8 @@ extern const char *RE_engine_id_CYCLES;
|
|||
#define BASE_VISIBLE(v3d, base) \
|
||||
(((v3d == NULL) || ((v3d)->localvd == NULL) || \
|
||||
((v3d)->local_view_uuid & (base)->local_view_bits)) && \
|
||||
((v3d == NULL) || (((v3d)->flag & V3D_LOCAL_COLLECTIONS) == 0) || \
|
||||
((v3d)->local_collections_uuid & (base)->local_collections_bits)) && \
|
||||
((v3d == NULL) || \
|
||||
(((1 << (base)->object->type) & (v3d)->object_type_exclude_viewport) == 0)) && \
|
||||
(((base)->flag & BASE_VISIBLE) != 0))
|
||||
|
|
|
@ -266,6 +266,8 @@ typedef struct View3D {
|
|||
unsigned short local_view_uuid;
|
||||
char _pad6[2];
|
||||
int layact DNA_DEPRECATED;
|
||||
unsigned short local_collections_uuid;
|
||||
short _pad7[3];
|
||||
|
||||
/** Optional bool for 3d cursor to define center. */
|
||||
short ob_centre_cursor;
|
||||
|
@ -329,7 +331,7 @@ typedef struct View3D {
|
|||
#define V3D_S3D_DISPVOLUME (1 << 2)
|
||||
|
||||
/** #View3D.flag */
|
||||
#define V3D_FLAG_UNUSED_0 (1 << 0) /* cleared */
|
||||
#define V3D_LOCAL_COLLECTIONS (1 << 0)
|
||||
#define V3D_FLAG_UNUSED_1 (1 << 1) /* cleared */
|
||||
#define V3D_HIDE_HELPLINES (1 << 2)
|
||||
#define V3D_INVALID_BACKBUF (1 << 3)
|
||||
|
|
|
@ -120,6 +120,26 @@ static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create)
|
|||
return view_layer->id_properties;
|
||||
}
|
||||
|
||||
static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, bContext *C)
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
const bool runtime_visible = (layer_collection->runtime_flag & LAYER_COLLECTION_VISIBLE) != 0;
|
||||
|
||||
if (v3d == NULL) {
|
||||
return runtime_visible;
|
||||
}
|
||||
|
||||
if ((v3d->flag & V3D_LOCAL_COLLECTIONS) == 0) {
|
||||
return runtime_visible;
|
||||
}
|
||||
|
||||
if (v3d->local_collections_uuid & layer_collection->local_collections_bits) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rna_ViewLayer_update_render_passes(ID *id)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
|
@ -386,6 +406,13 @@ static void rna_def_layer_collection(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_update");
|
||||
|
||||
func = RNA_def_function(srna, "visible_get", "rna_LayerCollection_visible_get");
|
||||
RNA_def_function_ui_description(func,
|
||||
"Whether this collection is visible, take into account the "
|
||||
"collection parent and the viewport");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
RNA_def_function_return(func, RNA_def_boolean(func, "result", 0, "", ""));
|
||||
|
||||
/* Run-time flags. */
|
||||
prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE);
|
||||
|
|
|
@ -1218,6 +1218,19 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(bContext *UN
|
|||
return item;
|
||||
}
|
||||
|
||||
static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = (View3D *)ptr->data;
|
||||
|
||||
if (ED_view3d_local_collections_set(bmain, v3d)) {
|
||||
BKE_layer_collection_local_sync(view_layer, v3d);
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *C,
|
||||
PointerRNA *UNUSED(ptr),
|
||||
PropertyRNA *UNUSED(prop),
|
||||
|
@ -3951,6 +3964,14 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_local_collections", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_LOCAL_COLLECTIONS);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Local Collections", "Display a different set of collections in this viewport");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_use_local_collections_update");
|
||||
|
||||
/* Stereo Settings */
|
||||
prop = RNA_def_property(srna, "stereo_3d_eye", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "multiview_eye");
|
||||
|
|
|
@ -2245,6 +2245,7 @@ static int wm_open_mainfile__open(bContext *C, wmOperator *op)
|
|||
if (G.fileflags & G_FILE_NO_UI) {
|
||||
ED_outliner_select_sync_from_all_tag(C);
|
||||
}
|
||||
ED_view3d_local_collections_reset(C, (G.fileflags & G_FILE_NO_UI) != 0);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Reference in New Issue