LibOverride: Fix several issues with resync code.
This commit essentially touches to post-processing of collections and objects after resync itself has been done, to ensure their proper instantiation in the scene: - Remove a lot of the process in resync case (resynced data are assumed to be already instantiated in the scene, unlike override creation case). - For auto-resync, only do post-processing once after all overrides have been resynced (doing it after each individual resynced was causing a lot of instantiation glitches, with a lot of unwanted extra objects and collections being added to the master collection). It also deals in a much more reliable way with detection of objects missing from the scene, by using the new `BKE_scene_objects_as_gset` utils. As a bonus this makes auto-resync process slightly faster (only by a few percents, but that's always good to get).
This commit is contained in:
parent
c1b1ed4d5b
commit
e92a7800b5
|
@ -84,7 +84,8 @@ bool BKE_lib_override_library_resync(struct Main *bmain,
|
|||
struct ViewLayer *view_layer,
|
||||
struct ID *id_root,
|
||||
struct Collection *override_resync_residual_storage,
|
||||
const bool do_hierarchy_enforce);
|
||||
const bool do_hierarchy_enforce,
|
||||
const bool do_post_process);
|
||||
void BKE_lib_override_library_main_resync(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer);
|
||||
|
|
|
@ -650,18 +650,6 @@ static bool lib_override_library_create_do(Main *bmain, ID *id_root)
|
|||
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,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
|
@ -672,13 +660,23 @@ static void lib_override_library_create_post_process(Main *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)) {
|
||||
case ID_GR: {
|
||||
Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
|
||||
(Object *)id_reference :
|
||||
NULL;
|
||||
Collection *collection_new = ((Collection *)id_root->newid);
|
||||
if (is_resync && BKE_collection_is_in_scene(collection_new)) {
|
||||
break;
|
||||
}
|
||||
if (ob_reference != NULL) {
|
||||
BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new);
|
||||
}
|
||||
|
@ -692,52 +690,16 @@ static void lib_override_library_create_post_process(Main *bmain,
|
|||
bmain, scene, ((Collection *)id_root), collection_new);
|
||||
}
|
||||
|
||||
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) {
|
||||
if (ob_new != NULL && ob_new->id.override_library != NULL) {
|
||||
if (ob_reference != NULL) {
|
||||
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 (is_resync) {
|
||||
ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER;
|
||||
}
|
||||
}
|
||||
BLI_assert(BKE_collection_is_in_scene(collection_new));
|
||||
|
||||
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);
|
||||
if (is_resync) {
|
||||
ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
|
||||
all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene);
|
||||
break;
|
||||
}
|
||||
case ID_OB: {
|
||||
Object *ob_new = (Object *)id_root->newid;
|
||||
if (!lib_override_library_create_post_process_object_is_instantiated(
|
||||
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);
|
||||
}
|
||||
if (is_resync) {
|
||||
ob_new->id.flag |= LIB_LIB_OVERRIDE_RESYNC_LEFTOVER;
|
||||
}
|
||||
if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) {
|
||||
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;
|
||||
}
|
||||
|
@ -747,16 +709,15 @@ static void lib_override_library_create_post_process(Main *bmain,
|
|||
}
|
||||
|
||||
/* We need to ensure all new overrides of objects are properly instantiated. */
|
||||
Collection *default_instantiating_collection = residual_storage;
|
||||
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
|
||||
Object *ob_new = (Object *)ob->id.newid;
|
||||
if (ob_new != NULL) {
|
||||
BLI_assert(ob_new->id.override_library != NULL &&
|
||||
ob_new->id.override_library->reference == &ob->id);
|
||||
|
||||
Collection *default_instantiating_collection = residual_storage;
|
||||
if (!lib_override_library_create_post_process_object_is_instantiated(
|
||||
view_layer, ob_new, is_resync)) {
|
||||
if (default_instantiating_collection == NULL) {
|
||||
if (BLI_gset_lookup(all_objects_in_scene, ob_new) == NULL) {
|
||||
if (id_root != NULL && default_instantiating_collection == NULL) {
|
||||
switch (GS(id_root->name)) {
|
||||
case ID_GR: {
|
||||
default_instantiating_collection = BKE_collection_add(
|
||||
|
@ -777,21 +738,23 @@ static void lib_override_library_create_post_process(Main *bmain,
|
|||
default_instantiating_collection = collection;
|
||||
}
|
||||
}
|
||||
if (default_instantiating_collection == NULL) {
|
||||
default_instantiating_collection = scene->master_collection;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
}
|
||||
if (default_instantiating_collection == NULL) {
|
||||
default_instantiating_collection = scene->master_collection;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_gset_free(all_objects_in_scene, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -902,7 +865,8 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
ViewLayer *view_layer,
|
||||
ID *id_root,
|
||||
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_LINKED(id_root));
|
||||
|
@ -1109,18 +1073,20 @@ bool BKE_lib_override_library_resync(Main *bmain,
|
|||
*/
|
||||
id_root = id_root_reference->newid;
|
||||
|
||||
/* 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
|
||||
* 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
|
||||
* that we do not have any stray objects. */
|
||||
lib_override_library_create_post_process(bmain,
|
||||
scene,
|
||||
view_layer,
|
||||
id_root_reference,
|
||||
id_root,
|
||||
override_resync_residual_storage,
|
||||
true);
|
||||
if (do_post_process) {
|
||||
/* 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
|
||||
* 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
|
||||
* that we do not have any stray objects. */
|
||||
lib_override_library_create_post_process(bmain,
|
||||
scene,
|
||||
view_layer,
|
||||
id_root_reference,
|
||||
id_root,
|
||||
override_resync_residual_storage,
|
||||
true);
|
||||
}
|
||||
|
||||
/* Cleanup. */
|
||||
BLI_ghash_free(linkedref_to_old_override, NULL, NULL);
|
||||
|
@ -1252,9 +1218,10 @@ void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *
|
|||
continue;
|
||||
}
|
||||
do_continue = true;
|
||||
|
||||
CLOG_INFO(&LOG, 2, "Resyncing %s...", id->name);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -1266,6 +1233,10 @@ void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *
|
|||
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)) {
|
||||
BKE_collection_delete(bmain, override_resync_residual_storage, true);
|
||||
}
|
||||
|
|
|
@ -925,7 +925,7 @@ static void id_override_library_resync_fn(bContext *C,
|
|||
}
|
||||
|
||||
BKE_lib_override_library_resync(
|
||||
bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce);
|
||||
bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true);
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue