Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/layer.c
| Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
| #include "DRW_engine.h" | #include "DRW_engine.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf | #define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf | ||||
| /* prototype */ | /* prototype */ | ||||
| struct EngineSettingsCB_Type; | struct EngineSettingsCB_Type; | ||||
| static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc); | static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc, const Main *bmain); | ||||
| static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects); | static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects); | ||||
| static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc); | static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc); | ||||
| static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc); | static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc); | ||||
| static IDProperty *collection_engine_settings_create(struct EngineSettingsCB_Type *ces_type, const bool populate); | static IDProperty *collection_engine_settings_create(struct EngineSettingsCB_Type *ces_type, const bool populate); | ||||
| static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name); | static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name); | ||||
| static void collection_engine_settings_init(IDProperty *root, const bool populate); | static void collection_engine_settings_init(IDProperty *root, const bool populate); | ||||
| static void layer_engine_settings_init(IDProperty *root, const bool populate); | static void layer_engine_settings_init(IDProperty *root, const bool populate); | ||||
| static void object_bases_iterator_next(BLI_Iterator *iter, const int flag); | static void object_bases_iterator_next(BLI_Iterator *iter, const int flag); | ||||
| ▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
| ViewLayer *BKE_view_layer_group_add(Group *group) | ViewLayer *BKE_view_layer_group_add(Group *group) | ||||
| { | { | ||||
| BLI_assert(group->view_layer == NULL); | BLI_assert(group->view_layer == NULL); | ||||
| SceneCollection *sc = BKE_collection_master(&group->id); | SceneCollection *sc = BKE_collection_master(&group->id); | ||||
| ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc); | ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc); | ||||
| return view_layer; | return view_layer; | ||||
| } | } | ||||
| void BKE_view_layer_free(ViewLayer *view_layer) | void BKE_view_layer_free(ViewLayer *view_layer, const Main *bmain) | ||||
| { | { | ||||
| BKE_view_layer_free_ex(view_layer, true); | BKE_view_layer_free_ex(view_layer, bmain, true); | ||||
| } | } | ||||
| /** | /** | ||||
| * Free (or release) any data used by this ViewLayer. | * Free (or release) any data used by this ViewLayer. | ||||
| */ | */ | ||||
| void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) | void BKE_view_layer_free_ex(ViewLayer *view_layer, const Main *bmain, const bool do_id_user) | ||||
| { | { | ||||
| view_layer->basact = NULL; | view_layer->basact = NULL; | ||||
| BKE_workspace_active_base_changed(NULL, view_layer); | |||||
| for (Base *base = view_layer->object_bases.first; base; base = base->next) { | for (Base *base = view_layer->object_bases.first; base; base = base->next) { | ||||
| if (base->collection_properties) { | if (base->collection_properties) { | ||||
| IDP_FreeProperty(base->collection_properties); | IDP_FreeProperty(base->collection_properties); | ||||
| MEM_freeN(base->collection_properties); | MEM_freeN(base->collection_properties); | ||||
| } | } | ||||
| } | } | ||||
| BLI_freelistN(&view_layer->object_bases); | BLI_freelistN(&view_layer->object_bases); | ||||
| for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | ||||
| layer_collection_free(NULL, lc); | layer_collection_free(NULL, lc, bmain); | ||||
| } | } | ||||
| BLI_freelistN(&view_layer->layer_collections); | BLI_freelistN(&view_layer->layer_collections); | ||||
| if (view_layer->properties) { | if (view_layer->properties) { | ||||
| IDP_FreeProperty(view_layer->properties); | IDP_FreeProperty(view_layer->properties); | ||||
| MEM_freeN(view_layer->properties); | MEM_freeN(view_layer->properties); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| Base *base; | Base *base; | ||||
| for (base = view_layer->object_bases.first; base; base = base->next) { | for (base = view_layer->object_bases.first; base; base = base->next) { | ||||
| base->flag &= ~BASE_SELECTED; | base->flag &= ~BASE_SELECTED; | ||||
| } | } | ||||
| } | } | ||||
| void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase) | void BKE_view_layer_base_select(ViewLayer *view_layer, Base *selbase, WorkSpace *workspace) | ||||
| { | { | ||||
| view_layer->basact = selbase; | view_layer->basact = selbase; | ||||
| if ((selbase->flag & BASE_SELECTABLED) != 0) { | if ((selbase->flag & BASE_SELECTABLED) != 0) { | ||||
| selbase->flag |= BASE_SELECTED; | selbase->flag |= BASE_SELECTED; | ||||
| } | } | ||||
| BKE_workspace_active_base_changed(workspace, view_layer); | |||||
| } | } | ||||
| /****************************************************************************/ | /****************************************************************************/ | ||||
| /* Copying functions for datablocks that use ViewLayer/SceneCollection */ | /* Copying functions for datablocks that use ViewLayer/SceneCollection */ | ||||
| /* Find the equivalent SceneCollection in the new tree */ | /* Find the equivalent SceneCollection in the new tree */ | ||||
| static SceneCollection *scene_collection_from_new_tree( | static SceneCollection *scene_collection_from_new_tree( | ||||
| SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src) | SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src) | ||||
| ▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first; | ||||
| base_src; | base_src; | ||||
| base_src = base_src->next, base_dst = base_dst->next) | base_src = base_src->next, base_dst = base_dst->next) | ||||
| { | { | ||||
| base_dst->flag = base_src->flag; | base_dst->flag = base_src->flag; | ||||
| base_dst->flag_legacy = base_src->flag_legacy; | base_dst->flag_legacy = base_src->flag_legacy; | ||||
| if (base_dst->object == active_ob) { | if (base_dst->object == active_ob) { | ||||
| view_layer_dst->basact = base_dst; | view_layer_dst->basact = base_dst; | ||||
| /* XXX */ | |||||
| // BKE_workspace_active_base_changed(bmain, view_layer_dst); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base) | static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base, const Main *UNUSED(bmain)) | ||||
| { | { | ||||
| base->refcount--; | base->refcount--; | ||||
| /* It only exists in the RenderLayer */ | /* It only exists in the RenderLayer */ | ||||
| if (base->refcount == 0) { | if (base->refcount == 0) { | ||||
| if (view_layer->basact == base) { | if (view_layer->basact == base) { | ||||
| view_layer->basact = NULL; | view_layer->basact = NULL; | ||||
| BKE_workspace_active_base_changed(NULL, view_layer); | |||||
| } | } | ||||
| if (base->collection_properties) { | if (base->collection_properties) { | ||||
| IDP_FreeProperty(base->collection_properties); | IDP_FreeProperty(base->collection_properties); | ||||
| MEM_freeN(base->collection_properties); | MEM_freeN(base->collection_properties); | ||||
| } | } | ||||
| BLI_remlink(&view_layer->object_bases, base); | BLI_remlink(&view_layer->object_bases, base); | ||||
| Show All 22 Lines | static Base *object_base_add(ViewLayer *view_layer, Object *ob) | ||||
| } | } | ||||
| base->refcount++; | base->refcount++; | ||||
| return base; | return base; | ||||
| } | } | ||||
| /* LayerCollection */ | /* LayerCollection */ | ||||
| static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc) | static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc, const Main *bmain) | ||||
| { | { | ||||
| if (view_layer) { | if (view_layer) { | ||||
| for (LinkData *link = lc->object_bases.first; link; link = link->next) { | for (LinkData *link = lc->object_bases.first; link; link = link->next) { | ||||
| view_layer_object_base_unref(view_layer, link->data); | view_layer_object_base_unref(view_layer, link->data, bmain); | ||||
| } | } | ||||
| } | } | ||||
| BLI_freelistN(&lc->object_bases); | BLI_freelistN(&lc->object_bases); | ||||
| } | } | ||||
| /** | /** | ||||
| * When freeing the entire ViewLayer at once we don't bother with unref | * When freeing the entire ViewLayer at once we don't bother with unref | ||||
| * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree | * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree | ||||
| */ | */ | ||||
| static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc) | static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc, const Main *bmain) | ||||
| { | { | ||||
| layer_collection_objects_unpopulate(view_layer, lc); | layer_collection_objects_unpopulate(view_layer, lc, bmain); | ||||
| BLI_freelistN(&lc->overrides); | BLI_freelistN(&lc->overrides); | ||||
| if (lc->properties) { | if (lc->properties) { | ||||
| IDP_FreeProperty(lc->properties); | IDP_FreeProperty(lc->properties); | ||||
| MEM_freeN(lc->properties); | MEM_freeN(lc->properties); | ||||
| } | } | ||||
| if (lc->properties_evaluated) { | if (lc->properties_evaluated) { | ||||
| IDP_FreeProperty(lc->properties_evaluated); | IDP_FreeProperty(lc->properties_evaluated); | ||||
| MEM_freeN(lc->properties_evaluated); | MEM_freeN(lc->properties_evaluated); | ||||
| } | } | ||||
| for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { | for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { | ||||
| layer_collection_free(view_layer, nlc); | layer_collection_free(view_layer, nlc, bmain); | ||||
| } | } | ||||
| BLI_freelistN(&lc->layer_collections); | BLI_freelistN(&lc->layer_collections); | ||||
| } | } | ||||
| /** | /** | ||||
| * Free (or release) LayerCollection from ViewLayer | * Free (or release) LayerCollection from ViewLayer | ||||
| * (does not free the LayerCollection itself). | * (does not free the LayerCollection itself). | ||||
| */ | */ | ||||
| void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc) | void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc, const Main *bmain) | ||||
| { | { | ||||
| layer_collection_free(view_layer, lc); | layer_collection_free(view_layer, lc, bmain); | ||||
| } | } | ||||
| /* LayerCollection */ | /* LayerCollection */ | ||||
| /** | /** | ||||
| * Recursively get the collection for a given index | * Recursively get the collection for a given index | ||||
| */ | */ | ||||
| static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i) | static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i) | ||||
| ▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | static void layer_collection_swap( | ||||
| BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b); | BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b); | ||||
| } | } | ||||
| /** | /** | ||||
| * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer. | * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer. | ||||
| * If \a lc_src is directly linked to the ViewLayer it's unlinked | * If \a lc_src is directly linked to the ViewLayer it's unlinked | ||||
| */ | */ | ||||
| bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) | bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src, const Main *bmain) | ||||
| { | { | ||||
| ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ||||
| bool is_directly_linked = false; | bool is_directly_linked = false; | ||||
| if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| Show All 9 Lines | bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src, const Main *bmain) | ||||
| /* Collection is already where we want it to be in the scene tree | /* Collection is already where we want it to be in the scene tree | ||||
| * but we want to swap it in the layer tree still */ | * but we want to swap it in the layer tree still */ | ||||
| if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) { | if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) { | ||||
| LayerCollection *lc_swap = lc_dst->layer_collections.last; | LayerCollection *lc_swap = lc_dst->layer_collections.last; | ||||
| layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src); | layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src); | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_swap); | BKE_collection_unlink(view_layer, lc_swap, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| else { | else { | ||||
| LayerCollection *lc_temp; | LayerCollection *lc_temp; | ||||
| is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | ||||
| if (!is_directly_linked) { | if (!is_directly_linked) { | ||||
| /* lc_src will be invalid after BKE_collection_move_into! | /* lc_src will be invalid after BKE_collection_move_into! | ||||
| * so we swap it with lc_temp to preserve its settings */ | * so we swap it with lc_temp to preserve its settings */ | ||||
| lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | ||||
| layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | ||||
| } | } | ||||
| if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { | if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection, bmain)) { | ||||
| if (!is_directly_linked) { | if (!is_directly_linked) { | ||||
| /* Swap back and remove */ | /* Swap back and remove */ | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | ||||
| BKE_collection_unlink(view_layer, lc_temp); | BKE_collection_unlink(view_layer, lc_temp, bmain); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| LayerCollection *lc_new = BLI_findptr( | LayerCollection *lc_new = BLI_findptr( | ||||
| &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection)); | &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection)); | ||||
| BLI_assert(lc_new); | BLI_assert(lc_new); | ||||
| layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src); | layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src); | ||||
| /* If it's directly linked, unlink it after the swap */ | /* If it's directly linked, unlink it after the swap */ | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_new); | BKE_collection_unlink(view_layer, lc_new, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** | /** | ||||
| * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer. | * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer. | ||||
| * If \a lc_src is directly linked to the ViewLayer it's unlinked | * If \a lc_src is directly linked to the ViewLayer it's unlinked | ||||
| */ | */ | ||||
| bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) | bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src, const Main *bmain) | ||||
| { | { | ||||
| ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ||||
| const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | ||||
| const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; | const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; | ||||
| if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Collection is already where we wanted it to be */ | /* Collection is already where we wanted it to be */ | ||||
| if (lc_dst->prev == lc_src) { | if (lc_dst->prev == lc_src) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Collection is already where we want it to be in the scene tree | /* Collection is already where we want it to be in the scene tree | ||||
| * but we want to swap it in the layer tree still */ | * but we want to swap it in the layer tree still */ | ||||
| if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) { | if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) { | ||||
| LayerCollection *lc_swap = lc_dst->prev; | LayerCollection *lc_swap = lc_dst->prev; | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src); | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_swap); | BKE_collection_unlink(view_layer, lc_swap, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* We don't allow to move above/below a directly linked collection | /* We don't allow to move above/below a directly linked collection | ||||
| * unless the source collection is also directly linked */ | * unless the source collection is also directly linked */ | ||||
| else if (is_directly_linked_dst) { | else if (is_directly_linked_dst) { | ||||
| /* Both directly linked to the ViewLayer, just need to swap */ | /* Both directly linked to the ViewLayer, just need to swap */ | ||||
| if (is_directly_linked_src) { | if (is_directly_linked_src) { | ||||
| Show All 10 Lines | else { | ||||
| if (!is_directly_linked_src) { | if (!is_directly_linked_src) { | ||||
| /* lc_src will be invalid after BKE_collection_move_into! | /* lc_src will be invalid after BKE_collection_move_into! | ||||
| * so we swap it with lc_temp to preserve its settings */ | * so we swap it with lc_temp to preserve its settings */ | ||||
| lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | ||||
| layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | ||||
| } | } | ||||
| if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { | if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection, bmain)) { | ||||
| if (!is_directly_linked_src) { | if (!is_directly_linked_src) { | ||||
| /* Swap back and remove */ | /* Swap back and remove */ | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | ||||
| BKE_collection_unlink(view_layer, lc_temp); | BKE_collection_unlink(view_layer, lc_temp, bmain); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| LayerCollection *lc_new = lc_dst->prev; | LayerCollection *lc_new = lc_dst->prev; | ||||
| BLI_assert(lc_new); | BLI_assert(lc_new); | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); | ||||
| /* If it's directly linked, unlink it after the swap */ | /* If it's directly linked, unlink it after the swap */ | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_new); | BKE_collection_unlink(view_layer, lc_new, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** | /** | ||||
| * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer. | * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer. | ||||
| * If \a lc_src is directly linked to the ViewLayer it's unlinked | * If \a lc_src is directly linked to the ViewLayer it's unlinked | ||||
| */ | */ | ||||
| bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) | bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src, const Main *bmain) | ||||
| { | { | ||||
| ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); | ||||
| const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; | ||||
| const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; | const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; | ||||
| if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Collection is already where we wanted it to be */ | /* Collection is already where we wanted it to be */ | ||||
| if (lc_dst->next == lc_src) { | if (lc_dst->next == lc_src) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Collection is already where we want it to be in the scene tree | /* Collection is already where we want it to be in the scene tree | ||||
| * but we want to swap it in the layer tree still */ | * but we want to swap it in the layer tree still */ | ||||
| if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) { | if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) { | ||||
| LayerCollection *lc_swap = lc_dst->next; | LayerCollection *lc_swap = lc_dst->next; | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src); | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_swap); | BKE_collection_unlink(view_layer, lc_swap, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* We don't allow to move above/below a directly linked collection | /* We don't allow to move above/below a directly linked collection | ||||
| * unless the source collection is also directly linked */ | * unless the source collection is also directly linked */ | ||||
| else if (is_directly_linked_dst) { | else if (is_directly_linked_dst) { | ||||
| /* Both directly linked to the ViewLayer, just need to swap */ | /* Both directly linked to the ViewLayer, just need to swap */ | ||||
| if (is_directly_linked_src) { | if (is_directly_linked_src) { | ||||
| Show All 10 Lines | else { | ||||
| if (!is_directly_linked_src) { | if (!is_directly_linked_src) { | ||||
| /* lc_src will be invalid after BKE_collection_move_into! | /* lc_src will be invalid after BKE_collection_move_into! | ||||
| * so we swap it with lc_temp to preserve its settings */ | * so we swap it with lc_temp to preserve its settings */ | ||||
| lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); | ||||
| layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); | ||||
| } | } | ||||
| if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { | if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection, bmain)) { | ||||
| if (!is_directly_linked_src) { | if (!is_directly_linked_src) { | ||||
| /* Swap back and remove */ | /* Swap back and remove */ | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); | ||||
| BKE_collection_unlink(view_layer, lc_temp); | BKE_collection_unlink(view_layer, lc_temp, bmain); | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| LayerCollection *lc_new = lc_dst->next; | LayerCollection *lc_new = lc_dst->next; | ||||
| BLI_assert(lc_new); | BLI_assert(lc_new); | ||||
| layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); | layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); | ||||
| /* If it's directly linked, unlink it after the swap */ | /* If it's directly linked, unlink it after the swap */ | ||||
| if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { | ||||
| BKE_collection_unlink(view_layer, lc_new); | BKE_collection_unlink(view_layer, lc_new, bmain); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc) | static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc, const Main *bmain) | ||||
| { | { | ||||
| if (lc->scene_collection == sc) { | if (lc->scene_collection == sc) { | ||||
| ListBase collections = {NULL}; | ListBase collections = {NULL}; | ||||
| BLI_movelisttolist(&collections, &lc->layer_collections); | BLI_movelisttolist(&collections, &lc->layer_collections); | ||||
| for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) { | for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) { | ||||
| LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection)); | LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection)); | ||||
| if (lc_nested) { | if (lc_nested) { | ||||
| BLI_remlink(&collections, lc_nested); | BLI_remlink(&collections, lc_nested); | ||||
| BLI_addtail(&lc->layer_collections, lc_nested); | BLI_addtail(&lc->layer_collections, lc_nested); | ||||
| } | } | ||||
| else { | else { | ||||
| layer_collection_add(view_layer, lc, sc_nested); | layer_collection_add(view_layer, lc, sc_nested); | ||||
| } | } | ||||
| } | } | ||||
| for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) { | for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) { | ||||
| layer_collection_free(view_layer, lc_nested); | layer_collection_free(view_layer, lc_nested, bmain); | ||||
| } | } | ||||
| BLI_freelistN(&collections); | BLI_freelistN(&collections); | ||||
| BLI_assert(BLI_listbase_count(&lc->layer_collections) == | BLI_assert(BLI_listbase_count(&lc->layer_collections) == | ||||
| BLI_listbase_count(&sc->scene_collections)); | BLI_listbase_count(&sc->scene_collections)); | ||||
| return true; | return true; | ||||
| } | } | ||||
| for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) { | for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) { | ||||
| if (layer_collection_resync(view_layer, lc_nested, sc)) { | if (layer_collection_resync(view_layer, lc_nested, sc, bmain)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /** | /** | ||||
| * Update the scene layers so that any LayerCollection that points | * Update the scene layers so that any LayerCollection that points | ||||
| * to \a sc is re-synced again | * to \a sc is re-synced again | ||||
| */ | */ | ||||
| void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc) | void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc, const Main *bmain) | ||||
| { | { | ||||
| for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { | for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { | ||||
| for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | ||||
| layer_collection_resync(view_layer, lc, sc); | layer_collection_resync(view_layer, lc, sc, bmain); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** | /** | ||||
| * Link a collection to a renderlayer | * Link a collection to a renderlayer | ||||
| * The collection needs to be created separately | * The collection needs to be created separately | ||||
| */ | */ | ||||
| LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc) | LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc) | ||||
| { | { | ||||
| LayerCollection *lc = layer_collection_add(view_layer, NULL, sc); | LayerCollection *lc = layer_collection_add(view_layer, NULL, sc); | ||||
| view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc); | view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc); | ||||
| return lc; | return lc; | ||||
| } | } | ||||
| /** | /** | ||||
| * Unlink a collection base from a renderlayer | * Unlink a collection base from a renderlayer | ||||
| * The corresponding collection is not removed from the master collection | * The corresponding collection is not removed from the master collection | ||||
| */ | */ | ||||
| void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc) | void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc, const Main *bmain) | ||||
| { | { | ||||
| BKE_layer_collection_free(view_layer, lc); | BKE_layer_collection_free(view_layer, lc, bmain); | ||||
| BLI_remlink(&view_layer->layer_collections, lc); | BLI_remlink(&view_layer->layer_collections, lc); | ||||
| MEM_freeN(lc); | MEM_freeN(lc); | ||||
| view_layer->active_collection = 0; | view_layer->active_collection = 0; | ||||
| } | } | ||||
| /** | /** | ||||
| * Recursively enable nested collections | * Recursively enable nested collections | ||||
| */ | */ | ||||
| Show All 40 Lines | static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *lc, Object *ob) | ||||
| if (is_selectable) { | if (is_selectable) { | ||||
| base->flag |= BASE_SELECTABLED; | base->flag |= BASE_SELECTABLED; | ||||
| } | } | ||||
| BLI_addtail(&lc->object_bases, BLI_genericNodeN(base)); | BLI_addtail(&lc->object_bases, BLI_genericNodeN(base)); | ||||
| } | } | ||||
| static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob) | static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob, const Main *bmain) | ||||
| { | { | ||||
| Base *base; | Base *base; | ||||
| base = BKE_view_layer_base_find(view_layer, ob); | base = BKE_view_layer_base_find(view_layer, ob); | ||||
| LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)); | LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)); | ||||
| BLI_remlink(&lc->object_bases, link); | BLI_remlink(&lc->object_bases, link); | ||||
| MEM_freeN(link); | MEM_freeN(link); | ||||
| view_layer_object_base_unref(view_layer, base); | view_layer_object_base_unref(view_layer, base, bmain); | ||||
| } | } | ||||
| static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects) | static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects) | ||||
| { | { | ||||
| for (LinkData *link = objects->first; link; link = link->next) { | for (LinkData *link = objects->first; link; link = link->next) { | ||||
| layer_collection_object_add(view_layer, lc, link->data); | layer_collection_object_add(view_layer, lc, link->data); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Remove the equivalent object base to all layers that have this collection | * Remove the equivalent object base to all layers that have this collection | ||||
| */ | */ | ||||
| void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob) | void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob, const Main *bmain) | ||||
| { | { | ||||
| for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { | for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { | ||||
| for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { | ||||
| LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); | LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); | ||||
| if (found) { | if (found) { | ||||
| layer_collection_object_remove(view_layer, found, ob); | layer_collection_object_remove(view_layer, found, ob, bmain); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /* Override */ | /* Override */ | ||||
| ▲ Show 20 Lines • Show All 984 Lines • Show Last 20 Lines | |||||