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

1  2 
source/blender/alembic/intern/abc_exporter.cc
source/blender/alembic/intern/abc_object.cc
source/blender/alembic/intern/alembic_capi.cc
tests/python/bl_alembic_import_test.py

index dd65613e2232ff985f0aac07c96c3935d70a1a73,11c63461ab40dfe671ea61082c2b8e70f5c48118..2c2d0b598e92b8683d0ca3540bbdb7d4b2d9952b
@@@ -108,7 -108,7 +108,7 @@@ static bool object_is_smoke_sim(Object 
        return false;
  }
  
- static bool object_is_shape(Object *ob)
+ static bool object_type_is_exportable(Object *ob)
  {
        switch (ob->type) {
                case OB_MESH:
                        }
  
                        return true;
+               case OB_EMPTY:
                case OB_CURVE:
                case OB_SURF:
                case OB_CAMERA:
   * Returns whether this object should be exported into the Alembic file.
   *
   * @param settings export settings, used for options like 'selected only'.
 - * @param ob the object in question.
 + * @param ob the object's base in question.
   * @param is_duplicated normally false; true when the object is instanced
   *                      into the scene by a dupli-object (e.g. part of a
   *                      dupligroup). This ignores selection and layer
   *                      visibility, and assumes that the dupli-object itself
   *                      (e.g. the group-instantiating empty) is exported.
   */
 -static bool export_object(const ExportSettings * const settings, Object *ob,
 +static bool export_object(const ExportSettings * const settings, const Base * const ob_base,
                            bool is_duplicated)
  {
        if (!is_duplicated) {
                /* These two tests only make sense when the object isn't being instanced
                 * into the scene. When it is, its exportability is determined by
                 * its dupli-object and the DupliObject::no_draw property. */
 -              if (settings->selected_only && !parent_selected(ob)) {
 +              if (settings->selected_only && !object_selected(ob_base)) {
                        return false;
                }
 -
 -              if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
 +              // FIXME Sybren: handle these cleanly (maybe just remove code), now using active scene layer instead.
 +              if (settings->visible_layers_only && (ob_base->flag & BASE_VISIBLED) == 0) {
                        return false;
                }
        }
  
 -      if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
 -              return false;
 -      }
 +      //      if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
 +      //              return false;
 +      //      }
  
        return true;
  }
@@@ -358,45 -359,42 +359,45 @@@ void AbcExporter::operator()(Main *bmai
  
  void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
  {
 -      Base *base = static_cast<Base *>(m_scene->base.first);
 -
 -      while (base) {
 +      for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
                Object *ob = base->object;
  
 -              switch (ob->type) {
 -                      case OB_LAMP:
 -                      case OB_LATTICE:
 -                      case OB_MBALL:
 -                      case OB_SPEAKER:
 -                              /* We do not export transforms for objects of these classes. */
 -                              break;
 -
 -                      default:
 -                              exploreTransform(eval_ctx, ob, ob->parent);
 +              if (export_object(&m_settings, base, false)) {
 +                      switch (ob->type) {
 +                              case OB_LAMP:
 +                              case OB_LATTICE:
 +                              case OB_MBALL:
 +                              case OB_SPEAKER:
 +                                      /* We do not export transforms for objects of these classes. */
 +                                      break;
 +
 +                              default:
 +                                      exploreTransform(eval_ctx, base, ob->parent, NULL);
 +                      }
                }
 -
 -              base = base->next;
        }
  }
  
 -void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
 +void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Base *ob_base, Object *parent, Object *dupliObParent)
  {
 +      Object *ob = ob_base->object;
 +
        /* If an object isn't exported itself, its duplilist shouldn't be
         * exported either. */
 -      if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
 +      if (!export_object(&m_settings, ob_base, dupliObParent != NULL)) {
                return;
        }
  
-       if (object_is_shape(ob)) {
+       if (object_type_is_exportable(ob)) {
                createTransformWriter(ob, parent, dupliObParent);
        }
  
        ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
  
        if (lb) {
 +              Base fake_base = *ob_base;  // copy flags (like selection state) from the real object.
 +              fake_base.next = fake_base.prev = NULL;
 +
                DupliObject *link = static_cast<DupliObject *>(lb->first);
                Object *dupli_ob = NULL;
                Object *dupli_parent = NULL;
                                dupli_ob = link->ob;
                                dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
  
 -                              exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob);
 +                              fake_base.object = dupli_ob;
 +                              exploreTransform(eval_ctx, &fake_base, dupli_parent, ob);
                        }
                }
        }
@@@ -491,28 -488,29 +492,28 @@@ AbcTransformWriter * AbcExporter::creat
  
  void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
  {
 -      Base *base = static_cast<Base *>(m_scene->base.first);
 -
 -      while (base) {
 -              Object *ob = base->object;
 -              exploreObject(eval_ctx, ob, NULL);
 -
 -              base = base->next;
 +      for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
 +              exploreObject(eval_ctx, base, NULL);
        }
  }
  
 -void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent)
 +void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent)
  {
        /* If an object isn't exported itself, its duplilist shouldn't be
         * exported either. */
 -      if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
 +      if (!export_object(&m_settings, ob_base, dupliObParent != NULL)) {
                return;
        }
  
 -      createShapeWriter(ob, dupliObParent);
 +      createShapeWriter(ob_base, dupliObParent);
        
 +      Object *ob = ob_base->object;
        ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
  
        if (lb) {
 +              Base fake_base = *ob_base;  // copy flags (like selection state) from the real object.
 +              fake_base.next = fake_base.prev = NULL;
 +
                DupliObject *link = static_cast<DupliObject *>(lb->first);
  
                for (; link; link = link->next) {
                        if (m_settings.renderable_only && link->no_draw) {
                                continue;
                        }
 -
                        if (link->type == OB_DUPLIGROUP) {
 -                              exploreObject(eval_ctx, link->ob, ob);
 +                              fake_base.object = link->ob;
 +                              exploreObject(eval_ctx, &fake_base, ob);
                        }
                }
        }
@@@ -553,11 -551,9 +554,11 @@@ void AbcExporter::createParticleSystems
        }
  }
  
 -void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
 +void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
  {
-       if (!object_is_shape(ob)) {
 +      Object *ob = ob_base->object;
 +
+       if (!object_type_is_exportable(ob)) {
                return;
        }
  
@@@ -641,5 -637,5 +642,5 @@@ void AbcExporter::setCurrentFrame(Main 
  {
        m_scene->r.cfra = static_cast<int>(t);
        m_scene->r.subframe = static_cast<float>(t) - m_scene->r.cfra;
 -      BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene, m_scene->lay);
 +      BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene);
  }
index ce0f9225228666aef3b1995eb44918725f4ab40a,94ec77f4191d7f47d1b272334a4c3ce6b07b417a..28a4d1850148654623742e1d4a4d534d2c7fff6a
@@@ -32,6 -32,7 +32,6 @@@ extern "C" 
  #include "DNA_space_types.h"  /* for FILE_MAX */
  
  #include "BKE_constraint.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_idprop.h"
  #include "BKE_library.h"
  #include "BKE_modifier.h"
@@@ -369,4 -370,5 +369,5 @@@ void AbcObjectReader::incref(
  void AbcObjectReader::decref()
  {
        --m_refcount;
+       BLI_assert(m_refcount >= 0);
  }
index 4aa4b8d548fea6cf2e3ccf1cfd2440e5dc03da75,7536a4a4fa63ad4b634312170aaf2fc6bb4137dd..61b18c7112fec47cdaea395d102eb29903b2d952
@@@ -48,15 -48,12 +48,15 @@@ extern "C" 
  #include "BKE_cdderivedmesh.h"
  #include "BKE_context.h"
  #include "BKE_curve.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_global.h"
 +#include "BKE_layer.h"
  #include "BKE_library.h"
  #include "BKE_main.h"
  #include "BKE_scene.h"
  
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_build.h"
 +
  /* SpaceType struct has a member called 'new' which obviously conflicts with C++
   * so temporarily redefining the new keyword to make it compile. */
  #define new extern_new
@@@ -175,7 -172,7 +175,7 @@@ static bool gather_objects_paths(const 
                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);
        }
  
@@@ -272,7 -269,8 +272,7 @@@ static void export_startjob(void *custo
                if (CFRA != orig_frame) {
                        CFRA = orig_frame;
  
 -                      BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain,
 -                                                    scene, scene->lay);
 +                      BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain, scene);
                }
  
                data->export_ok = !data->was_canceled;
@@@ -332,24 -330,13 +332,24 @@@ bool ABC_export
         * hardcore refactoring. */
        new (&job->settings) ExportSettings();
        job->settings.scene = job->scene;
 +
 +      /* Sybren: for now we only export the active scene layer.
 +       * Later in the 2.8 development process this may be replaced by using
 +       * a specific collection for Alembic I/O, which can then be toggled
 +       * between "real" objects and cached Alembic files. */
 +      job->settings.sl = CTX_data_scene_layer(C);
 +
        job->settings.frame_start = params->frame_start;
        job->settings.frame_end = params->frame_end;
        job->settings.frame_step_xform = params->frame_step_xform;
        job->settings.frame_step_shape = params->frame_step_shape;
        job->settings.shutter_open = params->shutter_open;
        job->settings.shutter_close = params->shutter_close;
 +
 +      /* Sybren: For now this is ignored, until we can get selection
 +       * detection working through Base pointers (instead of ob->flags). */
        job->settings.selected_only = params->selected_only;
 +
        job->settings.export_face_sets = params->face_sets;
        job->settings.export_normals = params->normals;
        job->settings.export_uvs = params->uvs;
        job->settings.export_particles = params->export_particles;
        job->settings.apply_subdiv = params->apply_subdiv;
        job->settings.flatten_hierarchy = params->flatten_hierarchy;
 +
 +      /* Sybren: visible_layer & renderable only is ignored for now,
 +       * to be replaced with collections later in the 2.8 dev process
 +       * (also see note above). */
        job->settings.visible_layers_only = params->visible_layers_only;
        job->settings.renderable_only = params->renderable_only;
 +
        job->settings.use_subdiv_schema = params->use_subdiv_schema;
        job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA);
        job->settings.pack_uv = params->packuv;
                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),
  
                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 -546,7 +564,7 @@@ static std::pair<bool, AbcObjectReader 
  
                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. */
@@@ -619,7 -605,6 +623,7 @@@ enum 
  struct ImportJobData {
        Main *bmain;
        Scene *scene;
 +      SceneLayer *scene_layer;
  
        char filename[1024];
        ImportSettings settings;
@@@ -820,32 -805,20 +824,32 @@@ static void import_endjob(void *user_da
        else {
                /* Add object to scene. */
                Base *base;
 +              LayerCollection *lc;
 +              SceneLayer *sl = data->scene_layer;
  
 -              BKE_scene_base_deselect_all(data->scene);
 +              BKE_scene_layer_base_deselect_all(sl);
 +
 +              lc = BKE_layer_collection_active(sl);
 +              if (lc == NULL) {
 +                      BLI_assert(BLI_listbase_count_ex(&sl->layer_collections, 1) == 0);
 +                      /* when there is no collection linked to this SceneLayer, create one */
 +                      SceneCollection *sc = BKE_collection_add(data->scene, NULL, NULL);
 +                      lc = BKE_collection_link(sl, sc);
 +              }
  
                for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
                        Object *ob = (*iter)->object();
                        ob->lay = data->scene->lay;
  
 -                      base = BKE_scene_base_add(data->scene, ob);
 -                      BKE_scene_base_select(data->scene, base);
 +                      BKE_collection_object_add(data->scene, lc->scene_collection, ob);
 +
 +                      base = BKE_scene_layer_base_find(sl, ob);
 +                      BKE_scene_layer_base_select(sl, base);
  
 -                      DAG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
 +                      DEG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                }
  
 -              DAG_relations_tag_update(data->bmain);
 +              DEG_relations_tag_update(data->bmain);
        }
  
        for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
@@@ -888,7 -861,6 +892,7 @@@ bool ABC_import(bContext *C, const cha
        ImportJobData *job = new ImportJobData();
        job->bmain = CTX_data_main(C);
        job->scene = CTX_data_scene(C);
 +      job->scene_layer = CTX_data_scene_layer(C);
        job->import_ok = false;
        BLI_strncpy(job->filename, filepath, 1024);
  
  
        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);
  
                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 -988,12 +1020,12 @@@ void CacheReader_free(CacheReader *read
        }
  }
  
+ 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 e83d38aec63cdb9c6e07ae30760b2be976c4b0f6,ef5ae37233372fd4db183c92cee9a8d52212047f..854a5846361d3fbd088d9ee9341188216a230e3d
@@@ -51,7 -51,7 +51,7 @@@ class SimpleImportTest(unittest.TestCas
  
          # The objects should be linked to scene_collection in Blender 2.8,
          # and to scene in Blender 2.7x.
 -        objects = bpy.context.scene.objects
 +        objects = bpy.context.scene_collection.objects
          self.assertEqual(13, len(objects))
  
          # Test the hierarchy.
@@@ -83,9 -83,9 +83,9 @@@
  
          # All cubes should be selected, but the sphere shouldn't be.
          for ob in bpy.data.objects:
 -            self.assertEqual('Cube' in ob.name, ob.select)
 +            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'
          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(