LibOverride: Add operator to convert a proxy object into an override.
In the end the process is surpringly simple, we only need to manually convert the proxy itself into an override (which is trivial), and then run common code with the default 'make override' operation. Fix T81059: Add operator to convert proxies to library overrides.
This commit is contained in:
parent
6fde0050c4
commit
c3a0618fbf
Notes:
blender-bot
2023-02-14 06:49:57 +01:00
Referenced by issue #81049, Add operator to convert proxies to library overrides
|
@ -2191,6 +2191,8 @@ class VIEW3D_MT_object_relations(Menu):
|
|||
|
||||
layout.operator("object.make_override_library", text="Make Library Override...")
|
||||
|
||||
layout.operator("object.convert_proxy_to_override")
|
||||
|
||||
layout.operator("object.make_dupli_face")
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -49,6 +49,7 @@ struct IDOverrideLibraryPropertyOperation;
|
|||
struct Main;
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct ViewLayer;
|
||||
|
||||
|
@ -77,6 +78,10 @@ bool BKE_lib_override_library_create(struct Main *bmain,
|
|||
struct ViewLayer *view_layer,
|
||||
struct ID *id_root,
|
||||
struct ID *id_reference);
|
||||
bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
struct Object *ob_proxy);
|
||||
bool BKE_lib_override_library_resync(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
|
|
|
@ -668,6 +668,42 @@ bool BKE_lib_override_library_create(
|
|||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a given proxy object into a library override.
|
||||
*
|
||||
* \note This is actually a thin wrapper around \a BKE_lib_override_library_create, only extra work
|
||||
* is to actually convert the proxy itself into an override first.
|
||||
*
|
||||
* \return true if override was successfully created.
|
||||
*/
|
||||
bool BKE_lib_override_library_proxy_convert(Main *bmain,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
Object *ob_proxy)
|
||||
{
|
||||
/* proxy_group, if defined, is the empty instanciating 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;
|
||||
ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
|
||||
&ob_proxy->proxy->id;
|
||||
ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
|
||||
|
||||
/* 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->proxy->proxy_from = NULL;
|
||||
ob_proxy->proxy = ob_proxy->proxy_group = NULL;
|
||||
|
||||
DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
|
||||
|
||||
return BKE_lib_override_library_create(bmain, scene, view_layer, id_root, id_reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
|
||||
* data, from an existing override hierarchy.
|
||||
|
|
|
@ -63,6 +63,7 @@ void OBJECT_OT_track_set(struct wmOperatorType *ot);
|
|||
void OBJECT_OT_track_clear(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_local(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_override_library(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_convert_proxy_to_override(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
|
||||
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
|
||||
|
|
|
@ -81,6 +81,7 @@ void ED_operatortypes_object(void)
|
|||
WM_operatortype_append(OBJECT_OT_track_clear);
|
||||
WM_operatortype_append(OBJECT_OT_make_local);
|
||||
WM_operatortype_append(OBJECT_OT_make_override_library);
|
||||
WM_operatortype_append(OBJECT_OT_convert_proxy_to_override);
|
||||
WM_operatortype_append(OBJECT_OT_make_single_user);
|
||||
WM_operatortype_append(OBJECT_OT_make_links_scene);
|
||||
WM_operatortype_append(OBJECT_OT_make_links_data);
|
||||
|
|
|
@ -2490,6 +2490,54 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot)
|
|||
ot->prop = prop;
|
||||
}
|
||||
|
||||
static bool convert_proxy_to_override_poll(bContext *C)
|
||||
{
|
||||
Object *obact = CTX_data_active_object(C);
|
||||
|
||||
return obact != NULL && obact->proxy != NULL;
|
||||
}
|
||||
|
||||
static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
|
||||
Object *ob_proxy = CTX_data_active_object(C);
|
||||
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, view_layer, ob_proxy);
|
||||
|
||||
/* Remove the instance empty from this scene, the items now have an overridden collection
|
||||
* instead. */
|
||||
if (success && is_override_instancing_object) {
|
||||
ED_object_base_free_and_unlink(bmain, scene, ob_proxy_group);
|
||||
}
|
||||
|
||||
DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
|
||||
return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Convert Proxy To Override";
|
||||
ot->description = "Convert a proxy to a local library override";
|
||||
ot->idname = "OBJECT_OT_convert_proxy_to_override";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = convert_proxy_to_override_exec;
|
||||
ot->poll = convert_proxy_to_override_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
|
|
@ -737,6 +737,31 @@ static void id_local_fn(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
static void object_proxy_to_override_convert_fn(bContext *C,
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
TreeElement *UNUSED(te),
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
TreeStoreElem *tselem,
|
||||
void *UNUSED(user_data))
|
||||
{
|
||||
BLI_assert(TSE_IS_REAL_ID(tselem));
|
||||
ID *id_proxy = tselem->id;
|
||||
BLI_assert(GS(id_proxy->name) == ID_OB);
|
||||
Object *ob_proxy = (Object *)id_proxy;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
if (ob_proxy->proxy == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_lib_override_library_proxy_convert(
|
||||
CTX_data_main(C), scene, CTX_data_view_layer(C), ob_proxy);
|
||||
|
||||
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
}
|
||||
|
||||
typedef struct OutlinerLibOverrideData {
|
||||
bool do_hierarchy;
|
||||
} OutlinerLibOverrideData;
|
||||
|
@ -1404,6 +1429,7 @@ enum {
|
|||
OL_OP_RENAME,
|
||||
OL_OP_OBJECT_MODE_ENTER,
|
||||
OL_OP_OBJECT_MODE_EXIT,
|
||||
OL_OP_PROXY_TO_OVERRIDE_CONVERT,
|
||||
};
|
||||
|
||||
static const EnumPropertyItem prop_object_op_types[] = {
|
||||
|
@ -1418,6 +1444,11 @@ static const EnumPropertyItem prop_object_op_types[] = {
|
|||
{OL_OP_RENAME, "RENAME", 0, "Rename", ""},
|
||||
{OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""},
|
||||
{OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""},
|
||||
{OL_OP_PROXY_TO_OVERRIDE_CONVERT,
|
||||
"OBJECT_PROXY_TO_OVERRIDE",
|
||||
0,
|
||||
"Convert Proxy to Override",
|
||||
"Convert a Proxy object to a full library override, inclduing all its dependencies"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -1487,6 +1518,15 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
|
|||
C, op->reports, scene, space_outliner, &space_outliner->tree, item_rename_fn);
|
||||
str = "Rename Object";
|
||||
}
|
||||
else if (event == OL_OP_PROXY_TO_OVERRIDE_CONVERT) {
|
||||
outliner_do_object_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
object_proxy_to_override_convert_fn);
|
||||
str = "Convert Proxy to Override";
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -1654,6 +1694,7 @@ typedef enum eOutlinerIdOpTypes {
|
|||
OUTLINER_IDOP_LOCAL,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
|
||||
|
@ -1694,6 +1735,11 @@ static const EnumPropertyItem prop_id_op_types[] = {
|
|||
0,
|
||||
"Add Library Override Hierarchy",
|
||||
"Add a local override of this linked data-block, and its hierarchy of dependencies"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT,
|
||||
"OVERRIDE_LIBRARY_PROXY_CONVERT",
|
||||
0,
|
||||
"Convert Proxy to Override",
|
||||
"Convert a Proxy object to a full library override, inclduing all its dependencies"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
|
||||
"OVERRIDE_LIBRARY_RESET",
|
||||
0,
|
||||
|
@ -1904,6 +1950,16 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
ED_undo_push(C, "Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT: {
|
||||
outliner_do_object_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
object_proxy_to_override_convert_fn);
|
||||
ED_undo_push(C, "Convert Proxy to Override");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
|
|
Loading…
Reference in New Issue