Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/lib_override.c
| Show First 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
| /** Get override data for a given ID. Needed because of our beloved shape keys snowflake. */ | /** Get override data for a given ID. Needed because of our beloved shape keys snowflake. */ | ||||
| BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id) | BLI_INLINE IDOverrideLibrary *lib_override_get(Main *bmain, ID *id) | ||||
| { | { | ||||
| if (id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) { | if (id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) { | ||||
| const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); | const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); | ||||
| if (id_type->owner_get != NULL) { | if (id_type->owner_get != NULL) { | ||||
| return id_type->owner_get(bmain, id)->override_library; | return id_type->owner_get(bmain, id)->override_library; | ||||
| } | } | ||||
| BLI_assert(!"IDTypeInfo of liboverride-embedded ID with no owner getter"); | BLI_assert_msg(0, "IDTypeInfo of liboverride-embedded ID with no owner getter"); | ||||
| } | } | ||||
| return id->override_library; | return id->override_library; | ||||
| } | } | ||||
| /** Initialize empty overriding of \a reference_id by \a local_id. */ | /** Initialize empty overriding of \a reference_id by \a local_id. */ | ||||
| IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) | IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) | ||||
| { | { | ||||
| /* If reference_id is NULL, we are creating an override template for purely local data. | /* If reference_id is NULL, we are creating an override template for purely local data. | ||||
| ▲ Show 20 Lines • Show All 661 Lines • ▼ Show 20 Lines | static void lib_override_library_create_post_process(Main *bmain, | ||||
| 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) | ||||
| { | { | ||||
| /* NOTE: We only care about local IDs here, if a linked object is not instantiated in any way we | /* NOTE: We only care about local IDs here, if a linked object is not instantiated in any way we | ||||
| * do not do anything about it. */ | * do not do anything about it. */ | ||||
| BKE_main_collection_sync(bmain); | /* We need to use the `_remap` version here as we prevented any LayerCollection resync during the | ||||
| * whole liboverride resyncing, which involves a lot of ID remapping. | |||||
| * | |||||
| * Otherwise, cached Base GHash e.g. can contain invalid stale data. */ | |||||
| BKE_main_collection_sync_remap(bmain); | |||||
| /* We create a set of all objects referenced into the scene by its hierarchy of collections. | /* 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. | * 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. */ | * 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); | 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 | /* Instantiating the root collection or object should never be needed in resync case, since the | ||||
| * old override would be remapped to the new one. */ | * old override would be remapped to the new one. */ | ||||
| ▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | bool BKE_lib_override_library_resync(Main *bmain, | ||||
| const bool do_hierarchy_enforce, | const bool do_hierarchy_enforce, | ||||
| const bool do_post_process, | const bool do_post_process, | ||||
| BlendFileReadReport *reports) | BlendFileReadReport *reports) | ||||
| { | { | ||||
| BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); | BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); | ||||
| ID *id_root_reference = id_root->override_library->reference; | ID *id_root_reference = id_root->override_library->reference; | ||||
| if (id_root_reference->tag & LIB_TAG_MISSING) { | |||||
| BKE_reportf(reports != NULL ? reports->reports : NULL, | |||||
| RPT_ERROR, | |||||
| "impossible to resync data-block %s and its dependencies, as its linked reference " | |||||
| "is missing", | |||||
| id_root->name + 2); | |||||
| return false; | |||||
| } | |||||
| BKE_main_relations_create(bmain, 0); | BKE_main_relations_create(bmain, 0); | ||||
| LibOverrideGroupTagData data = {.bmain = bmain, | LibOverrideGroupTagData data = {.bmain = bmain, | ||||
| .scene = scene, | .scene = scene, | ||||
| .id_root = id_root, | .id_root = id_root, | ||||
| .tag = LIB_TAG_DOIT, | .tag = LIB_TAG_DOIT, | ||||
| .missing_tag = LIB_TAG_MISSING, | .missing_tag = LIB_TAG_MISSING, | ||||
| .is_override = true, | .is_override = true, | ||||
| .is_resync = true}; | .is_resync = true}; | ||||
| ▲ Show 20 Lines • Show All 693 Lines • ▼ Show 20 Lines | #define OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME "OVERRIDE_RESYNC_LEFTOVERS" | ||||
| if (override_resync_residual_storage == NULL) { | if (override_resync_residual_storage == NULL) { | ||||
| override_resync_residual_storage = BKE_collection_add( | override_resync_residual_storage = BKE_collection_add( | ||||
| bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME); | bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME); | ||||
| /* Hide the collection from viewport and render. */ | /* Hide the collection from viewport and render. */ | ||||
| override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT | | override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT | | ||||
| COLLECTION_RESTRICT_RENDER; | COLLECTION_RESTRICT_RENDER; | ||||
| } | } | ||||
| /* Necessary to improve performances, and prevent layers matching override sub-collections to be | |||||
| * lost when re-syncing the parent override collection. | |||||
| * Ref. T73411. */ | |||||
| BKE_layer_collection_resync_forbid(); | |||||
| int library_indirect_level = lib_override_libraries_index_define(bmain); | int library_indirect_level = lib_override_libraries_index_define(bmain); | ||||
| while (library_indirect_level >= 0) { | while (library_indirect_level >= 0) { | ||||
| /* Update overrides from each indirect level separately. */ | /* Update overrides from each indirect level separately. */ | ||||
| lib_override_library_main_resync_on_library_indirect_level(bmain, | lib_override_library_main_resync_on_library_indirect_level(bmain, | ||||
| scene, | scene, | ||||
| view_layer, | view_layer, | ||||
| override_resync_residual_storage, | override_resync_residual_storage, | ||||
| library_indirect_level, | library_indirect_level, | ||||
| reports); | reports); | ||||
| library_indirect_level--; | library_indirect_level--; | ||||
| } | } | ||||
| BKE_layer_collection_resync_allow(); | |||||
| /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ | /* Essentially ensures that potentially new overrides of new objects will be instantiated. */ | ||||
| lib_override_library_create_post_process( | lib_override_library_create_post_process( | ||||
| bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true); | 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); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 376 Lines • ▼ Show 20 Lines | switch (override_property_operation->operation) { | ||||
| case IDOVERRIDE_LIBRARY_OP_NOOP: | case IDOVERRIDE_LIBRARY_OP_NOOP: | ||||
| return true; | return true; | ||||
| case IDOVERRIDE_LIBRARY_OP_ADD: | case IDOVERRIDE_LIBRARY_OP_ADD: | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| case IDOVERRIDE_LIBRARY_OP_SUBTRACT: | case IDOVERRIDE_LIBRARY_OP_SUBTRACT: | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| case IDOVERRIDE_LIBRARY_OP_MULTIPLY: | case IDOVERRIDE_LIBRARY_OP_MULTIPLY: | ||||
| if (ptr_storage == NULL || ptr_storage->data == NULL || prop_storage == NULL) { | if (ptr_storage == NULL || ptr_storage->data == NULL || prop_storage == NULL) { | ||||
| BLI_assert(!"Missing data to apply differential override operation."); | BLI_assert_msg(0, "Missing data to apply differential override operation."); | ||||
| return false; | return false; | ||||
| } | } | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| case IDOVERRIDE_LIBRARY_OP_INSERT_AFTER: | case IDOVERRIDE_LIBRARY_OP_INSERT_AFTER: | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| case IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE: | case IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE: | ||||
| ATTR_FALLTHROUGH; | ATTR_FALLTHROUGH; | ||||
| case IDOVERRIDE_LIBRARY_OP_REPLACE: | case IDOVERRIDE_LIBRARY_OP_REPLACE: | ||||
| if ((ptr_dst == NULL || ptr_dst->data == NULL || prop_dst == NULL) || | if ((ptr_dst == NULL || ptr_dst->data == NULL || prop_dst == NULL) || | ||||
| (ptr_src == NULL || ptr_src->data == NULL || prop_src == NULL)) { | (ptr_src == NULL || ptr_src->data == NULL || prop_src == NULL)) { | ||||
| BLI_assert(!"Missing data to apply override operation."); | BLI_assert_msg(0, "Missing data to apply override operation."); | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| /** Check against potential \a bmain. */ | /** Check against potential \a bmain. */ | ||||
| ▲ Show 20 Lines • Show All 821 Lines • Show Last 20 Lines | |||||