Commit: 8c9805fc628223984ad0c664b5a49b7f9eec0caa
Author: Bastien Montagne
Date:   Tue May 17 16:09:28 2022 +0200
Branches: master
https://developer.blender.org/rB8c9805fc628223984ad0c664b5a49b7f9eec0caa

Revert "Outliner: Remove the 'Remap data-block usages' operation."

This reverts commit 30534deced8dad16c566dd82db3edd462283de13.

After discussion and feedback from users, it's better to keep this tool
available until there is time to properly re-think the whole Outliner's
contextual menu.

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

M       source/blender/editors/space_outliner/outliner_edit.cc
M       source/blender/editors/space_outliner/outliner_intern.hh
M       source/blender/editors/space_outliner/outliner_ops.cc
M       source/blender/editors/space_outliner/outliner_tools.cc

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

diff --git a/source/blender/editors/space_outliner/outliner_edit.cc 
b/source/blender/editors/space_outliner/outliner_edit.cc
index f4e28af3fca..1de45b0ec96 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -575,6 +575,187 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name ID Remap Operator
+ * \{ */
+
+static int outliner_id_remap_exec(bContext *C, wmOperator *op)
+{
+  Main *bmain = CTX_data_main(C);
+  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+
+  const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
+  ID *old_id = reinterpret_cast<ID *>(
+      BLI_findlink(which_libbase(CTX_data_main(C), id_type), 
RNA_enum_get(op->ptr, "old_id")));
+  ID *new_id = reinterpret_cast<ID *>(
+      BLI_findlink(which_libbase(CTX_data_main(C), id_type), 
RNA_enum_get(op->ptr, "new_id")));
+
+  /* check for invalid states */
+  if (space_outliner == nullptr) {
+    return OPERATOR_CANCELLED;
+  }
+
+  if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == 
GS(new_id->name)))) {
+    BKE_reportf(op->reports,
+                RPT_ERROR_INVALID_INPUT,
+                "Invalid old/new ID pair ('%s' / '%s')",
+                old_id ? old_id->name : "Invalid ID",
+                new_id ? new_id->name : "Invalid ID");
+    return OPERATOR_CANCELLED;
+  }
+
+  if (ID_IS_LINKED(old_id)) {
+    BKE_reportf(op->reports,
+                RPT_WARNING,
+                "Old ID '%s' is linked from a library, indirect usages of this 
data-block will "
+                "not be remapped",
+                old_id->name);
+  }
+
+  BKE_libblock_remap(
+      bmain, old_id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | 
ID_REMAP_SKIP_NEVER_NULL_USAGE);
+
+  BKE_main_lib_objects_recalc_all(bmain);
+
+  /* recreate dependency graph to include new objects */
+  DEG_relations_tag_update(bmain);
+
+  /* Free gpu materials, some materials depend on existing objects,
+   * such as lights so freeing correctly refreshes. */
+  GPU_materials_free(bmain);
+
+  WM_event_add_notifier(C, NC_WINDOW, nullptr);
+
+  return OPERATOR_FINISHED;
+}
+
+static bool outliner_id_remap_find_tree_element(bContext *C,
+                                                wmOperator *op,
+                                                ListBase *tree,
+                                                const float y)
+{
+  LISTBASE_FOREACH (TreeElement *, te, tree) {
+    if (y > te->ys && y < te->ys + UI_UNIT_Y) {
+      TreeStoreElem *tselem = TREESTORE(te);
+
+      if ((tselem->type == TSE_SOME_ID) && tselem->id) {
+        RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
+        RNA_enum_set_identifier(C, op->ptr, "new_id", tselem->id->name + 2);
+        RNA_enum_set_identifier(C, op->ptr, "old_id", tselem->id->name + 2);
+        return true;
+      }
+    }
+    if (outliner_id_remap_find_tree_element(C, op, &te->subtree, y)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent 
*event)
+{
+  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
+  ARegion *region = CTX_wm_region(C);
+  float fmval[2];
+
+  if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, 
"id_type"))) {
+    UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], 
&fmval[0], &fmval[1]);
+
+    outliner_id_remap_find_tree_element(C, op, &space_outliner->tree, 
fmval[1]);
+  }
+
+  return WM_operator_props_dialog_popup(C, op, 400);
+}
+
+static const EnumPropertyItem *outliner_id_itemf(bContext *C,
+                                                 PointerRNA *ptr,
+                                                 PropertyRNA *UNUSED(prop),
+                                                 bool *r_free)
+{
+  if (C == nullptr) {
+    return DummyRNA_NULL_items;
+  }
+
+  EnumPropertyItem item_tmp = {0}, *item = nullptr;
+  int totitem = 0;
+  int i = 0;
+
+  short id_type = (short)RNA_enum_get(ptr, "id_type");
+  ID *id = reinterpret_cast<ID *>(which_libbase(CTX_data_main(C), 
id_type)->first);
+
+  for (; id; id = reinterpret_cast<ID *>(id->next)) {
+    item_tmp.identifier = item_tmp.name = id->name + 2;
+    item_tmp.value = i++;
+    RNA_enum_item_add(&item, &totitem, &item_tmp);
+  }
+
+  RNA_enum_item_end(&item, &totitem);
+  *r_free = true;
+
+  return item;
+}
+
+void OUTLINER_OT_id_remap(wmOperatorType *ot)
+{
+  PropertyRNA *prop;
+
+  /* identifiers */
+  ot->name = "Outliner ID Data Remap";
+  ot->idname = "OUTLINER_OT_id_remap";
+
+  /* callbacks */
+  ot->invoke = outliner_id_remap_invoke;
+  ot->exec = outliner_id_remap_exec;
+  ot->poll = ED_operator_outliner_active;
+
+  /* Flags. */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID 
Type", "");
+  RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
+  /* Changing ID type wont make sense, would return early with "Invalid 
old/new ID pair" anyways.
+   */
+  RNA_def_property_flag(prop, PROP_HIDDEN);
+
+  prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", 
"Old ID to replace");
+  RNA_def_property_enum_funcs_runtime(prop, nullptr, nullptr, 
outliner_id_itemf);
+  RNA_def_property_flag(prop, (PropertyFlag)(PROP_ENUM_NO_TRANSLATE | 
PROP_HIDDEN));
+
+  ot->prop = RNA_def_enum(ot->srna,
+                          "new_id",
+                          DummyRNA_NULL_items,
+                          0,
+                          "New ID",
+                          "New ID to remap all selected IDs' users to");
+  RNA_def_property_enum_funcs_runtime(ot->prop, nullptr, nullptr, 
outliner_id_itemf);
+  RNA_def_property_flag(ot->prop, PROP_ENUM_NO_TRANSLATE);
+}
+
+void id_remap_fn(bContext *C,
+                 ReportList *UNUSED(reports),
+                 Scene *UNUSED(scene),
+                 TreeElement *UNUSED(te),
+                 TreeStoreElem *UNUSED(tsep),
+                 TreeStoreElem *tselem,
+                 void *UNUSED(user_data))
+{
+  wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_id_remap", false);
+  PointerRNA op_props;
+
+  BLI_assert(tselem->id != nullptr);
+
+  WM_operator_properties_create_ptr(&op_props, ot);
+
+  RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
+  RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
+
+  WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
+
+  WM_operator_properties_free(&op_props);
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name ID Copy Operator
  * \{ */
diff --git a/source/blender/editors/space_outliner/outliner_intern.hh 
b/source/blender/editors/space_outliner/outliner_intern.hh
index 2fdf327cbee..f3bcb7b0f1e 100644
--- a/source/blender/editors/space_outliner/outliner_intern.hh
+++ b/source/blender/editors/space_outliner/outliner_intern.hh
@@ -442,6 +442,13 @@ void id_delete_fn(struct bContext *C,
                   struct TreeStoreElem *tsep,
                   struct TreeStoreElem *tselem,
                   void *user_data);
+void id_remap_fn(struct bContext *C,
+                 struct ReportList *reports,
+                 struct Scene *scene,
+                 struct TreeElement *te,
+                 struct TreeStoreElem *tsep,
+                 struct TreeStoreElem *tselem,
+                 void *user_data);
 
 /**
  * To retrieve coordinates with redrawing the entire tree.
@@ -516,6 +523,7 @@ void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
 void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
 void OUTLINER_OT_id_copy(struct wmOperatorType *ot);
 void OUTLINER_OT_id_paste(struct wmOperatorType *ot);
 void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.cc 
b/source/blender/editors/space_outliner/outliner_ops.cc
index e053a94c572..8baac45666e 100644
--- a/source/blender/editors/space_outliner/outliner_ops.cc
+++ b/source/blender/editors/space_outliner/outliner_ops.cc
@@ -31,6 +31,7 @@ void outliner_operatortypes(void)
   WM_operatortype_append(OUTLINER_OT_lib_relocate);
   WM_operatortype_append(OUTLINER_OT_id_operation);
   WM_operatortype_append(OUTLINER_OT_id_delete);
+  WM_operatortype_append(OUTLINER_OT_id_remap);
   WM_operatortype_append(OUTLINER_OT_id_copy);
   WM_operatortype_append(OUTLINER_OT_id_paste);
   WM_operatortype_append(OUTLINER_OT_data_operation);
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc 
b/source/blender/editors/space_outliner/outliner_tools.cc
index cb1f2bd7204..cc81d5ed68d 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -1700,6 +1700,7 @@ enum {
   OL_OP_SELECT = 1,
   OL_OP_DESELECT,
   OL_OP_SELECT_HIERARCHY,
+  OL_OP_REMAP,
   OL_OP_RENAME,
 };
 
@@ -1707,6 +1708,11 @@ static const EnumPropertyItem prop_object_op_types[] = {
     {OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""},
     {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
     {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
+    {OL_OP_REMAP,
+     "REMAP",
+     0,
+     "Remap Users",
+     "Make all users of selected data-blocks to use instead a new chosen one"},
     {OL_OP_RENAME, "RENAME", 0, "Rename", ""},
     {0, nullptr, 0, nullptr, nullptr},
 };
@@ -1768,6 +1774,12 @@ static int outliner_object_operation_exec(bContext *C, 
wmOperator *op)
       str = "Deselect Objects";
       selection_changed = true;
       break;
+    case OL_OP_REMAP:
+      outliner_do_libdata_operation(
+          C, op->reports, scene, space_outliner, &space_outliner->tree, 
id_remap_fn, nullptr);
+      /* No undo push here, operator does it itself (since it's a modal one, 
the op_undo_depth
+       * trick does not work here). */
+      break;
     case OL_OP_RENAME:
       outlin

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to