diff options
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r-- | source/blender/editors/space_view3d/view3d_view.c | 136 |
1 files changed, 134 insertions, 2 deletions
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2515ee6e482..e5e1b1297f6 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -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); + } +} + +/** \} */ |