Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/lib_override.c
| Show First 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | |||||
| ID *BKE_lib_override_library_create_from_id(Main *bmain, | ID *BKE_lib_override_library_create_from_id(Main *bmain, | ||||
| ID *reference_id, | ID *reference_id, | ||||
| const bool do_tagged_remap) | const bool do_tagged_remap) | ||||
| { | { | ||||
| BLI_assert(reference_id != NULL); | BLI_assert(reference_id != NULL); | ||||
| BLI_assert(ID_IS_LINKED(reference_id)); | BLI_assert(ID_IS_LINKED(reference_id)); | ||||
| ID *local_id = lib_override_library_create_from(bmain, reference_id, 0); | ID *local_id = lib_override_library_create_from(bmain, reference_id, 0); | ||||
| /* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant | |||||
| * mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies. | |||||
| * Ref T94650. */ | |||||
| local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY; | |||||
| if (do_tagged_remap) { | if (do_tagged_remap) { | ||||
| Key *reference_key, *local_key = NULL; | Key *reference_key, *local_key = NULL; | ||||
| if ((reference_key = BKE_key_from_id(reference_id)) != NULL) { | if ((reference_key = BKE_key_from_id(reference_id)) != NULL) { | ||||
| local_key = BKE_key_from_id(local_id); | local_key = BKE_key_from_id(local_id); | ||||
| BLI_assert(local_key != NULL); | BLI_assert(local_key != NULL); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 374 Lines • ▼ Show 20 Lines | static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) | ||||
| if (id_root->tag & LIB_TAG_MISSING) { | if (id_root->tag & LIB_TAG_MISSING) { | ||||
| id_root->tag |= data->missing_tag; | id_root->tag |= data->missing_tag; | ||||
| } | } | ||||
| else { | else { | ||||
| id_root->tag |= data->tag; | id_root->tag |= data->tag; | ||||
| } | } | ||||
| if (ELEM(GS(id_root->name), ID_OB, ID_GR)) { | /* Only objects and groups are currently considered as 'keys' in override hierarchies. */ | ||||
| /* Tag all collections and objects. */ | if (!ELEM(GS(id_root->name), ID_OB, ID_GR)) { | ||||
| return; | |||||
| } | |||||
| /* Tag all collections and objects recursively. */ | |||||
| lib_override_linked_group_tag_recursive(data); | lib_override_linked_group_tag_recursive(data); | ||||
| /* Do not override objects used as bone shapes, nor their collections if possible. */ | /* Do not override objects used as bone shapes, nor their collections if possible. */ | ||||
| lib_override_linked_group_tag_clear_boneshapes_objects(data); | lib_override_linked_group_tag_clear_boneshapes_objects(data); | ||||
| /* For each object tagged for override, ensure we get at least one local or liboverride | /* For each object tagged for override, ensure we get at least one local or liboverride | ||||
| * collection to host it. Avoids getting a bunch of random object in the scene's master | * collection to host it. Avoids getting a bunch of random object in the scene's master | ||||
| * collection when all objects' dependencies are not properly 'packed' into a single root | * collection when all objects' dependencies are not properly 'packed' into a single root | ||||
| * collection. */ | * collection. */ | ||||
| LISTBASE_FOREACH (Object *, ob, &bmain->objects) { | LISTBASE_FOREACH (Object *, ob, &bmain->objects) { | ||||
| if (ID_IS_LINKED(ob) && (ob->id.tag & data->tag) != 0) { | if (ID_IS_LINKED(ob) && (ob->id.tag & data->tag) != 0) { | ||||
| Collection *instantiating_collection = NULL; | Collection *instantiating_collection = NULL; | ||||
| Collection *instantiating_collection_override_candidate = NULL; | Collection *instantiating_collection_override_candidate = NULL; | ||||
| /* Loop over all collections instantiating the object, if we already have a 'locale' one we | /* Loop over all collections instantiating the object, if we already have a 'locale' one we | ||||
| * have nothing to do, otherwise try to find a 'linked' one that we can override too. */ | * have nothing to do, otherwise try to find a 'linked' one that we can override too. */ | ||||
| LinkNodePair *instantiating_collection_linklist = BLI_ghash_lookup( | LinkNodePair *instantiating_collection_linklist = BLI_ghash_lookup( | ||||
| data->linked_object_to_instantiating_collections, ob); | data->linked_object_to_instantiating_collections, ob); | ||||
| if (instantiating_collection_linklist != NULL) { | if (instantiating_collection_linklist != NULL) { | ||||
| for (LinkNode *instantiating_collection_linknode = | for (LinkNode *instantiating_collection_linknode = instantiating_collection_linklist->list; | ||||
| instantiating_collection_linklist->list; | |||||
| instantiating_collection_linknode != NULL; | instantiating_collection_linknode != NULL; | ||||
| instantiating_collection_linknode = instantiating_collection_linknode->next) { | instantiating_collection_linknode = instantiating_collection_linknode->next) { | ||||
| instantiating_collection = instantiating_collection_linknode->link; | instantiating_collection = instantiating_collection_linknode->link; | ||||
| /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the | /* In (recursive) resync case, if a collection of a 'parent' lib instantiates the | ||||
| * linked object, it is also fine. */ | * linked object, it is also fine. */ | ||||
| if (!ID_IS_LINKED(instantiating_collection) || | if (!ID_IS_LINKED(instantiating_collection) || | ||||
| (is_resync && ID_IS_LINKED(id_root) && | (is_resync && ID_IS_LINKED(id_root) && | ||||
| instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) { | instantiating_collection->id.lib->temp_index < id_root->lib->temp_index)) { | ||||
| break; | break; | ||||
| } | } | ||||
| if (ID_IS_LINKED(instantiating_collection) && | if (ID_IS_LINKED(instantiating_collection) && | ||||
| (!is_resync || instantiating_collection->id.lib == id_root->lib)) { | (!is_resync || instantiating_collection->id.lib == id_root->lib)) { | ||||
| instantiating_collection_override_candidate = instantiating_collection; | instantiating_collection_override_candidate = instantiating_collection; | ||||
| } | } | ||||
| instantiating_collection = NULL; | instantiating_collection = NULL; | ||||
| } | } | ||||
| } | } | ||||
| if (instantiating_collection == NULL && | if (instantiating_collection == NULL && | ||||
| instantiating_collection_override_candidate != NULL) { | instantiating_collection_override_candidate != NULL) { | ||||
| if (instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING) { | if (instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING) { | ||||
| instantiating_collection_override_candidate->id.tag |= data->missing_tag; | instantiating_collection_override_candidate->id.tag |= data->missing_tag; | ||||
| } | } | ||||
| else { | else { | ||||
| instantiating_collection_override_candidate->id.tag |= data->tag; | instantiating_collection_override_candidate->id.tag |= data->tag; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *data) | static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *data) | ||||
| { | { | ||||
| Main *bmain = data->bmain; | Main *bmain = data->bmain; | ||||
| ID *id_owner = data->id_root; | ID *id_owner = data->id_root; | ||||
| BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner)); | BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner)); | ||||
| BLI_assert(data->is_override); | BLI_assert(data->is_override); | ||||
| if (id_owner->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) { | |||||
| return; | |||||
| } | |||||
| const uint tag = data->tag; | const uint tag = data->tag; | ||||
| const uint missing_tag = data->missing_tag; | const uint missing_tag = data->missing_tag; | ||||
| MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, | MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, | ||||
| id_owner); | id_owner); | ||||
| BLI_assert(entry != NULL); | BLI_assert(entry != NULL); | ||||
| if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { | if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { | ||||
| ▲ Show 20 Lines • Show All 893 Lines • ▼ Show 20 Lines | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (id->tag & (LIB_TAG_DOIT | LIB_TAG_MISSING)) { | if (id->tag & (LIB_TAG_DOIT | LIB_TAG_MISSING)) { | ||||
| /* We already processed that ID as part of another ID's hierarchy. */ | /* We already processed that ID as part of another ID's hierarchy. */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) { | |||||
| /* This ID is not part of an override hierarchy. */ | |||||
| continue; | |||||
| } | |||||
| data.id_root = id->override_library->reference; | data.id_root = id->override_library->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); | ||||
| BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | ||||
| } | } | ||||
| FOREACH_MAIN_ID_END; | FOREACH_MAIN_ID_END; | ||||
| lib_override_group_tag_data_clear(&data); | lib_override_group_tag_data_clear(&data); | ||||
| /* Now check existing overrides, those needing resync will be the one either already tagged as | /* Now check existing overrides, those needing resync will be the one either already tagged as | ||||
| * such, or the one using linked data that is now tagged as needing override. */ | * such, or the one using linked data that is now tagged as needing override. */ | ||||
| BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); | ||||
| FOREACH_MAIN_ID_BEGIN (bmain, id) { | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) { | |||||
| /* This ID is not part of an override hierarchy. */ | |||||
| BLI_assert((id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0); | |||||
| continue; | |||||
| } | |||||
| if (id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) { | if (id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) { | ||||
| CLOG_INFO(&LOG, 4, "ID %s (%p) was already tagged as needing resync", id->name, id->lib); | CLOG_INFO(&LOG, 4, "ID %s (%p) was already tagged as needing resync", id->name, id->lib); | ||||
| lib_override_resync_tagging_finalize_recurse(bmain, id, library_indirect_level); | lib_override_resync_tagging_finalize_recurse(bmain, id, library_indirect_level); | ||||
| continue; | continue; | ||||
| } | } | ||||
| MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); | MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); | ||||
| BLI_assert(entry != NULL); | BLI_assert(entry != NULL); | ||||
| ▲ Show 20 Lines • Show All 1,368 Lines • Show Last 20 Lines | |||||