[Bf-blender-cvs] [ca1aae3e7bf] temp-T50725-alembic-export-custom-properties: Support for matrices of type double

Sybren A. Stüvel noreply at git.blender.org
Thu Sep 10 19:45:40 CEST 2020


Commit: ca1aae3e7bf9f0c2c61fe6d6fd54cf0c4042016d
Author: Sybren A. Stüvel
Date:   Thu Sep 10 16:09:33 2020 +0200
Branches: temp-T50725-alembic-export-custom-properties
https://developer.blender.org/rBca1aae3e7bf9f0c2c61fe6d6fd54cf0c4042016d

Support for matrices of type double

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

M	source/blender/io/alembic/exporter/abc_custom_props.cc
M	source/blender/io/alembic/exporter/abc_custom_props.h

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

diff --git a/source/blender/io/alembic/exporter/abc_custom_props.cc b/source/blender/io/alembic/exporter/abc_custom_props.cc
index 17439007129..6962e801590 100644
--- a/source/blender/io/alembic/exporter/abc_custom_props.cc
+++ b/source/blender/io/alembic/exporter/abc_custom_props.cc
@@ -25,6 +25,7 @@
 
 #include <functional>
 #include <iostream>
+#include <memory>
 #include <string>
 
 #include <Alembic/Abc/OTypedArrayProperty.h>
@@ -53,45 +54,49 @@ CustomPropertiesExporter::~CustomPropertiesExporter()
 {
 }
 
-namespace {
-
-/* Callback for IDP_foreach_property() that just calls CustomPropertiesExporter::write(). */
-void customPropertiesExporter_write(IDProperty *id_property, void *user_data)
-{
-  CustomPropertiesExporter *exporter = reinterpret_cast<CustomPropertiesExporter *>(user_data);
-  exporter->write(id_property);
-};
-
-}  // namespace
-
 void CustomPropertiesExporter::write_all(IDProperty *group)
 {
   if (group == nullptr) {
     std::cout << "CustomPropertiesExporter::write_all(nullptr)\n";
     return;
   }
-  std::cout << "CustomPropertiesExporter::write_all(" << group->name << ")\n";
-  IDP_foreach_property(group,
-                       IDP_TYPE_FILTER_STRING | IDP_TYPE_FILTER_INT | IDP_TYPE_FILTER_FLOAT |
-                           IDP_TYPE_FILTER_ARRAY | IDP_TYPE_FILTER_DOUBLE,
-                       customPropertiesExporter_write,
-                       this);
+  std::cout << "CustomPropertiesExporter::write_all()\n";
+  BLI_assert(group->type = IDP_GROUP);
+
+  /* Loop over the properties, just like IDP_foreach_property() does but without the recursion. */
+  LISTBASE_FOREACH (IDProperty *, id_property, &group->data.group) {
+    if (STREQ(id_property->name, "_RNA_UI")) {
+      continue;
+    }
+    write(id_property);
+  }
+
   std::cout << "\n";
 }
 
 void CustomPropertiesExporter::write(IDProperty *id_property)
 {
   std::cout << "    CustomPropertiesExporter::write(" << id_property->name << " ";
+
+  if (id_property->name[0] == '\0') {
+    strcpy(id_property->name, "NONAME");
+    std::cout << "\033[95mskip nameless of type " << id_property->type << "\033[0m)\n";
+    /* This happens when custom properties are pointing to things like mathutils.Matrix. Not sure
+     * why they don't get a name then, though. */
+    return;
+  }
+
   switch (id_property->type) {
     case IDP_STRING: {
       std::cout << "string";
       /* The Alembic library doesn't accept NULL-terminated character arrays. */
-      const std::string prop_value = IDP_String(id_property);
+      const std::string prop_value(IDP_String(id_property), id_property->len - 1);
       set_scalar_property<OStringArrayProperty, std::string>(id_property->name, prop_value);
       break;
     }
     case IDP_INT:
       std::cout << "int";
+      static_assert(sizeof(int) == sizeof(int32_t), "Expecting 'int' to be 32-bit");
       set_scalar_property<OInt32ArrayProperty, int32_t>(id_property->name, IDP_Int(id_property));
       break;
     case IDP_FLOAT:
@@ -104,46 +109,219 @@ void CustomPropertiesExporter::write(IDProperty *id_property)
                                                         IDP_Double(id_property));
       break;
     case IDP_ARRAY:
-      switch (id_property->subtype) {
-        case IDP_INT: {
-          std::cout << "int[]";
-          const int *array = (int *)IDP_Array(id_property);
-          set_array_property<OInt32ArrayProperty, int32_t>(
-              id_property->name, array, id_property->len);
-          break;
-        }
-        case IDP_FLOAT: {
-          std::cout << "float[]";
-          const float *array = (float *)IDP_Array(id_property);
-          set_array_property<OFloatArrayProperty, float>(
-              id_property->name, array, id_property->len);
-          break;
-        }
-        case IDP_DOUBLE: {
-          std::cout << "double[]";
-          const double *array = (double *)IDP_Array(id_property);
-          set_array_property<ODoubleArrayProperty, double>(
-              id_property->name, array, id_property->len);
-          break;
-        }
-        case IDP_ARRAY:
-        case IDP_GROUP:
-        case IDP_ID:
-        case IDP_IDPARRAY:
-          std::cout << "\033[91munsupported[]\033[0m)\n";
-          /* Unsupported. */
-          break;
-      }
+      write_array(id_property);
+      break;
+    case IDP_IDPARRAY:
+      write_idparray(id_property);
+      break;
+
+    /* Unsupported: */
+    case IDP_GROUP:
+    case IDP_ID:
+      std::cout << "\033[91munsupported type " << (uint16_t)id_property->type << "\033[0m)\n";
+      break;
+  }
+}
+
+void CustomPropertiesExporter::write_array(IDProperty *id_property)
+{
+  BLI_assert(id_property->type == IDP_ARRAY);
+
+  switch (id_property->subtype) {
+    case IDP_INT: {
+      std::cout << "int[]";
+      const int *array = (int *)IDP_Array(id_property);
+      static_assert(sizeof(int) == sizeof(int32_t), "Expecting 'int' to be 32-bit");
+      set_array_property<OInt32ArrayProperty, int32_t>(id_property->name, array, id_property->len);
+      break;
+    }
+    case IDP_FLOAT: {
+      std::cout << "float[]";
+      const float *array = (float *)IDP_Array(id_property);
+      set_array_property<OFloatArrayProperty, float>(id_property->name, array, id_property->len);
+      break;
+    }
+    case IDP_DOUBLE: {
+      std::cout << "double[]";
+      const double *array = (double *)IDP_Array(id_property);
+      set_array_property<ODoubleArrayProperty, double>(id_property->name, array, id_property->len);
+      break;
+    }
+
+    /* Unsupported: */
+    case IDP_ARRAY:
+      std::cout << "\033[91marray-of-arrays\033[0m\n";
+      break;
+    case IDP_GROUP:
+      std::cout << "\033[91marray-of-groups\033[0m\n";
+      break;
+    case IDP_ID:
+      std::cout << "\033[91marray-of-IDs\033[0m\n";
+      break;
+    case IDP_IDPARRAY:
+      std::cout << "\033[91array-of-IDPARRAY\033[0m)\n";
+      break;
+  }
+}
+
+void CustomPropertiesExporter::write_idparray(IDProperty *idp_array)
+{
+  BLI_assert(idp_array->type == IDP_IDPARRAY);
+
+  if (idp_array->len == 0) {
+    /* Don't bother writing dataless arrays. */
+    return;
+  }
+
+  IDProperty *idp_elements = (IDProperty *)IDP_Array(idp_array);
+
+#ifndef NDEBUG
+  /* Sanity check that all elements of the array have the same type.
+   * Blender should already enforce this, hence it's only used in debug mode. */
+  for (int i = 1; i < idp_array->len; i++) {
+    if (idp_elements[i].type == idp_elements[0].type) {
+      continue;
+    }
+
+    std::cerr << "Custom property " << idp_array->name << " has elements of varying type";
+    BLI_assert(!"Mixed type IDP_ARRAY custom property found");
+  }
+#endif
+
+  // /* Loop over the array, just like IDP_foreach_property() does but without the recursion. */
+  // IDProperty *loop = IDP_Array(idp_array);
+  // for (int i = 0; i < idp_array->len; i++) {
+  //   IDP_foreach_property(&loop[i], type_filter, callback, user_data);
+  // }
+
+  std::cout << "IDPArray of ";
+  switch (idp_elements[0].type) {
+    case IDP_STRING:
+      std::cout << "IDP_STRING";
+      write_idparray_of_strings(idp_array);
+      break;
+    case IDP_ARRAY:
+      std::cout << "IDP_ARRAY: ";
+      write_idparray_matrix(idp_array);
       break;
+
+    /* Unsupported. */
+    case IDP_INT:
+    case IDP_FLOAT:
+    case IDP_DOUBLE:
     case IDP_GROUP:
     case IDP_ID:
     case IDP_IDPARRAY:
-      std::cout << "\033[91munsupported\033[0m)\n";
-      /* Unsupported. */
+    case IDP_NUMTYPES:
+      break;
+  }
+  std::cout << "\n";
+}
+
+void CustomPropertiesExporter::write_idparray_of_strings(IDProperty *idp_array)
+{
+  BLI_assert(idp_array->type == IDP_IDPARRAY);
+  BLI_assert(idp_array->len > 0);
+
+  /* Convert to an array of std::strings, because Alembic doesn't like zero-delimited strings. */
+  IDProperty *idp_elements = (IDProperty *)IDP_Array(idp_array);
+  std::vector<std::string> strings(idp_array->len);
+  for (int i = 0; i < idp_array->len; i++) {
+    BLI_assert(idp_elements[i].type == IDP_STRING);
+    strings[i] = IDP_String(&idp_elements[i]);
+  }
+
+  /* Alembic needs a pointer to the first value of the array. */
+  const std::string *array_of_strings = &strings[0];
+  set_array_property<OStringArrayProperty, std::string>(
+      idp_array->name, array_of_strings, strings.size());
+}
+
+void CustomPropertiesExporter::write_idparray_matrix(IDProperty *idp_array)
+{
+  BLI_assert(idp_array->type == IDP_IDPARRAY);
+  BLI_assert(idp_array->len > 0);
+
+  /* This must be an array of arrays. */
+  IDProperty *idp_rows = (IDProperty *)IDP_Array(idp_array);
+  BLI_assert(idp_rows[0].type == IDP_ARRAY);
+
+  /* This function is made for writing NxM matrices, and doesn't support non-numeric types or rows
+   * of varying length. */
+  const size_t num_rows = idp_array->len;
+  if (num_rows == 0) {
+    return;
+  }
+  const size_t num_cols = idp_rows[0].len;
+  const int subtype = idp_rows[0].subtype;
+  if (!ELEM(subtype, IDP_INT, IDP_FLOAT, IDP_DOUBLE)) {
+    /* Non-numerical types are not supported. */
+    return;
+  }
+
+  /* All rows must have the same length, and have values of the same type. */
+  for (int row_idx = 0; row_idx < num_rows; row_idx++) {
+    const IDProperty &idp_row = idp_rows[0];
+    if (idp_row.subtype != subtype || idp_row.len != num_cols) {
+      return;
+    }
+  }
+
+  std::cout << "matrix[" << num_rows << "][" << num_cols << "]";
+  switch (subtype) {
+    case IDP_INT:
+      write_idparray_matrix_int(idp_array);
+      break;
+    case IDP_FLOAT:
+      write_idparray_matrix_float(idp_array);
+      break;
+    case IDP_DOUBLE:
+      write_idparray_matrix_double(idp_array);
       break;
   }
 }
 
+void CustomPropertiesExporter::write_idparray_matrix_int(IDProperty * /*idp_array*/)
+{
+  std::cout << "int";
+}
+
+void CustomPropertiesExporter::write_idparray_matrix_float(IDProperty * /*idp_array*/)
+{
+  std::cout << "float";
+}
+
+void CustomPropertiesExporter::write_idparray_matrix_double(IDProperty *idp_array)
+{
+  std::cout << "double";
+  BLI_assert(idp_array->type == IDP_IDPARRAY);
+  BLI_assert(idp_array->len > 0);
+
+  /* This must be an array of arrays of double. */
+  const IDProperty *idp_rows = (IDProper

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list