Blender V4.5
lib_override_proxy_conversion.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "CLG_log.h"
10
11#include "BLI_linklist.h"
12#include "BLI_listbase.h"
13
14/* Required for proxy to liboverrides conversion code. */
15#define DNA_DEPRECATED_ALLOW
16
17#include "DNA_ID.h"
19#include "DNA_object_types.h"
20#include "DNA_scene_types.h"
21
22#include "DEG_depsgraph.hh"
23
24#include "BKE_collection.hh"
25#include "BKE_idtype.hh"
26#include "BKE_lib_id.hh"
27#include "BKE_lib_override.hh"
28#include "BKE_main.hh"
29
30#include "BLO_readfile.hh"
31
32static CLG_LogRef LOG = {"bke.liboverride_proxy_conversion"};
33
35 Scene *scene,
36 ViewLayer *view_layer,
37 Object *ob_proxy)
38{
39 /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
40 * coming. */
41 Object *ob_proxy_group = ob_proxy->proxy_group;
42 const bool is_override_instancing_object = (ob_proxy_group != nullptr) &&
43 (ob_proxy_group->instance_collection != nullptr);
44 ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
45 &ob_proxy->proxy->id;
46 ID *id_instance_hint = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
47
48 /* In some cases the instance collection of a proxy object may be local (see e.g. #83875). Not
49 * sure this is a valid state, but for now just abort the overriding process. */
51 if (ob_proxy->proxy != nullptr) {
52 ob_proxy->proxy->proxy_from = nullptr;
53 }
54 id_us_min((ID *)ob_proxy->proxy);
55 ob_proxy->proxy = ob_proxy->proxy_group = nullptr;
56 return false;
57 }
58
59 /* We manually convert the proxy object into a library override, further override handling will
60 * then be handled by `BKE_lib_override_library_create()` just as for a regular override
61 * creation.
62 */
63 ob_proxy->proxy->id.tag |= ID_TAG_DOIT;
64 ob_proxy->proxy->id.newid = &ob_proxy->id;
65 BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
67
68 ob_proxy->proxy->proxy_from = nullptr;
69 ob_proxy->proxy = ob_proxy->proxy_group = nullptr;
70
72
73 /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
74 * overrides. Also do that for the IDs from the same lib as the proxy in case it is linked.
75 * While this might not be 100% the desired behavior, it is likely to be the case most of the
76 * time. Ref: #91711. */
77 ID *id_iter;
78 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
79 if (!ID_IS_LINKED(id_iter) || id_iter->lib == ob_proxy->id.lib) {
80 id_iter->tag |= ID_TAG_DOIT;
81 }
82 }
84
86 scene,
87 view_layer,
88 ob_proxy->id.lib,
89 id_root,
90 id_root,
91 id_instance_hint,
92 nullptr,
93 false);
94}
95
97 Scene *scene,
98 Object *ob_proxy,
100{
101 Object *ob_proxy_group = ob_proxy->proxy_group;
102 const bool is_override_instancing_object = ob_proxy_group != nullptr;
103
104 const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, nullptr, ob_proxy);
105
106 if (success) {
107 CLOG_INFO(&LOG,
108 4,
109 "Proxy object '%s' successfully converted to library overrides",
110 ob_proxy->id.name);
111 /* Remove the instance empty from this scene, the items now have an overridden collection
112 * instead. */
113 if (is_override_instancing_object) {
114 BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
115 }
116 reports->count.proxies_to_lib_overrides_success++;
117 }
118}
119
121{
122 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
123 LinkNodePair proxy_objects = {nullptr};
124
125 FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
126 if (object->proxy_group != nullptr) {
127 BLI_linklist_append(&proxy_objects, object);
128 }
129 }
131
132 FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
133 if (object->proxy != nullptr && object->proxy_group == nullptr) {
134 BLI_linklist_append(&proxy_objects, object);
135 }
136 }
138
139 for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != nullptr;
140 proxy_object_iter = proxy_object_iter->next)
141 {
142 Object *proxy_object = static_cast<Object *>(proxy_object_iter->link);
143 lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
144 }
145
146 BLI_linklist_free(proxy_objects.list, nullptr);
147 }
148
149 LISTBASE_FOREACH (Object *, object, &bmain->objects) {
150 if (object->proxy_group != nullptr || object->proxy != nullptr) {
151 if (ID_IS_LINKED(object)) {
152 CLOG_WARN(&LOG,
153 "Linked proxy object '%s' from '%s' failed to be converted to library override",
154 object->id.name + 2,
155 object->id.lib->filepath);
156 }
157 else {
158 CLOG_WARN(&LOG,
159 "Proxy object '%s' failed to be converted to library override",
160 object->id.name + 2);
161 }
162 reports->count.proxies_to_lib_overrides_failures++;
163 if (object->proxy != nullptr) {
164 object->proxy->proxy_from = nullptr;
165 }
166 id_us_min((ID *)object->proxy);
167 object->proxy = object->proxy_group = nullptr;
168 }
169 }
170}
#define FOREACH_SCENE_OBJECT_END
bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, bool free_us)
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
void id_us_min(ID *id)
Definition lib_id.cc:361
bool BKE_lib_override_library_create(Main *bmain, Scene *scene, ViewLayer *view_layer, Library *owner_library, ID *id_root_reference, ID *id_hierarchy_root_reference, ID *id_instance_hint, ID **r_id_root_override, const bool do_fully_editable)
IDOverrideLibrary * BKE_lib_override_library_init(ID *local_id, ID *reference_id)
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:563
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:557
#define LISTBASE_FOREACH(type, var, list)
external readfile function prototypes.
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
void DEG_id_tag_update(ID *id, unsigned int flags)
ID and Library types, which are fundamental for SDNA.
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ LIBOVERRIDE_FLAG_SYSTEM_DEFINED
Definition DNA_ID.h:353
@ ID_TAG_DOIT
Definition DNA_ID.h:944
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
ReportList * reports
Definition WM_types.hh:1025
#define ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(_id)
#define ID_IS_LINKED(_id)
bool BKE_lib_override_library_proxy_convert(Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob_proxy)
void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
static void lib_override_library_proxy_convert_do(Main *bmain, Scene *scene, Object *ob_proxy, BlendFileReadReport *reports)
#define LOG(severity)
Definition log.h:32
unsigned int flag
Definition DNA_ID.h:338
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
struct Library * lib
Definition DNA_ID.h:410
struct ID * newid
Definition DNA_ID.h:408
IDOverrideLibrary * override_library
Definition DNA_ID.h:459
char name[66]
Definition DNA_ID.h:415
LinkNode * list
struct LinkNode * next
ListBase scenes
Definition BKE_main.hh:245
ListBase objects
Definition BKE_main.hh:247
struct Collection * instance_collection