[Bf-blender-cvs] [c3a0618fbff] master: LibOverride: Add operator to convert a proxy object into an override.

Bastien Montagne noreply at git.blender.org
Wed Sep 23 11:07:43 CEST 2020


Commit: c3a0618fbffffffcf5abbeed8de3f19d8a401db1
Author: Bastien Montagne
Date:   Wed Sep 23 10:47:27 2020 +0200
Branches: master
https://developer.blender.org/rBc3a0618fbffffffcf5abbeed8de3f19d8a401db1

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.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_lib_override.h
M	source/blender/blenkernel/intern/lib_override.c
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_ops.c
M	source/blender/editors/object/object_relations.c
M	source/blender/editors/space_outliner/outliner_tools.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 888b4a62139..bbe23bc8bbc 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -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()
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 9a5700d2fbd..233a7d6e478 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -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,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index d7ccef3c0e7..ec53229057c 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -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.
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 0a243a56dee..d0c6134bab5 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -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);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 390770d5c5c..3fc29f3147b 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -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);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 4adf1a8d9f2..9750eff677d 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -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;
+}
+
 /** \} */
 
 /* ------------------------------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 8fe4c364aa6..eb2969aa15d 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -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,
   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list