Fix #106943: driver on inactive view layer doesn't work #107031

Manually merged
Sybren A. Stüvel merged 3 commits from dr.sybren/blender:anim/106943-bg-view-layer-driver into main 2023-04-17 13:02:55 +02:00
3 changed files with 38 additions and 33 deletions

View File

@ -75,6 +75,12 @@ void BKE_view_layer_free(struct ViewLayer *view_layer);
*/ */
void BKE_view_layer_free_ex(struct ViewLayer *view_layer, bool do_id_user); void BKE_view_layer_free_ex(struct ViewLayer *view_layer, bool do_id_user);
/**
* Free the bases of this #ViewLayer, and what they reference.
* This includes baseact, object_bases, object_bases_hash, and layer_collections.
*/
void BKE_view_layer_free_object_content(struct ViewLayer *view_layer);
/** /**
* Tag all the selected objects of a render-layer. * Tag all the selected objects of a render-layer.
*/ */

View File

@ -246,19 +246,7 @@ void BKE_view_layer_free(ViewLayer *view_layer)
void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
{ {
view_layer->basact = nullptr; BKE_view_layer_free_object_content(view_layer);
BLI_freelistN(&view_layer->object_bases);
if (view_layer->object_bases_hash) {
BLI_ghash_free(view_layer->object_bases_hash, nullptr, nullptr);
}
LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, &view_layer->layer_collections) {
layer_collection_free(view_layer, lc);
MEM_freeN(lc);
}
BLI_listbase_clear(&view_layer->layer_collections);
LISTBASE_FOREACH (ViewLayerEngineData *, sled, &view_layer->drawdata) { LISTBASE_FOREACH (ViewLayerEngineData *, sled, &view_layer->drawdata) {
if (sled->storage) { if (sled->storage) {
@ -287,6 +275,23 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
MEM_freeN(view_layer); MEM_freeN(view_layer);
} }
void BKE_view_layer_free_object_content(ViewLayer *view_layer)
{
view_layer->basact = nullptr;
BLI_freelistN(&view_layer->object_bases);
if (view_layer->object_bases_hash) {
BLI_ghash_free(view_layer->object_bases_hash, nullptr, nullptr);
}
LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, &view_layer->layer_collections) {
layer_collection_free(view_layer, lc);
MEM_freeN(lc);
}
BLI_listbase_clear(&view_layer->layer_collections);
}
void BKE_view_layer_selected_objects_tag(const Scene *scene, ViewLayer *view_layer, const int tag) void BKE_view_layer_selected_objects_tag(const Scene *scene, ViewLayer *view_layer, const int tag)
{ {
BKE_view_layer_synced_ensure(scene, view_layer); BKE_view_layer_synced_ensure(scene, view_layer);

View File

@ -353,12 +353,11 @@ ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_
return nullptr; return nullptr;
} }
/* Remove all view layers but the one which corresponds to an input one. */ /* Remove all bases from all view layers except the input one. */
void scene_remove_unused_view_layers(const Depsgraph *depsgraph, void scene_minimize_unused_view_layers(const Depsgraph *depsgraph,
const IDNode *id_node, const IDNode *id_node,
Scene *scene_cow) Scene *scene_cow)
{ {
const ViewLayer *view_layer_input;
if (depsgraph->is_render_pipeline_depsgraph) { if (depsgraph->is_render_pipeline_depsgraph) {
/* If the dependency graph is used for post-processing (such as compositor) we do need to /* If the dependency graph is used for post-processing (such as compositor) we do need to
* have access to its view layer names so can not remove any view layers. * have access to its view layer names so can not remove any view layers.
@ -370,18 +369,12 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
* NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of
* render layer node possibly pointing to another scene. */ * render layer node possibly pointing to another scene. */
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) { LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
view_layer->basact = nullptr; BKE_view_layer_free_object_content(view_layer);
} }
return; return;
} }
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
/* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled const ViewLayer *view_layer_input = get_original_view_layer(depsgraph, id_node);
* via some driver. Such scenes should not have view layers after copy. */
view_layer_input = nullptr;
}
else {
view_layer_input = get_original_view_layer(depsgraph, id_node);
}
ViewLayer *view_layer_eval = nullptr; ViewLayer *view_layer_eval = nullptr;
/* Find evaluated view layer. At the same time we free memory used by /* Find evaluated view layer. At the same time we free memory used by
* all other of the view layers. */ * all other of the view layers. */
@ -394,15 +387,16 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
view_layer_eval = view_layer_cow; view_layer_eval = view_layer_cow;
} }
else { else {
BKE_view_layer_free_ex(view_layer_cow, false); BKE_view_layer_free_object_content(view_layer_cow);
} }
} }
/* Make evaluated view layer the only one in the evaluated scene (if it exists). */
/* Make evaluated view layer the first one in the evaluated scene (if it exists). This is for
* legacy sake, as this used to remove all other view layers, automatically making the evaluated
* one the first. Some other code may still assume it is. */
if (view_layer_eval != nullptr) { if (view_layer_eval != nullptr) {
view_layer_eval->prev = view_layer_eval->next = nullptr; BLI_listbase_swaplinks(&scene_cow->view_layers, scene_cow->view_layers.first, view_layer_eval);
} }
scene_cow->view_layers.first = view_layer_eval;
scene_cow->view_layers.last = view_layer_eval;
} }
void scene_remove_all_bases(Scene *scene_cow) void scene_remove_all_bases(Scene *scene_cow)
@ -467,7 +461,7 @@ void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
const IDNode *id_node, const IDNode *id_node,
Scene *scene_cow) Scene *scene_cow)
{ {
scene_remove_unused_view_layers(depsgraph, id_node, scene_cow); scene_minimize_unused_view_layers(depsgraph, id_node, scene_cow);
/* If dependency graph is used for post-processing we don't need any bases and can free of them. /* If dependency graph is used for post-processing we don't need any bases and can free of them.
* Do it before re-mapping to make that process faster. */ * Do it before re-mapping to make that process faster. */
if (depsgraph->is_render_pipeline_depsgraph) { if (depsgraph->is_render_pipeline_depsgraph) {