[Bf-blender-cvs] [3bc037a7eb8] blender-v3.2-release: Fix T96399: New 3.1 OBJ exporter is missing Path Mode setting

Aras Pranckevicius noreply at git.blender.org
Tue May 10 18:00:38 CEST 2022


Commit: 3bc037a7eb8d214aac9d755f8b2dd0e04cdf3a85
Author: Aras Pranckevicius
Date:   Tue May 10 11:34:42 2022 +0300
Branches: blender-v3.2-release
https://developer.blender.org/rB3bc037a7eb8d214aac9d755f8b2dd0e04cdf3a85

Fix T96399: New 3.1 OBJ exporter is missing Path Mode setting

New OBJ exporter is missing "Path Mode" setting for exporting .mtl
files. The options that used to be available were: Auto, Absolute,
Relative, Match, Strip Path, Copy. All of them are important. The new
behavior (without any UI option to control it) curiously does not match
any of the previous setting. New behavior is like "Relative, but to the
source blender file, and not the destination export file".

Most of the previous logic was only present in Python based code
(bpy_extras.io_utils.path_reference and friends). The bulk of this
commit is porting that to C++.

Reviewed By: Howard Trickey
Differential Revision: https://developer.blender.org/D14906

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

M	source/blender/editors/io/CMakeLists.txt
M	source/blender/editors/io/io_obj.c
M	source/blender/io/common/CMakeLists.txt
A	source/blender/io/common/IO_path_util.hh
A	source/blender/io/common/IO_path_util_types.h
A	source/blender/io/common/intern/path_util.cc
M	source/blender/io/wavefront_obj/IO_wavefront_obj.h
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
M	source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc
M	source/blender/io/wavefront_obj/exporter/obj_exporter.cc
M	source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
M	source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh

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

diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 418a399db28..ef093a01ff8 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -9,6 +9,7 @@ set(INC
   ../../depsgraph
   ../../io/alembic
   ../../io/collada
+  ../../io/common
   ../../io/gpencil
   ../../io/usd
   ../../io/wavefront_obj
diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c
index 9156ff15ded..886586ff236 100644
--- a/source/blender/editors/io/io_obj.c
+++ b/source/blender/editors/io/io_obj.c
@@ -29,6 +29,7 @@
 
 #include "DEG_depsgraph.h"
 
+#include "IO_path_util_types.h"
 #include "IO_wavefront_obj.h"
 #include "io_obj.h"
 
@@ -59,6 +60,15 @@ static const EnumPropertyItem io_obj_export_evaluation_mode[] = {
      "Export objects as they appear in the viewport"},
     {0, NULL, 0, NULL, NULL}};
 
+static const EnumPropertyItem io_obj_path_mode[] = {
+    {PATH_REFERENCE_AUTO, "AUTO", 0, "Auto", "Use Relative paths with subdirectories only"},
+    {PATH_REFERENCE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Always write absolute paths"},
+    {PATH_REFERENCE_RELATIVE, "RELATIVE", 0, "Relative", "Write relative paths where possible"},
+    {PATH_REFERENCE_MATCH, "MATCH", 0, "Match", "Match Absolute/Relative setting with input path"},
+    {PATH_REFERENCE_STRIP, "STRIP", 0, "Strip", "Write filename only"},
+    {PATH_REFERENCE_COPY, "COPY", 0, "Copy", "Copy the file to the destination path"},
+    {0, NULL, 0, NULL, NULL}};
+
 static int wm_obj_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
 {
   if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -87,6 +97,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
     return OPERATOR_CANCELLED;
   }
   struct OBJExportParams export_params;
+  export_params.file_base_for_tests[0] = '\0';
   RNA_string_get(op->ptr, "filepath", export_params.filepath);
   export_params.blen_filepath = CTX_data_main(C)->filepath;
   export_params.export_animation = RNA_boolean_get(op->ptr, "export_animation");
@@ -103,6 +114,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
   export_params.export_uv = RNA_boolean_get(op->ptr, "export_uv");
   export_params.export_normals = RNA_boolean_get(op->ptr, "export_normals");
   export_params.export_materials = RNA_boolean_get(op->ptr, "export_materials");
+  export_params.path_mode = RNA_enum_get(op->ptr, "path_mode");
   export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
   export_params.export_curves_as_nurbs = RNA_boolean_get(op->ptr, "export_curves_as_nurbs");
 
@@ -119,9 +131,9 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
 
 static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
 {
-
   const bool export_animation = RNA_boolean_get(imfptr, "export_animation");
   const bool export_smooth_groups = RNA_boolean_get(imfptr, "export_smooth_groups");
+  const bool export_materials = RNA_boolean_get(imfptr, "export_materials");
 
   uiLayoutSetPropSep(layout, true);
   uiLayoutSetPropDecorate(layout, false);
@@ -150,6 +162,9 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
   uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE);
   uiItemR(sub, imfptr, "apply_modifiers", 0, IFACE_("Apply Modifiers"), ICON_NONE);
   uiItemR(sub, imfptr, "export_eval_mode", 0, IFACE_("Properties"), ICON_NONE);
+  sub = uiLayoutColumn(sub, false);
+  uiLayoutSetEnabled(sub, export_materials);
+  uiItemR(sub, imfptr, "path_mode", 0, IFACE_("Path Mode"), ICON_NONE);
 
   /* Options for what to write. */
   box = uiLayoutBox(layout);
@@ -162,6 +177,7 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
   uiItemR(sub, imfptr, "export_triangulated_mesh", 0, IFACE_("Triangulated Mesh"), ICON_NONE);
   uiItemR(sub, imfptr, "export_curves_as_nurbs", 0, IFACE_("Curves as NURBS"), ICON_NONE);
 
+  /* Grouping options. */
   box = uiLayoutBox(layout);
   uiItemL(box, IFACE_("Grouping"), ICON_GROUP);
   col = uiLayoutColumn(box, false);
@@ -322,6 +338,12 @@ void WM_OT_obj_export(struct wmOperatorType *ot)
                   "Export Materials",
                   "Export MTL library. There must be a Principled-BSDF node for image textures to "
                   "be exported to the MTL file");
+  RNA_def_enum(ot->srna,
+               "path_mode",
+               io_obj_path_mode,
+               PATH_REFERENCE_AUTO,
+               "Path Mode",
+               "Method used to reference paths");
   RNA_def_boolean(ot->srna,
                   "export_triangulated_mesh",
                   false,
diff --git a/source/blender/io/common/CMakeLists.txt b/source/blender/io/common/CMakeLists.txt
index b1add38bf01..b5766b44025 100644
--- a/source/blender/io/common/CMakeLists.txt
+++ b/source/blender/io/common/CMakeLists.txt
@@ -19,10 +19,13 @@ set(SRC
   intern/dupli_parent_finder.cc
   intern/dupli_persistent_id.cc
   intern/object_identifier.cc
+  intern/path_util.cc
   intern/string_utils.cc
 
   IO_abstract_hierarchy_iterator.h
   IO_dupli_persistent_id.hh
+  IO_path_util.hh
+  IO_path_util_types.h
   IO_string_utils.hh
   IO_types.h
   intern/dupli_parent_finder.hh
diff --git a/source/blender/io/common/IO_path_util.hh b/source/blender/io/common/IO_path_util.hh
new file mode 100644
index 00000000000..ac2f935523e
--- /dev/null
+++ b/source/blender/io/common/IO_path_util.hh
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#pragma once
+
+#include "BLI_string_ref.hh"
+#include "BLI_set.hh"
+
+#include "IO_path_util_types.h"
+
+namespace blender::io {
+
+/**
+ * Return a filepath relative to a destination directory, for use with
+ * exporters.
+ *
+ * When PATH_REFERENCE_COPY mode is used, the file path pair (source
+ * path, destination path) is added to the `copy_set`.
+ * 
+ * Equivalent of bpy_extras.io_utils.path_reference.
+ */
+std::string path_reference(StringRefNull filepath,
+                           StringRefNull base_src,
+                           StringRefNull base_dst,
+                           ePathReferenceMode mode,
+                           Set<std::pair<std::string, std::string>> *copy_set = nullptr);
+
+/** Execute copying files of path_reference. */
+void path_reference_copy(const Set<std::pair<std::string, std::string>> &copy_set);
+
+} // namespace blender::io
diff --git a/source/blender/io/common/IO_path_util_types.h b/source/blender/io/common/IO_path_util_types.h
new file mode 100644
index 00000000000..0233f601a81
--- /dev/null
+++ b/source/blender/io/common/IO_path_util_types.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#pragma once
+
+/** Method used to reference paths. Equivalent of bpy_extras.io_utils.path_reference_mode. */
+typedef enum {
+  /** Use Relative paths with subdirectories only. */
+  PATH_REFERENCE_AUTO = 0,
+  /** Always write absolute paths. */
+  PATH_REFERENCE_ABSOLUTE = 1,
+  /** Write relative paths where possible. */
+  PATH_REFERENCE_RELATIVE = 2,
+  /** Match Absolute/Relative setting with input path. */
+  PATH_REFERENCE_MATCH = 3,
+  /** Filename only. */
+  PATH_REFERENCE_STRIP = 4,
+  /** Copy the file to the destination path. */
+  PATH_REFERENCE_COPY = 5,
+} ePathReferenceMode;
diff --git a/source/blender/io/common/intern/path_util.cc b/source/blender/io/common/intern/path_util.cc
new file mode 100644
index 00000000000..2b9a1d67b44
--- /dev/null
+++ b/source/blender/io/common/intern/path_util.cc
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "IO_path_util.hh"
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+namespace blender::io {
+
+std::string path_reference(StringRefNull filepath,
+                           StringRefNull base_src,
+                           StringRefNull base_dst,
+                           ePathReferenceMode mode,
+                           Set<std::pair<std::string, std::string>> *copy_set)
+{
+  const bool is_relative = BLI_path_is_rel(filepath.c_str());
+  char filepath_abs[PATH_MAX];
+  BLI_strncpy(filepath_abs, filepath.c_str(), PATH_MAX);
+  BLI_path_abs(filepath_abs, base_src.c_str());
+  BLI_path_normalize(nullptr, filepath_abs);
+
+  /* Figure out final mode to be used. */
+  if (mode == PATH_REFERENCE_MATCH) {
+    mode = is_relative ? PATH_REFERENCE_RELATIVE : PATH_REFERENCE_ABSOLUTE;
+  }
+  else if (mode == PATH_REFERENCE_AUTO) {
+    mode = BLI_path_contains(base_dst.c_str(), filepath_abs) ? PATH_REFERENCE_RELATIVE :
+                                                               PATH_REFERENCE_ABSOLUTE;
+  }
+  else if (mode == PATH_REFERENCE_COPY) {
+    char filepath_cpy[PATH_MAX];
+    BLI_path_join(filepath_cpy, PATH_MAX, base_dst.c_str(), BLI_path_basename(filepath_abs), nullptr);
+    copy_set->add(std::make_pair(filepath_abs, filepath_cpy));
+    BLI_strncpy(filepath_abs, filepath_cpy, PATH_MAX);
+    mode = PATH_REFERENCE_RELATIVE;
+  }
+
+  /* Now we know the final path mode. */
+  if (mode == PATH_REFERENCE_ABSOLUTE) {
+    return filepath_abs;
+  }
+  else if (mode == PATH_REFERENCE_RELATIVE) {
+    char rel_path[PATH_MAX];
+    BLI_strncpy(rel_path, filepath_abs, PATH_MAX);
+    BLI_path_rel(rel_path, base_dst.c_str());
+    /* Can't always find relative path (e.g. between different drives). */
+    if (!BLI_path_is_rel(rel_path)) {
+      return filepath_abs;
+    }
+    return rel_path + 2; /* Skip blender's internal "//" prefix. */
+  }
+  else if (mode == PATH_REFERENCE_STRIP) {
+    return BLI_path_basename(filepath_abs);
+  }
+  BLI_assert_msg(false, "Invalid path reference mode");
+  return filepath_abs;
+}
+
+void path_reference_copy(const Set<std::pair<std::string, std::string>> &copy_set)
+{
+  for (const auto &copy : copy_set) {
+    const char *src = copy.first.c_str();
+    const char *dst = copy.second.c_str();
+    if (!BLI_exists(src)) {
+      fprintf(stderr, "Missing source file '%s', not copying\n", src);
+      continue;
+    }
+    if (0 == BLI_path_cmp_normalized(src, dst)) {
+      continue; /* Source and dest are the same. */
+    }
+    if (!BLI_make_existing_file(dst)) {
+      fprintf(stde

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list