Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/lib_override.c
| Show First 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user) | ||||
| BKE_lib_override_library_clear(*override, do_id_user); | BKE_lib_override_library_clear(*override, do_id_user); | ||||
| MEM_freeN(*override); | MEM_freeN(*override); | ||||
| *override = NULL; | *override = NULL; | ||||
| } | } | ||||
| static ID *lib_override_library_create_from(Main *bmain, ID *reference_id) | static ID *lib_override_library_create_from(Main *bmain, ID *reference_id) | ||||
| { | { | ||||
| ID *local_id = BKE_id_copy(bmain, reference_id); | /* Note: We do not want to copy possible override data from reference here (whether it is an | ||||
| * override template, or already an override of some other ref data). */ | |||||
| ID *local_id = BKE_id_copy_ex( | |||||
| bmain, reference_id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE); | |||||
| if (local_id == NULL) { | if (local_id == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| id_us_min(local_id); | id_us_min(local_id); | ||||
| BKE_lib_override_library_init(local_id, reference_id); | BKE_lib_override_library_init(local_id, reference_id); | ||||
| /* Note: From liboverride perspective (and RNA one), shape keys are considered as local embedded | /* Note: From liboverride perspective (and RNA one), shape keys are considered as local embedded | ||||
| * data-blocks, just like root node trees or master collections. Therefore, we never need to | * data-blocks, just like root node trees or master collections. Therefore, we never need to | ||||
| * create overrides for them. We need a way to mark them as overrides though. */ | * create overrides for them. We need a way to mark them as overrides though. */ | ||||
| Key *reference_key; | Key *reference_key; | ||||
| if ((reference_key = BKE_key_from_id(reference_id)) != NULL) { | if ((reference_key = BKE_key_from_id(reference_id)) != NULL) { | ||||
| Key *local_key = BKE_key_from_id(local_id); | Key *local_key = BKE_key_from_id(local_id); | ||||
| BLI_assert(local_key != NULL); | BLI_assert(local_key != NULL); | ||||
| local_key->id.flag |= LIB_EMBEDDED_DATA_LIB_OVERRIDE; | local_key->id.flag |= LIB_EMBEDDED_DATA_LIB_OVERRIDE; | ||||
| } | } | ||||
| return local_id; | return local_id; | ||||
| } | } | ||||
| /** Check if given ID has some override rules that actually indicate the user edited it. | /** | ||||
| * Check if given ID has some override rules that actually indicate the user edited it. | |||||
| * | * | ||||
| * TODO: This could be simplified by storing a flag in IDOverrideLibrary during the diffing | * TODO: This could be simplified by storing a flag in #IDOverrideLibrary during the diffing | ||||
| * process? */ | * process? | ||||
| */ | |||||
| bool BKE_lib_override_library_is_user_edited(struct ID *id) | bool BKE_lib_override_library_is_user_edited(struct ID *id) | ||||
| { | { | ||||
| if (!ID_IS_OVERRIDE_LIBRARY(id)) { | if (!ID_IS_OVERRIDE_LIBRARY(id)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) { | LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) { | ||||
| LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { | LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { | ||||
| ▲ Show 20 Lines • Show All 412 Lines • ▼ Show 20 Lines | static bool lib_override_library_create_do(Main *bmain, ID *id_root) | ||||
| BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | ||||
| lib_override_hierarchy_dependencies_recursive_tag(&data); | lib_override_hierarchy_dependencies_recursive_tag(&data); | ||||
| BKE_main_relations_free(bmain); | BKE_main_relations_free(bmain); | ||||
| return BKE_lib_override_library_create_from_tag(bmain); | return BKE_lib_override_library_create_from_tag(bmain); | ||||
| } | } | ||||
| BLI_INLINE bool lib_override_library_create_post_process_object_is_instantiated( | |||||
| ViewLayer *view_layer, Object *object, const bool is_resync) | |||||
| { | |||||
| /* We cannot rely on check for object being actually instantiated in resync case, because often | |||||
| * the overridden collection is 'excluded' from the current view-layer. | |||||
| * | |||||
| * Fallback to a basic user-count check then, this is weak (since it could lead to some object | |||||
| * not being instantiated at all), but it should work fine in most common cases. */ | |||||
| return ((is_resync && ID_REAL_USERS(object) >= 1) || | |||||
| (!is_resync && BKE_view_layer_base_find(view_layer, object) != NULL)); | |||||
| } | |||||
| static void lib_override_library_create_post_process(Main *bmain, | static void lib_override_library_create_post_process(Main *bmain, | ||||
| Scene *scene, | Scene *scene, | ||||
| ViewLayer *view_layer, | ViewLayer *view_layer, | ||||
| ID *id_root, | ID *id_root, | ||||
| ID *id_reference, | ID *id_reference, | ||||
| Collection *residual_storage, | Collection *residual_storage, | ||||
| const bool is_resync) | const bool is_resync) | ||||
| { | { | ||||
| BKE_main_collection_sync(bmain); | BKE_main_collection_sync(bmain); | ||||
| if (id_root->newid != NULL) { | /* We create a set of all objects referenced into the scene by its hierarchy of collections. | ||||
| * NOTE: This is different that the list of bases, since objects in excluded collections etc. | |||||
| * won't have a base, but are still considered as instanced from our point of view. */ | |||||
| GSet *all_objects_in_scene = BKE_scene_objects_as_gset(scene, NULL); | |||||
| /* Instantiating the root collection or object should never be needed in resync case, since the | |||||
| * old override would be remapped to the new one. */ | |||||
| if (!is_resync && id_root != NULL && id_root->newid != NULL) { | |||||
| switch (GS(id_root->name)) { | switch (GS(id_root->name)) { | ||||
| case ID_GR: { | case ID_GR: { | ||||
| Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? | Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? | ||||
| (Object *)id_reference : | (Object *)id_reference : | ||||
| NULL; | NULL; | ||||
| Collection *collection_new = ((Collection *)id_root->newid); | Collection *collection_new = ((Collection *)id_root->newid); | ||||
| if (is_resync && BKE_collection_is_in_scene(collection_new)) { | |||||
| break; | |||||
| } | |||||
| if (ob_reference != NULL) { | if (ob_reference != NULL) { | ||||
| BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); | BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); | ||||
| } | } | ||||
| else if (id_reference != NULL) { | else if (id_reference != NULL) { | ||||
| BLI_assert(GS(id_reference->name) == ID_GR); | BLI_assert(GS(id_reference->name) == ID_GR); | ||||
| BKE_collection_add_from_collection( | BKE_collection_add_from_collection( | ||||
| bmain, scene, ((Collection *)id_reference), collection_new); | bmain, scene, ((Collection *)id_reference), collection_new); | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_collection_add_from_collection( | BKE_collection_add_from_collection( | ||||
| bmain, scene, ((Collection *)id_root), collection_new); | bmain, scene, ((Collection *)id_root), collection_new); | ||||
| } | } | ||||
| FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { | BLI_assert(BKE_collection_is_in_scene(collection_new)); | ||||
| if (ob_new != NULL && ob_new->id.override_library != NULL) { | |||||
| if (ob_reference != NULL) { | all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene); | ||||
| Base *base = BKE_view_layer_base_find(view_layer, ob_new); | |||||
| if (!lib_override_library_create_post_process_object_is_instantiated( | |||||
| view_layer, ob_new, is_resync)) { | |||||
| BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new); | |||||
| base = BKE_view_layer_base_find(view_layer, ob_new); | |||||
| DEG_id_tag_update_ex( | |||||
| bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); | |||||
| } | |||||
| if (ob_new == (Object *)ob_reference->id.newid && base != NULL) { | |||||
| /* TODO: is setting active needed? */ | |||||
| BKE_view_layer_base_select_and_set_active(view_layer, base); | |||||
| } | |||||
| } | |||||
| else if (!lib_override_library_create_post_process_object_is_instantiated( | |||||
| view_layer, ob_new, is_resync)) { | |||||
| BKE_collection_object_add(bmain, collection_new, ob_new); | |||||
| DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); | |||||
| } | |||||
| } | |||||
| } | |||||
| FOREACH_COLLECTION_OBJECT_RECURSIVE_END; | |||||
| break; | break; | ||||
| } | } | ||||
| case ID_OB: { | case ID_OB: { | ||||
| Object *ob_new = (Object *)id_root->newid; | Object *ob_new = (Object *)id_root->newid; | ||||
| if (!lib_override_library_create_post_process_object_is_instantiated( | if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) { | ||||
| view_layer, ob_new, is_resync)) { | |||||
| if (is_resync && residual_storage != NULL) { | |||||
| BKE_collection_object_add(bmain, residual_storage, ob_new); | |||||
| } | |||||
| else { | |||||
| BKE_collection_object_add_from(bmain, scene, (Object *)id_root, ob_new); | BKE_collection_object_add_from(bmain, scene, (Object *)id_root, ob_new); | ||||
| } | all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| /* We need to ensure all new overrides of objects are properly instantiated. */ | /* We need to ensure all new overrides of objects are properly instantiated. */ | ||||
| Collection *default_instantiating_collection = residual_storage; | |||||
| LISTBASE_FOREACH (Object *, ob, &bmain->objects) { | LISTBASE_FOREACH (Object *, ob, &bmain->objects) { | ||||
| Object *ob_new = (Object *)ob->id.newid; | Object *ob_new = (Object *)ob->id.newid; | ||||
| if (ob_new != NULL) { | if (ob_new != NULL) { | ||||
| BLI_assert(ob_new->id.override_library != NULL && | BLI_assert(ob_new->id.override_library != NULL && | ||||
| ob_new->id.override_library->reference == &ob->id); | ob_new->id.override_library->reference == &ob->id); | ||||
| Collection *default_instantiating_collection = residual_storage; | if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) { | ||||
| if (!lib_override_library_create_post_process_object_is_instantiated( | if (id_root != NULL && default_instantiating_collection == NULL) { | ||||
| view_layer, ob_new, is_resync)) { | |||||
| if (default_instantiating_collection == NULL) { | |||||
| switch (GS(id_root->name)) { | switch (GS(id_root->name)) { | ||||
| case ID_GR: { | case ID_GR: { | ||||
| default_instantiating_collection = BKE_collection_add( | default_instantiating_collection = BKE_collection_add( | ||||
| bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); | bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); | ||||
| /* Hide the collection from viewport and render. */ | /* Hide the collection from viewport and render. */ | ||||
| default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | | default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | | ||||
| COLLECTION_RESTRICT_RENDER; | COLLECTION_RESTRICT_RENDER; | ||||
| break; | break; | ||||
| } | } | ||||
| case ID_OB: { | case ID_OB: { | ||||
| /* Add the other objects to one of the collections instantiating the | /* Add the other objects to one of the collections instantiating the | ||||
| * root object, or scene's master collection if none found. */ | * root object, or scene's master collection if none found. */ | ||||
| Object *ob_root = (Object *)id_root; | Object *ob_root = (Object *)id_root; | ||||
| LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { | LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { | ||||
| if (BKE_collection_has_object(collection, ob_root) && | if (BKE_collection_has_object(collection, ob_root) && | ||||
| BKE_view_layer_has_collection(view_layer, collection) && | BKE_view_layer_has_collection(view_layer, collection) && | ||||
| !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) { | !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) { | ||||
| default_instantiating_collection = collection; | default_instantiating_collection = collection; | ||||
| } | } | ||||
| } | } | ||||
| if (default_instantiating_collection == NULL) { | |||||
| default_instantiating_collection = scene->master_collection; | |||||
| } | |||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| } | } | ||||
| } | } | ||||
| if (default_instantiating_collection == NULL) { | |||||
| default_instantiating_collection = scene->master_collection; | |||||
| } | |||||
| BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); | BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); | ||||
| DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); | DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_gset_free(all_objects_in_scene, NULL); | |||||
| } | } | ||||
| /** | /** | ||||
| * Advanced 'smart' function to create fully functional overrides. | * Advanced 'smart' function to create fully functional overrides. | ||||
| * | * | ||||
| * \note Currently it only does special things if given \a id_root is an object of collection, more | * \note Currently it only does special things if given \a id_root is an object of collection, more | ||||
| * specific behaviors may be added in the future for other ID types. | * specific behaviors may be added in the future for other ID types. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | |||||
| * \param id_root: The root liboverride ID to resync from. | * \param id_root: The root liboverride ID to resync from. | ||||
| * \return true if override was successfully resynced. | * \return true if override was successfully resynced. | ||||
| */ | */ | ||||
| bool BKE_lib_override_library_resync(Main *bmain, | bool BKE_lib_override_library_resync(Main *bmain, | ||||
| Scene *scene, | Scene *scene, | ||||
| ViewLayer *view_layer, | ViewLayer *view_layer, | ||||
| ID *id_root, | ID *id_root, | ||||
| Collection *override_resync_residual_storage, | Collection *override_resync_residual_storage, | ||||
| const bool do_hierarchy_enforce) | const bool do_hierarchy_enforce, | ||||
| const bool do_post_process) | |||||
| { | { | ||||
| BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); | BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); | ||||
| BLI_assert(!ID_IS_LINKED(id_root)); | BLI_assert(!ID_IS_LINKED(id_root)); | ||||
| ID *id_root_reference = id_root->override_library->reference; | ID *id_root_reference = id_root->override_library->reference; | ||||
| BKE_main_relations_create(bmain, 0); | BKE_main_relations_create(bmain, 0); | ||||
| LibOverrideGroupTagData data = { | LibOverrideGroupTagData data = { | ||||
| .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; | .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; | ||||
| lib_override_local_group_tag(&data); | lib_override_local_group_tag(&data); | ||||
| BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | ||||
| data.id_root = id_root_reference; | data.id_root = id_root_reference; | ||||
| lib_override_linked_group_tag(&data); | lib_override_linked_group_tag(&data); | ||||
| BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | ||||
| lib_override_hierarchy_dependencies_recursive_tag(&data); | lib_override_hierarchy_dependencies_recursive_tag(&data); | ||||
| /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides. */ | /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides. */ | ||||
| GHash *linkedref_to_old_override = BLI_ghash_new( | GHash *linkedref_to_old_override = BLI_ghash_new( | ||||
| BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); | BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); | ||||
| ID *id; | ID *id; | ||||
| FOREACH_MAIN_ID_BEGIN (bmain, id) { | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| if (id->tag & LIB_TAG_DOIT && ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | if (id->tag & LIB_TAG_DOIT && !ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | ||||
| /* While this should not happen in typical cases (and won't be properly supported here), user | /* While this should not happen in typical cases (and won't be properly supported here), user | ||||
| * is free to do all kind of very bad things, including having different local overrides of a | * is free to do all kind of very bad things, including having different local overrides of a | ||||
| * same linked ID in a same hierarchy. */ | * same linked ID in a same hierarchy. */ | ||||
| if (!BLI_ghash_haskey(linkedref_to_old_override, id->override_library->reference)) { | if (!BLI_ghash_haskey(linkedref_to_old_override, id->override_library->reference)) { | ||||
| BLI_ghash_insert(linkedref_to_old_override, id->override_library->reference, id); | BLI_ghash_insert(linkedref_to_old_override, id->override_library->reference, id); | ||||
| if ((id->override_library->reference->tag & LIB_TAG_DOIT) == 0) { | if ((id->override_library->reference->tag & LIB_TAG_DOIT) == 0) { | ||||
| /* We have an override, but now it does not seem to be necessary to override that ID | /* We have an override, but now it does not seem to be necessary to override that ID | ||||
| * anymore. Check if there are some actual overrides from the user, otherwise assume | * anymore. Check if there are some actual overrides from the user, otherwise assume | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | else if (id->tag & LIB_TAG_MISSING && !ID_IS_LINKED(id)) { | ||||
| id->tag |= LIB_TAG_DOIT; | id->tag |= LIB_TAG_DOIT; | ||||
| id->tag &= ~LIB_TAG_MISSING; | id->tag &= ~LIB_TAG_MISSING; | ||||
| CLOG_INFO(&LOG, 2, "Old override %s is being deleted", id->name); | CLOG_INFO(&LOG, 2, "Old override %s is being deleted", id->name); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Otherwise, keep them, user needs to decide whether what to do with them. */ | /* Otherwise, keep them, user needs to decide whether what to do with them. */ | ||||
| BLI_assert((id->tag & LIB_TAG_DOIT) == 0); | BLI_assert((id->tag & LIB_TAG_DOIT) == 0); | ||||
| id_fake_user_set(id); | id_fake_user_set(id); | ||||
| id->flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER; | |||||
| CLOG_INFO(&LOG, 2, "Old override %s is being kept around as it was user-edited", id->name); | CLOG_INFO(&LOG, 2, "Old override %s is being kept around as it was user-edited", id->name); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| FOREACH_MAIN_ID_END; | FOREACH_MAIN_ID_END; | ||||
| BKE_id_multi_tagged_delete(bmain); | BKE_id_multi_tagged_delete(bmain); | ||||
| /* At this point, `id_root` has very likely been deleted, we need to update it to its new | /* At this point, `id_root` has very likely been deleted, we need to update it to its new | ||||
| * version. | * version. | ||||
| */ | */ | ||||
| id_root = id_root_reference->newid; | id_root = id_root_reference->newid; | ||||
| if (do_post_process) { | |||||
| /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ | /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ | ||||
| /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine | /* Note: Here 'reference' collection and 'newly added' collection are the same, which is fine | ||||
| * since we already relinked old root override collection to new resync'ed one above. So this | * since we already relinked old root override collection to new resync'ed one above. So this | ||||
| * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure | * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure | ||||
| * that we do not have any stray objects. */ | * that we do not have any stray objects. */ | ||||
| lib_override_library_create_post_process(bmain, | lib_override_library_create_post_process(bmain, | ||||
| scene, | scene, | ||||
| view_layer, | view_layer, | ||||
| id_root_reference, | id_root_reference, | ||||
| id_root, | id_root, | ||||
| override_resync_residual_storage, | override_resync_residual_storage, | ||||
| true); | true); | ||||
| } | |||||
| /* Cleanup. */ | /* Cleanup. */ | ||||
| BLI_ghash_free(linkedref_to_old_override, NULL, NULL); | BLI_ghash_free(linkedref_to_old_override, NULL, NULL); | ||||
| BKE_main_id_clear_newpoins(bmain); | BKE_main_id_clear_newpoins(bmain); | ||||
| BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); /* That one should not be needed in fact. */ | BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); /* That one should not be needed in fact. */ | ||||
| return success; | return success; | ||||
| ▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) { | ||||
| if ((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0) { | if ((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); | BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id)); | ||||
| if (ID_IS_LINKED(id)) { | if (ID_IS_LINKED(id)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| do_continue = true; | do_continue = true; | ||||
| CLOG_INFO(&LOG, 2, "Resyncing %s...", id->name); | CLOG_INFO(&LOG, 2, "Resyncing %s...", id->name); | ||||
| const bool success = BKE_lib_override_library_resync( | const bool success = BKE_lib_override_library_resync( | ||||
| bmain, scene, view_layer, id, override_resync_residual_storage, false); | bmain, scene, view_layer, id, override_resync_residual_storage, false, false); | ||||
| CLOG_INFO(&LOG, 2, "\tSuccess: %d", success); | CLOG_INFO(&LOG, 2, "\tSuccess: %d", success); | ||||
| break; | break; | ||||
| } | } | ||||
| FOREACH_MAIN_LISTBASE_ID_END; | FOREACH_MAIN_LISTBASE_ID_END; | ||||
| if (do_continue) { | if (do_continue) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| FOREACH_MAIN_LISTBASE_END; | FOREACH_MAIN_LISTBASE_END; | ||||
| } | } | ||||
| /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ | |||||
| lib_override_library_create_post_process( | |||||
| bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true); | |||||
| if (BKE_collection_is_empty(override_resync_residual_storage)) { | if (BKE_collection_is_empty(override_resync_residual_storage)) { | ||||
| BKE_collection_delete(bmain, override_resync_residual_storage, true); | BKE_collection_delete(bmain, override_resync_residual_storage, true); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Advanced 'smart' function to delete library overrides (including their existing override | * Advanced 'smart' function to delete library overrides (including their existing override | ||||
| * hierarchy) and remap their usages to their linked reference IDs. | * hierarchy) and remap their usages to their linked reference IDs. | ||||
| ▲ Show 20 Lines • Show All 1,154 Lines • ▼ Show 20 Lines | #endif | ||||
| local->override_library->storage = storage_id; | local->override_library->storage = storage_id; | ||||
| #ifdef DEBUG_OVERRIDE_TIMEIT | #ifdef DEBUG_OVERRIDE_TIMEIT | ||||
| TIMEIT_END_AVERAGED(BKE_lib_override_library_operations_store_start); | TIMEIT_END_AVERAGED(BKE_lib_override_library_operations_store_start); | ||||
| #endif | #endif | ||||
| return storage_id; | return storage_id; | ||||
| } | } | ||||
| /** Restore given ID modified by \a BKE_lib_override_library_operations_store_start, to its | /** | ||||
| * original state. */ | * Restore given ID modified by #BKE_lib_override_library_operations_store_start, to its | ||||
| * original state. | |||||
| */ | |||||
| void BKE_lib_override_library_operations_store_end( | void BKE_lib_override_library_operations_store_end( | ||||
| OverrideLibraryStorage *UNUSED(override_storage), ID *local) | OverrideLibraryStorage *UNUSED(override_storage), ID *local) | ||||
| { | { | ||||
| BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(local)); | BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(local)); | ||||
| /* Nothing else to do here really, we need to keep all temp override storage data-blocks in | /* Nothing else to do here really, we need to keep all temp override storage data-blocks in | ||||
| * memory until whole file is written anyway (otherwise we'd get mem pointers overlap). */ | * memory until whole file is written anyway (otherwise we'd get mem pointers overlap). */ | ||||
| local->override_library->storage = NULL; | local->override_library->storage = NULL; | ||||
| Show All 15 Lines | |||||