Alembic export: added support for writing dupli-groups
authorSybren A. Stüvel <sybren@stuvel.eu>
Wed, 12 Apr 2017 10:35:09 +0000 (12:35 +0200)
committerSybren A. Stüvel <sybren@stuvel.eu>
Thu, 13 Apr 2017 14:34:37 +0000 (16:34 +0200)
This supports our common character animation workflow, where a character,
its rig, and the custom bone shapes are all part of a group. This group
is then linked into the scene, the rig is proxified and animated. Such
a group can now be exported. Use "Renderable objects only" to prevent
writing the custom bone shapes to the Alembic file.

source/blender/alembic/intern/abc_exporter.cc

index 39896529c97092cb44246a04243d858dd0bc1dc3..c58aedd65037779e17de6e14681fbb1e51c2ba80 100644 (file)
@@ -124,14 +124,32 @@ static bool object_is_shape(Object *ob)
        }
 }
 
-static bool export_object(const ExportSettings * const settings, Object *ob)
+
+/**
+ * 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 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,
+                          bool is_duplicated)
 {
-       if (settings->selected_only && !parent_selected(ob)) {
-               return false;
-       }
+       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)) {
+                       return false;
+               }
 
-       if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
-               return false;
+               if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) {
+                       return false;
+               }
        }
 
        if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
@@ -372,7 +390,7 @@ void AbcExporter::createTransformWritersFlat()
        while (base) {
                Object *ob = base->object;
 
-               if (export_object(&m_settings, ob) && object_is_shape(ob)) {
+               if (export_object(&m_settings, ob, false) && object_is_shape(ob)) {
                        std::string name = get_id_name(ob);
                        m_xforms[name] = new AbcTransformWriter(
                                             ob, m_writer->archive().getTop(), NULL,
@@ -385,8 +403,13 @@ void AbcExporter::createTransformWritersFlat()
 
 void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
 {
+       /* If an object isn't exported itself, its duplilist shouldn't be
+        * exported either. */
+       if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+               return;
+       }
 
-       if (export_object(&m_settings, ob) && object_is_shape(ob)) {
+       if (object_is_shape(ob)) {
                createTransformWriter(ob, parent, dupliObParent);
        }
 
@@ -397,15 +420,18 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje
                Object *dupli_ob = NULL;
                Object *dupli_parent = NULL;
                
-               while (link) {
+               for (; link; link = link->next) {
+                       /* This skips things like custom bone shapes. */
+                       if (m_settings.renderable_only && link->no_draw) {
+                               continue;
+                       }
+
                        if (link->type == OB_DUPLIGROUP) {
                                dupli_ob = link->ob;
                                dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
 
                                exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob);
                        }
-
-                       link = link->next;
                }
        }
 
@@ -478,14 +504,26 @@ void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
 
 void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent)
 {
-       ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
-       
+       /* If an object isn't exported itself, its duplilist shouldn't be
+        * exported either. */
+       if (!export_object(&m_settings, ob, dupliObParent != NULL)) {
+               return;
+       }
+
        createShapeWriter(ob, dupliObParent);
        
+       ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
+
        if (lb) {
                DupliObject *dupliob = static_cast<DupliObject *>(lb->first);
 
                while (dupliob) {
+                       /* This skips things like custom bone shapes. */
+                       if (m_settings.renderable_only && dupliob->no_draw) {
+                               dupliob = dupliob->next;
+                               continue;
+                       }
+
                        if (dupliob->type == OB_DUPLIGROUP) {
                                exploreObject(eval_ctx, dupliob->ob, ob);
                        }
@@ -503,10 +541,6 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
                return;
        }
 
-       if (!export_object(&m_settings, ob)) {
-               return;
-       }
-
        std::string name;
 
        if (m_settings.flatten_hierarchy) {