Merge commit 'master@6ed15c5a41130b55cb57a43a8a9470a91d38c3d5' into blender2.8
authorSybren A. Stüvel <sybren@stuvel.eu>
Wed, 26 Apr 2017 14:50:29 +0000 (16:50 +0200)
committerSybren A. Stüvel <sybren@stuvel.eu>
Wed, 26 Apr 2017 14:50:29 +0000 (16:50 +0200)
# Conflicts:
# source/blender/alembic/intern/abc_exporter.cc

build_files/cmake/config/blender_full.cmake
build_files/cmake/config/blender_release.cmake
source/blender/alembic/ABC_alembic.h
source/blender/alembic/intern/abc_archive.cc
source/blender/alembic/intern/abc_exporter.cc
source/blender/alembic/intern/abc_hair.cc
source/blender/alembic/intern/abc_object.cc
source/blender/alembic/intern/alembic_capi.cc
source/blender/blenkernel/intern/constraint.c
source/blender/makesdna/DNA_cachefile_types.h
tests/python/bl_alembic_import_test.py

index 87b8ed5f92132b4267a2032dce9189794f63efad..ecde50ff156301cf72a63ee5d25334f0b4b368d1 100644 (file)
@@ -73,10 +73,9 @@ elseif(WIN32)
        endif()
 elseif(APPLE)
        set(WITH_JACK                ON  CACHE BOOL "" FORCE)
-       set(WITH_CODEC_QUICKTIME     ON  CACHE BOOL "" FORCE)
+       set(WITH_CODEC_QUICKTIME     OFF  CACHE BOOL "" FORCE)
        set(WITH_OPENSUBDIV          OFF CACHE BOOL "" FORCE)
-       set(WITH_CODEC_QUICKTIME     ON  CACHE BOOL "" FORCE)
 
-       include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
-       apple_check_quicktime()
+#      include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
+#      apple_check_quicktime()
 endif()
index b60c8c7380c7dd8c965eaecd08459ff05ca6c241..f7239559fb8c50a02869808997d5a925bae42d76 100644 (file)
@@ -74,10 +74,9 @@ elseif(WIN32)
        endif()
 elseif(APPLE)
        set(WITH_JACK                ON  CACHE BOOL "" FORCE)
-       set(WITH_CODEC_QUICKTIME     ON  CACHE BOOL "" FORCE)
+       set(WITH_CODEC_QUICKTIME     OFF  CACHE BOOL "" FORCE)
        set(WITH_OPENSUBDIV          OFF CACHE BOOL "" FORCE)
-       set(WITH_CODEC_QUICKTIME     ON  CACHE BOOL "" FORCE)
 
-       include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
-       apple_check_quicktime()
+#      include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
+#      apple_check_quicktime()
 endif()
index 6b698e5ec66acde37fcdaa59c3414094a24c8507..6228ae60c56de21b3386ac3fa537b62dca8c69e7 100644 (file)
@@ -121,6 +121,7 @@ struct DerivedMesh *ABC_read_mesh(struct CacheReader *reader,
                                   const char **err_str,
                                   int flags);
 
+void CacheReader_incref(struct CacheReader *reader);
 void CacheReader_free(struct CacheReader *reader);
 
 struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *handle,
index cdbda0ace690188c9a60f8f18eb44e7a4c50b597..194a8224c62b8be1d3e632569dc556e6e9019da4 100644 (file)
@@ -68,7 +68,7 @@ static IArchive open_archive(const std::string &filename,
 #else
                /* Inspect the file to see whether it's really a HDF5 file. */
                char header[4];  /* char(0x89) + "HDF" */
-               std::ifstream the_file(filename, std::ios::in | std::ios::binary);
+               std::ifstream the_file(filename.c_str(), std::ios::in | std::ios::binary);
                if (!the_file) {
                        std::cerr << "Unable to open " << filename << std::endl;
                }
index dd65613e2232ff985f0aac07c96c3935d70a1a73..2c2d0b598e92b8683d0ca3540bbdb7d4b2d9952b 100644 (file)
@@ -108,7 +108,7 @@ static bool object_is_smoke_sim(Object *ob)
        return false;
 }
 
-static bool object_is_shape(Object *ob)
+static bool object_type_is_exportable(Object *ob)
 {
        switch (ob->type) {
                case OB_MESH:
@@ -117,6 +117,7 @@ static bool object_is_shape(Object *ob)
                        }
 
                        return true;
+               case OB_EMPTY:
                case OB_CURVE:
                case OB_SURF:
                case OB_CAMERA:
@@ -387,7 +388,7 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, O
                return;
        }
 
-       if (object_is_shape(ob)) {
+       if (object_type_is_exportable(ob)) {
                createTransformWriter(ob, parent, dupliObParent);
        }
 
@@ -557,7 +558,7 @@ void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
 {
        Object *ob = ob_base->object;
 
-       if (!object_is_shape(ob)) {
+       if (!object_type_is_exportable(ob)) {
                return;
        }
 
index 9a974273a46bc4054c470b267fb105df927393de..2d42c532c9bce0dd7a5eb3b1e5c0ba4b0cc283e6 100644 (file)
@@ -241,7 +241,6 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
        invert_m4_m4_safe(inv_mat, m_object->obmat);
 
        MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE));
-       MFace *mface = dm->getTessFaceArray(dm);
        MVert *mverts = dm->getVertArray(dm);
 
        ParticleCacheKey **cache = m_psys->childcache;
@@ -253,12 +252,25 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
                path = cache[p];
 
                if (part->from == PART_FROM_FACE) {
-                       const int num = pc->num;
+                       if (part->childtype == PART_CHILD_PARTICLES || !mtface) {
+                               /* Face index is unknown for these particles, so just take info
+                                * from the parent. */
+                               uv_values.push_back(uv_values[pc->parent]);
+                               norm_values.push_back(norm_values[pc->parent]);
+                       }
+                       else {
+                               const int num = pc->num;
+                               if (num < 0) {
+                                       ABC_LOG(m_settings.logger)
+                                               << "Warning, child particle of hair system " << m_psys->name
+                                               << " has unknown face index of geometry of "<< (m_object->id.name + 2)
+                                               << ", skipping child hair." << std::endl;
+                                       continue;
+                               }
 
-                       MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
-                       MTFace *tface = mtface + num;
+                               MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE));
+                               MTFace *tface = mtface + num;
 
-                       if (mface && mtface) {
                                float r_uv[2], tmpnor[3], mapfw[4], vec[3];
 
                                psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv);
@@ -270,6 +282,14 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
                                norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1]));
                        }
                }
+               else {
+                       ABC_LOG(m_settings.logger)
+                               << "Unknown particle type " << part->from
+                               << " for child hair of system " << m_psys->name
+                               << std::endl;
+                       uv_values.push_back(uv_values[pc->parent]);
+                       norm_values.push_back(norm_values[pc->parent]);
+               }
 
                int steps = path->segments + 1;
                hvertices.push_back(steps);
index ce0f9225228666aef3b1995eb44918725f4ab40a..28a4d1850148654623742e1d4a4d534d2c7fff6a 100644 (file)
@@ -369,4 +369,5 @@ void AbcObjectReader::incref()
 void AbcObjectReader::decref()
 {
        --m_refcount;
+       BLI_assert(m_refcount >= 0);
 }
index 4aa4b8d548fea6cf2e3ccf1cfd2440e5dc03da75..61b18c7112fec47cdaea395d102eb29903b2d952 100644 (file)
@@ -175,7 +175,7 @@ static bool gather_objects_paths(const IObject &object, ListBase *object_paths)
                void *abc_path_void = MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath");
                AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(abc_path_void);
 
-               BLI_strncpy(abc_path->path, object.getFullName().c_str(), PATH_MAX);
+               BLI_strncpy(abc_path->path, object.getFullName().c_str(), sizeof(abc_path->path));
                BLI_addtail(object_paths, abc_path);
        }
 
@@ -377,6 +377,7 @@ bool ABC_export(
                std::swap(job->settings.frame_start, job->settings.frame_end);
        }
 
+       bool export_ok = false;
        if (as_background_job) {
                wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
                                            CTX_wm_window(C),
@@ -399,9 +400,12 @@ bool ABC_export(
 
                export_startjob(job, &stop, &do_update, &progress);
                export_endjob(job);
+               export_ok = job->export_ok;
+
+               MEM_freeN(job);
        }
 
-       return job->export_ok;
+       return export_ok;
 }
 
 /* ********************** Import file ********************** */
@@ -560,7 +564,7 @@ static std::pair<bool, AbcObjectReader *> visit_object(
 
                AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(
                                                  MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"));
-               BLI_strncpy(abc_path->path, full_name.c_str(), PATH_MAX);
+               BLI_strncpy(abc_path->path, full_name.c_str(), sizeof(abc_path->path));
                BLI_addtail(&settings.cache_file->object_paths, abc_path);
 
                /* We can now assign this reader as parent for our children. */
@@ -903,13 +907,14 @@ bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
 
        G.is_break = false;
 
+       bool import_ok = false;
        if (as_background_job) {
                wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
-                                                                       CTX_wm_window(C),
-                                                                       job->scene,
-                                                                       "Alembic Import",
-                                                                       WM_JOB_PROGRESS,
-                                                                       WM_JOB_TYPE_ALEMBIC);
+                                           CTX_wm_window(C),
+                                           job->scene,
+                                           "Alembic Import",
+                                           WM_JOB_PROGRESS,
+                                           WM_JOB_TYPE_ALEMBIC);
 
                /* setup job */
                WM_jobs_customdata_set(wm_job, job, import_freejob);
@@ -925,9 +930,12 @@ bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
 
                import_startjob(job, &stop, &do_update, &progress);
                import_endjob(job);
+               import_ok = job->import_ok;
+
+               import_freejob(job);
        }
 
-       return job->import_ok;
+       return import_ok;
 }
 
 /* ************************************************************************** */
@@ -1012,6 +1020,12 @@ void CacheReader_free(CacheReader *reader)
        }
 }
 
+void CacheReader_incref(CacheReader *reader)
+{
+       AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
+       abc_reader->incref();
+}
+
 CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
 {
        if (object_path[0] == '\0') {
index 58ad171ee207f0bed967e960634e7accdd4edd06..9bc1ce16284777f94c66cb95831d098a2d1aec91 100644 (file)
@@ -4387,19 +4387,17 @@ static void transformcache_copy(bConstraint *con, bConstraint *srccon)
        BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path));
        dst->cache_file = src->cache_file;
 
-       if (dst->cache_file) {
-               id_us_plus(&dst->cache_file->id);
+#ifdef WITH_ALEMBIC
+       if (dst->reader) {
+               CacheReader_incref(dst->reader);
        }
+#endif
 }
 
 static void transformcache_free(bConstraint *con)
 {
        bTransformCacheConstraint *data = con->data;
 
-       if (data->cache_file) {
-               id_us_min(&data->cache_file->id);
-       }
-
        if (data->reader) {
 #ifdef WITH_ALEMBIC
                CacheReader_free(data->reader);
index e6fe8102b4fae537c71f2e0f2f2d24702b8a5cf4..a353c94ae64d8b87a9feb2b0fbb2197a69455ee2 100644 (file)
@@ -47,10 +47,12 @@ enum {
        CACHEFILE_KEYFRAME_DRAWN = (1 << 0),
 };
 
+/* Representation of an object's path inside the Alembic file.
+ * Note that this is not a file path. */
 typedef struct AlembicObjectPath {
        struct AlembicObjectPath *next, *prev;
 
-       char path[4096];  /* 4096 = PATH_MAX */
+       char path[4096];
 } AlembicObjectPath;
 
 typedef struct CacheFile {
@@ -64,7 +66,7 @@ typedef struct CacheFile {
         * CacheFile. */
        ListBase object_paths;
 
-       char filepath[4096];  /* 4096 = PATH_MAX */
+       char filepath[1024];  /* 1024 = FILE_MAX */
 
        char is_sequence;
        char forward_axis;
index e83d38aec63cdb9c6e07ae30760b2be976c4b0f6..854a5846361d3fbd088d9ee9341188216a230e3d 100644 (file)
@@ -85,7 +85,7 @@ class SimpleImportTest(unittest.TestCase):
         for ob in bpy.data.objects:
             self.assertEqual('Cube' in ob.name, ob.select_get())
 
-    def test_change_path(self):
+    def test_change_path_constraint(self):
         import math
 
         fname = 'cube-rotating1.abc'
@@ -122,6 +122,32 @@ class SimpleImportTest(unittest.TestCase):
         self.assertAlmostEqual(y, 0)
         self.assertAlmostEqual(z, 0)
 
+    def test_change_path_modifier(self):
+        import math
+
+        fname = 'animated-mesh.abc'
+        abc = self.testdir / fname
+        relpath = bpy.path.relpath(str(abc))
+
+        res = bpy.ops.wm.alembic_import(filepath=str(abc), as_background_job=False)
+        self.assertEqual({'FINISHED'}, res)
+        cube = bpy.context.active_object
+
+        # Check that the file loaded ok.
+        bpy.context.scene.frame_set(6)
+        self.assertAlmostEqual(-1, cube.data.vertices[0].co.x)
+        self.assertAlmostEqual(-1, cube.data.vertices[0].co.y)
+        self.assertAlmostEqual(0.5905638933181763, cube.data.vertices[0].co.z)
+
+        # Change path from absolute to relative. This should not break the animation.
+        bpy.context.scene.frame_set(1)
+        bpy.data.cache_files[fname].filepath = relpath
+        bpy.context.scene.frame_set(6)
+
+        self.assertAlmostEqual(1, cube.data.vertices[3].co.x)
+        self.assertAlmostEqual(1, cube.data.vertices[3].co.y)
+        self.assertAlmostEqual(0.5905638933181763, cube.data.vertices[3].co.z)
+
     def test_import_long_names(self):
         # This file contains very long names. The longest name is 4047 chars.
         bpy.ops.wm.alembic_import(