Files
test2/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
Sergey Sharybin c1bc70b711 Cleanup: Add a copyright notice to files and use SPDX format
A lot of files were missing copyright field in the header and
the Blender Foundation contributed to them in a sense of bug
fixing and general maintenance.

This change makes it explicit that those files are at least
partially copyrighted by the Blender Foundation.

Note that this does not make it so the Blender Foundation is
the only holder of the copyright in those files, and developers
who do not have a signed contract with the foundation still
hold the copyright as well.

Another aspect of this change is using SPDX format for the
header. We already used it for the license specification,
and now we state it for the copyright as well, following the
FAQ:

    https://reuse.software/faq/
2023-05-31 16:19:06 +02:00

165 lines
5.7 KiB
C

/* SPDX-FileCopyrightText: 2016 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
#include "BLI_linklist.h"
/* Required for proxy to liboverrides conversion code. */
#define DNA_DEPRECATED_ALLOW
#include "DNA_ID.h"
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DEG_depsgraph.h"
#include "BKE_collection.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BLO_readfile.h"
static CLG_LogRef LOG = {"bke.liboverride_proxy_conversion"};
bool BKE_lib_override_library_proxy_convert(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
Object *ob_proxy)
{
/* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
* coming. */
Object *ob_proxy_group = ob_proxy->proxy_group;
const bool is_override_instancing_object = (ob_proxy_group != NULL) &&
(ob_proxy_group->instance_collection != NULL);
ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
&ob_proxy->proxy->id;
ID *id_instance_hint = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
/* In some cases the instance collection of a proxy object may be local (see e.g. #83875). Not
* sure this is a valid state, but for now just abort the overriding process. */
if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_root)) {
if (ob_proxy->proxy != NULL) {
ob_proxy->proxy->proxy_from = NULL;
}
id_us_min((ID *)ob_proxy->proxy);
ob_proxy->proxy = ob_proxy->proxy_group = NULL;
return false;
}
/* We manually convert the proxy object into a library override, further override handling will
* then be handled by `BKE_lib_override_library_create()` just as for a regular override
* creation.
*/
ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
ob_proxy->proxy->id.newid = &ob_proxy->id;
BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
ob_proxy->id.override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
ob_proxy->proxy->proxy_from = NULL;
ob_proxy->proxy = ob_proxy->proxy_group = NULL;
DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
/* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
* overrides. Also do that for the IDs from the same lib as the proxy in case it is linked.
* While this might not be 100% the desired behavior, it is likely to be the case most of the
* time. Ref: #91711. */
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (!ID_IS_LINKED(id_iter) || id_iter->lib == ob_proxy->id.lib) {
id_iter->tag |= LIB_TAG_DOIT;
}
}
FOREACH_MAIN_ID_END;
return BKE_lib_override_library_create(
bmain, scene, view_layer, ob_proxy->id.lib, id_root, id_root, id_instance_hint, NULL, false);
}
static void lib_override_library_proxy_convert_do(Main *bmain,
Scene *scene,
Object *ob_proxy,
BlendFileReadReport *reports)
{
Object *ob_proxy_group = ob_proxy->proxy_group;
const bool is_override_instancing_object = ob_proxy_group != NULL;
const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
if (success) {
CLOG_INFO(&LOG,
4,
"Proxy object '%s' successfully converted to library overrides",
ob_proxy->id.name);
/* Remove the instance empty from this scene, the items now have an overridden collection
* instead. */
if (is_override_instancing_object) {
BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
}
reports->count.proxies_to_lib_overrides_success++;
}
}
void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
{
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LinkNodePair proxy_objects = {NULL};
FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
if (object->proxy_group != NULL) {
BLI_linklist_append(&proxy_objects, object);
}
}
FOREACH_SCENE_OBJECT_END;
FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
if (object->proxy != NULL && object->proxy_group == NULL) {
BLI_linklist_append(&proxy_objects, object);
}
}
FOREACH_SCENE_OBJECT_END;
for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
proxy_object_iter = proxy_object_iter->next)
{
Object *proxy_object = proxy_object_iter->link;
lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
}
BLI_linklist_free(proxy_objects.list, NULL);
}
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
if (object->proxy_group != NULL || object->proxy != NULL) {
if (ID_IS_LINKED(object)) {
CLOG_WARN(&LOG,
"Linked proxy object '%s' from '%s' failed to be converted to library override",
object->id.name + 2,
object->id.lib->filepath);
}
else {
CLOG_WARN(&LOG,
"Proxy object '%s' failed to be converted to library override",
object->id.name + 2);
}
reports->count.proxies_to_lib_overrides_failures++;
if (object->proxy != NULL) {
object->proxy->proxy_from = NULL;
}
id_us_min((ID *)object->proxy);
object->proxy = object->proxy_group = NULL;
}
}
}