Index: source/blender/collada/GeometryExporter.cpp =================================================================== --- source/blender/collada/GeometryExporter.cpp (revision 47586) +++ source/blender/collada/GeometryExporter.cpp (working copy) @@ -61,7 +61,7 @@ mScene = sce; GeometryFunctor gf; - gf.forEachMeshObjectInScene(sce, *this, this->export_settings->selected); + gf.forEachMeshObjectInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/SceneExporter.cpp =================================================================== --- source/blender/collada/SceneExporter.cpp (revision 47586) +++ source/blender/collada/SceneExporter.cpp (working copy) @@ -26,6 +26,7 @@ #include "SceneExporter.h" #include "collada_utils.h" +#include "BKE_object.h" SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings) @@ -41,112 +42,74 @@ closeLibrary(); } -// Returns true if the parent chain does not contain any selected object -// Otherwise return false (ob has selected predecessor) -bool is_exported_base_node(Object *ob, bool selection_only) { - - if (selection_only && ob->flag & SELECT) { - // Move up towards root object, - // stop at first selected predecessor's child, - // or at root, if no parent was selected - while (ob->parent && (ob->parent->type==OB_ARMATURE || !(ob->parent->flag & SELECT))) - { - ob = ob->parent; - } - } - - return !ob->parent; -} - void SceneExporter::exportHierarchy(Scene *sce) -{ - Base *base= (Base*) sce->base.first; - while (base) { - Object *ob = base->object; - - bool is_export_base_node = is_exported_base_node(ob, this->export_settings->selected); - if (is_export_base_node) { - if (sce->lay & ob->lay) { - switch (ob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - if (this->export_settings->selected && !(ob->flag & SELECT)) { - break; - } - // write nodes.... +{ + LinkNode *node = this->export_settings->export_set; + while (node) { + Object *ob = (Object*) node->link; + if (bc_is_base_node(this->export_settings->export_set, ob)) { + switch (ob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_ARMATURE: + if (bc_is_marked(ob)) { + bc_remove_mark(ob); writeNodes(ob, sce); - break; - } + } + break; } } - - base= base->next; + node= node->next; } } void SceneExporter::writeNodes(Object *ob, Scene *sce) { - // Add associated armature first if available - if (this->export_settings->include_armatures) { - Object *ob_arm = bc_get_assigned_armature(ob); - if(ob_arm != NULL) - writeNodes(ob_arm, sce); + Object *ob_arm = bc_get_assigned_armature(ob); + if(ob_arm != NULL && bc_is_marked(ob_arm)) { + bc_remove_mark(ob_arm); + writeNodes(ob_arm, sce); } - COLLADASW::Node node(mSW); - node.setNodeId(translate_id(id_name(ob))); - node.setNodeName(translate_id(id_name(ob))); - node.setType(COLLADASW::Node::NODE); + COLLADASW::Node colladaNode(mSW); + colladaNode.setNodeId(translate_id(id_name(ob))); + colladaNode.setNodeName(translate_id(id_name(ob))); + colladaNode.setType(COLLADASW::Node::NODE); - node.start(); + colladaNode.start(); bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob); std::list child_objects; - // XXX Not sure about this. - // For me this looks more like a very special case for a very special purpose. - // Wouldn't it be better to have only one option here ? - // - // - include children - // - // Instead of "include_bone_children" ? - // then we could just ask: - // if (this->export_settings->include_children) - // ... - if (this->export_settings->include_armatures - && this->export_settings->include_bone_children) { + // list child objects + LinkNode *node = this->export_settings->export_set ; + while (node) { + // cob - child object + Object *cob = (Object *)node->link; - // list child objects - Base *b = (Base*) sce->base.first; - while (b) { - // cob - child object - Object *cob = b->object; - - if (cob->parent == ob) { - switch (cob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - case OB_ARMATURE: + if (cob->parent == ob) { + switch (cob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_ARMATURE: + if (bc_is_marked(cob)) child_objects.push_back(cob); - break; - } + break; } - - b = b->next; } + node = node->next; } - if (ob->type == OB_MESH && this->export_settings->include_armatures && is_skinned_mesh) // for skinned mesh we write obmat in - TransformWriter::add_node_transform_identity(node); + TransformWriter::add_node_transform_identity(colladaNode); else - TransformWriter::add_node_transform_ob(node, ob); + TransformWriter::add_node_transform_ob(colladaNode, ob); // if (ob->type == OB_MESH) { @@ -167,9 +130,6 @@ // else if (ob->type == OB_ARMATURE) { arm_exporter->add_armature_bones(ob, sce, this, child_objects); - - // XXX this looks unstable... - node.end(); } // @@ -196,12 +156,19 @@ } } + if (ob->type == OB_ARMATURE) { + colladaNode.end(); + } + for (std::list::iterator i= child_objects.begin(); i != child_objects.end(); ++i) { - writeNodes(*i, sce); + if(bc_is_marked(*i)) { + bc_remove_mark(*i); + writeNodes(*i, sce); + } } - - if (ob->type != OB_ARMATURE) - node.end(); + if (ob->type != OB_ARMATURE) { + colladaNode.end(); + } } Index: source/blender/collada/LightExporter.cpp =================================================================== --- source/blender/collada/LightExporter.cpp (revision 47586) +++ source/blender/collada/LightExporter.cpp (working copy) @@ -36,16 +36,16 @@ #include "collada_internal.h" template -void forEachLampObjectInScene(Scene *sce, Functor &f, bool export_selected) +void forEachLampObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - Base *base= (Base*) sce->base.first; - while (base) { - Object *ob = base->object; + LinkNode *node = export_set; + while (node) { + Object *ob = (Object *)node->link; - if (ob->type == OB_LAMP && ob->data && !(export_selected && !(ob->flag & SELECT))) { + if (ob->type == OB_LAMP && ob->data) { f(ob); } - base= base->next; + node= node->next; } } @@ -55,7 +55,7 @@ { openLibrary(); - forEachLampObjectInScene(sce, *this, this->export_settings->selected); + forEachLampObjectInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/collada_internal.h =================================================================== --- source/blender/collada/collada_internal.h (revision 47586) +++ source/blender/collada/collada_internal.h (working copy) @@ -39,6 +39,8 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BLI_math.h" +#include "BLI_math.h" +#include "BLI_linklist.h" class UnitConverter { @@ -96,6 +98,4 @@ extern std::string get_material_id(Material *mat); -extern bool has_object_type(Scene* sce, short obtype); - #endif /* __COLLADA_INTERNAL_H__ */ Index: source/blender/collada/DocumentExporter.cpp =================================================================== --- source/blender/collada/DocumentExporter.cpp (revision 47586) +++ source/blender/collada/DocumentExporter.cpp (working copy) @@ -108,8 +108,9 @@ #include "collada_internal.h" #include "DocumentExporter.h" -#include "ExportSettings.h" +extern bool bc_has_object_type(LinkNode *export_set, short obtype); + // can probably go after refactor is complete #include "InstanceWriter.h" #include "TransformWriter.h" @@ -226,14 +227,15 @@ asset.getContributor().mAuthoringTool = version_buf; asset.add(); + LinkNode *export_set = this->export_settings->export_set; // - if (has_object_type(sce, OB_CAMERA)) { + if (bc_has_object_type(export_set, OB_CAMERA)) { CamerasExporter ce(&sw, this->export_settings); ce.exportCameras(sce); } // - if (has_object_type(sce, OB_LAMP)) { + if (bc_has_object_type(export_set, OB_LAMP)) { LightsExporter le(&sw, this->export_settings); le.exportLights(sce); } @@ -251,7 +253,7 @@ me.exportMaterials(sce); // - if (has_object_type(sce, OB_MESH)) { + if (bc_has_object_type(export_set, OB_MESH)) { GeometryExporter ge(&sw, this->export_settings); ge.exportGeom(sce); } @@ -262,10 +264,8 @@ // ArmatureExporter arm_exporter(&sw, this->export_settings); - if (this->export_settings->include_armatures) { - if (has_object_type(sce, OB_ARMATURE)) { - arm_exporter.export_controllers(sce); - } + if (bc_has_object_type(export_set, OB_ARMATURE)) { + arm_exporter.export_controllers(sce); } // Index: source/blender/collada/ArmatureExporter.cpp =================================================================== --- source/blender/collada/ArmatureExporter.cpp (revision 47586) +++ source/blender/collada/ArmatureExporter.cpp (working copy) @@ -112,7 +112,7 @@ openLibrary(); GeometryFunctor gf; - gf.forEachMeshObjectInScene(sce, *this, this->export_settings->selected); + gf.forEachMeshObjectInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/CameraExporter.cpp =================================================================== --- source/blender/collada/CameraExporter.cpp (revision 47586) +++ source/blender/collada/CameraExporter.cpp (working copy) @@ -29,7 +29,6 @@ #include #include "COLLADASWCamera.h" -#include "COLLADASWCameraOptic.h" #include "DNA_camera_types.h" @@ -40,16 +39,16 @@ CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings): COLLADASW::LibraryCameras(sw), export_settings(export_settings) {} template -void forEachCameraObjectInScene(Scene *sce, Functor &f, bool export_selected) +void forEachCameraObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - Base *base = (Base*) sce->base.first; - while (base) { - Object *ob = base->object; + LinkNode *node = export_set; + while (node) { + Object *ob = (Object *)node->link; - if (ob->type == OB_CAMERA && ob->data && !(export_selected && !(ob->flag & SELECT))) { + if (ob->type == OB_CAMERA && ob->data) { f(ob, sce); } - base = base->next; + node = node->next; } } @@ -57,7 +56,7 @@ { openLibrary(); - forEachCameraObjectInScene(sce, *this, this->export_settings->selected); + forEachCameraObjectInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/DocumentExporter.h =================================================================== --- source/blender/collada/DocumentExporter.h (revision 47586) +++ source/blender/collada/DocumentExporter.h (working copy) @@ -28,6 +28,7 @@ #define __DOCUMENTEXPORTER_H__ #include "ExportSettings.h" +#include "DNA_customdata_types.h" struct Scene; Index: source/blender/collada/collada_utils.cpp =================================================================== --- source/blender/collada/collada_utils.cpp (revision 47586) +++ source/blender/collada/collada_utils.cpp (working copy) @@ -32,6 +32,8 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" +#include "collada_utils.h" + #include "DNA_modifier_types.h" #include "DNA_customdata_types.h" #include "DNA_object_types.h" @@ -49,6 +51,7 @@ extern "C" { #include "BKE_DerivedMesh.h" +#include "BLI_linklist.h" } #include "WM_api.h" // XXX hrm, see if we can do without this @@ -164,3 +167,102 @@ return ob_arm; } +// Returns the highest selected ancestor +// returns NULL if no ancestor is selected +Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob) +{ + Object *ancestor = ob; + while (ob->parent && bc_is_in_Export_set(export_set, ob->parent)) + { + ob = ob->parent; + ancestor = ob; + } + return ancestor; +} + +bool bc_is_base_node(LinkNode *export_set, Object *ob) +{ + Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob); + return (root == ob); +} + +bool bc_is_in_Export_set(LinkNode *export_set, Object *ob) +{ + LinkNode *node = export_set; + + while (node) { + Object *element = (Object *)node->link; + + if (element == ob) + return true; + + node= node->next; + } + return false; +} + +bool bc_has_object_type(LinkNode *export_set, short obtype) +{ + LinkNode *node = export_set; + + while (node) { + Object *ob = (Object *)node->link; + + if (ob->type == obtype && ob->data) { + return true; + } + node= node->next; + } + return false; +} + +int bc_is_marked(Object *ob) +{ + return ob && (ob->id.flag & LIB_DOIT); +} + +void bc_remove_mark(Object *ob) +{ + ob->id.flag &= ~LIB_DOIT; +} + + + +// Return the list of exported Objects +// for baseSet == BC_EXP_ALL returns a list with all objects of the scene. +// for baseSet == BC_EXP_SELECTED returns selected objects plus related according to includeFilter +// for baseSet == BC_EXP_VISIBLE we still need the implementation +LinkNode *bc_get_export_set(Scene *sce, const ExportSettings *export_settings) +{ + int includeFilter = 0; + exportSet baseSet; + LinkNode *export_set = NULL; + + baseSet = (export_settings->selected) ? BC_EXP_SELECTED : BC_EXP_ALL; + includeFilter; + if (export_settings->include_armatures) includeFilter |= OB_REL_MOD_ARMATURE; + if (export_settings->include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE; + + switch(baseSet) + { + case BC_EXP_SELECTED: + export_set = BKE_object_relational_superset(sce, includeFilter); + break; + + default: + { + Base *base; + for (base = (Base *)sce->base.first; base; base = base->next) { + BLI_linklist_prepend(&export_set, base->object); + } + } + break; + } + return export_set; +} + +// Return a previous created list of linkNodes +void bc_release_export_set(LinkNode*export_set) +{ + BLI_linklist_free(export_set, NULL); +} Index: source/blender/collada/MaterialExporter.cpp =================================================================== --- source/blender/collada/MaterialExporter.cpp (revision 47586) +++ source/blender/collada/MaterialExporter.cpp (working copy) @@ -39,7 +39,7 @@ openLibrary(); MaterialFunctor mf; - mf.forEachMaterialInScene(sce, *this, this->export_settings->selected); + mf.forEachMaterialInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/collada.cpp =================================================================== --- source/blender/collada/collada.cpp (revision 47586) +++ source/blender/collada/collada.cpp (working copy) @@ -56,20 +56,12 @@ int apply_modifiers, int include_armatures, - int include_bone_children, + int include_children, int use_object_instantiation, int second_life ) { ExportSettings export_settings; - - export_settings.selected = selected != 0; - export_settings.apply_modifiers = apply_modifiers != 0; - export_settings.include_armatures = include_armatures != 0; - export_settings.include_bone_children = include_bone_children != 0; - export_settings.second_life = second_life != 0; - export_settings.use_object_instantiation = use_object_instantiation != 0; - export_settings.filepath = (char *)filepath; /* annoying, collada crashes if file cant be created! [#27162] */ if (!BLI_exists(filepath)) { @@ -80,9 +72,21 @@ } /* end! */ + + export_settings.selected = selected != 0; + export_settings.apply_modifiers = apply_modifiers != 0; + export_settings.include_armatures = include_armatures != 0; + export_settings.include_children = include_children != 0; + export_settings.second_life = second_life != 0; + export_settings.use_object_instantiation = use_object_instantiation != 0; + export_settings.filepath = (char *)filepath; + export_settings.export_set = bc_get_export_set(sce, &export_settings); + DocumentExporter exporter(&export_settings); exporter.exportCurrentScene(sce); + bc_release_export_set(export_settings.export_set); + return 1; } } Index: source/blender/collada/AnimationExporter.cpp =================================================================== --- source/blender/collada/AnimationExporter.cpp (revision 47586) +++ source/blender/collada/AnimationExporter.cpp (working copy) @@ -25,16 +25,16 @@ #include "MaterialExporter.h" template -void forEachObjectInScene(Scene *sce, Functor &f) +void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - Base *base= (Base*) sce->base.first; + LinkNode *node = export_set; - while (base) { - Object *ob = base->object; + while (node) { + Object *ob = (Object *)node->link; f(ob); - base= base->next; + node= node->next; } } @@ -45,7 +45,7 @@ openLibrary(); - forEachObjectInScene(sce, *this); + forEachObjectInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/ImageExporter.cpp =================================================================== --- source/blender/collada/ImageExporter.cpp (revision 47586) +++ source/blender/collada/ImageExporter.cpp (working copy) @@ -73,7 +73,7 @@ if (hasImages(sce)) { openLibrary(); MaterialFunctor mf; - mf.forEachMaterialInScene(sce, *this, this->export_settings->selected); + mf.forEachMaterialInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/collada_utils.h =================================================================== --- source/blender/collada/collada_utils.h (revision 47586) +++ source/blender/collada/collada_utils.h (working copy) @@ -40,18 +40,44 @@ #include "DNA_customdata_types.h" #include "DNA_texture_types.h" #include "BKE_context.h" +#include "BKE_object.h" + #include "DNA_scene_types.h" +extern "C" { +#include "BKE_DerivedMesh.h" +#include "BLI_linklist.h" +} + +#include "ExportSettings.h" + typedef std::map > TexIndexTextureArrayMap; +typedef enum exportSet { + BC_EXP_SELECTED, /* Selected Objects */ + BC_EXP_VISIBLE, /* Visible Objects (not implemented) */ + BC_EXP_ALL /* All Objects */ +} exportSet; + extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index); - extern int bc_test_parent_loop(Object *par, Object *ob); extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space=true); -extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); -extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); extern Object *bc_add_object(Scene *scene, int type, const char *name); extern Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob); + extern Object *bc_get_assigned_armature(Object *ob); +extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob); +extern bool bc_is_base_node(LinkNode *export_set, Object *ob); +extern bool bc_is_in_Export_set(LinkNode *export_set, Object *ob); +extern bool bc_has_object_type(LinkNode *export_set, short obtype); +extern int bc_is_marked(Object *ob); +extern void bc_remove_mark(Object *ob); + +extern LinkNode *bc_get_export_set(Scene *sce, const ExportSettings *export_settings); +extern void bc_release_export_set(LinkNode*export_set); + +extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); +extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); + #endif Index: source/blender/collada/EffectExporter.cpp =================================================================== --- source/blender/collada/EffectExporter.cpp (revision 47586) +++ source/blender/collada/EffectExporter.cpp (working copy) @@ -31,6 +31,7 @@ #include "COLLADASWEffectProfile.h" #include "EffectExporter.h" +#include "DocumentExporter.h" #include "MaterialExporter.h" #include "DNA_mesh_types.h" @@ -82,7 +83,7 @@ this->scene = sce; openLibrary(); MaterialFunctor mf; - mf.forEachMaterialInScene(sce, *this, this->export_settings->selected); + mf.forEachMaterialInExportSet(sce, *this, this->export_settings->export_set); closeLibrary(); } Index: source/blender/collada/GeometryExporter.h =================================================================== --- source/blender/collada/GeometryExporter.h (revision 47586) +++ source/blender/collada/GeometryExporter.h (working copy) @@ -42,6 +42,8 @@ #include "ExportSettings.h" +extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob); + // TODO: optimize UV sets by making indexed list with duplicates removed class GeometryExporter : COLLADASW::LibraryGeometries { @@ -112,21 +114,17 @@ // f should have // void operator()(Object* ob) template - void forEachMeshObjectInScene(Scene *sce, Functor &f, bool export_selected) + void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { - Base *base= (Base*) sce->base.first; - while (base) { - Object *ob = base->object; - - if (ob->type == OB_MESH && ob->data && - !(export_selected && !(ob->flag & SELECT)) && - ((sce->lay & ob->lay)!=0)) + LinkNode *node= export_set; + while (node) { + Object *ob = (Object *)node->link; + if (ob->type == OB_MESH) { f(ob); } - base= base->next; - + node = node->next; } } }; Index: source/blender/collada/collada_internal.cpp =================================================================== --- source/blender/collada/collada_internal.cpp (revision 47586) +++ source/blender/collada/collada_internal.cpp (working copy) @@ -27,9 +27,10 @@ /* COLLADABU_ASSERT, may be able to remove later */ #include "COLLADABUPlatform.h" - #include "collada_internal.h" +#include "BLI_linklist.h" + UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) {} void UnitConverter::read_asset(const COLLADAFW::FileInfo* asset) @@ -277,17 +278,3 @@ { return translate_id(id_name(mat)) + "-material"; } - -bool has_object_type(Scene *sce, short obtype) -{ - Base *base= (Base*) sce->base.first; - while (base) { - Object *ob = base->object; - - if (ob->type == obtype && ob->data) { - return true; - } - base= base->next; - } - return false; -} Index: source/blender/collada/MaterialExporter.h =================================================================== --- source/blender/collada/MaterialExporter.h (revision 47586) +++ source/blender/collada/MaterialExporter.h (working copy) @@ -89,11 +89,11 @@ // f should have // void operator()(Material* ma) template - void forEachMaterialInScene(Scene *sce, Functor &f, bool export_selected) + void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { ForEachMaterialFunctor matfunc(&f); GeometryFunctor gf; - gf.forEachMeshObjectInScene >(sce, matfunc, export_selected); + gf.forEachMeshObjectInExportSet >(sce, matfunc, export_set); } }; Index: source/blender/collada/collada.h =================================================================== --- source/blender/collada/collada.h (revision 47586) +++ source/blender/collada/collada.h (working copy) @@ -44,11 +44,13 @@ int apply_modifiers, int include_armatures, - int include_bone_children, + int include_children, int use_object_instantiation, int second_life); + + #ifdef __cplusplus } #endif Index: source/blender/collada/ExportSettings.h =================================================================== --- source/blender/collada/ExportSettings.h (revision 47586) +++ source/blender/collada/ExportSettings.h (working copy) @@ -24,6 +24,10 @@ * \ingroup collada */ +extern "C" { +#include "BLI_linklist.h" +} + #ifndef __EXPORTSETTINGS_H__ #define __EXPORTSETTINGS_H__ @@ -33,10 +37,11 @@ bool selected; bool apply_modifiers; bool include_armatures; - bool include_bone_children; + bool include_children; bool use_object_instantiation; bool second_life; char *filepath; + LinkNode *export_set; }; #endif Index: source/blender/makesrna/intern/rna_scene_api.c =================================================================== --- source/blender/makesrna/intern/rna_scene_api.c (revision 47586) +++ source/blender/makesrna/intern/rna_scene_api.c (working copy) @@ -91,12 +91,12 @@ int selected, int apply_modifiers, int include_armatures, - int include_bone_children, + int include_children, int use_object_instantiation, int second_life) { collada_export(scene, filepath, selected, apply_modifiers, - include_armatures, include_bone_children, + include_armatures, include_children, use_object_instantiation, second_life); } @@ -128,7 +128,7 @@ parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements"); parm = RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers (in Preview resolution)"); parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Include armature(s) used by the exported objects"); - parm = RNA_def_boolean(func, "include_bone_children", 0, "Include Bone Children", "Include all objects attached to bones of selected Armature(s)"); + parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Include all children even if not selected"); parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instantiation", "Instantiate multiple Objects from same Data"); parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); RNA_def_function_ui_description(func, "Export to collada file"); Index: source/blender/blenkernel/intern/object.c =================================================================== --- source/blender/blenkernel/intern/object.c (revision 47586) +++ source/blender/blenkernel/intern/object.c (working copy) @@ -63,6 +63,7 @@ #include "BLI_math.h" #include "BLI_pbvh.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BKE_main.h" #include "BKE_global.h" @@ -3076,3 +3077,124 @@ return clip; } + + +/* + * Find an associated Armature object + */ +static Object *find_assigned_armature(Object *ob) +{ + Object *ob_arm = NULL; + + if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) { + ob_arm = ob->parent; + } + else { + ModifierData *mod = (ModifierData*)ob->modifiers.first; + while (mod) { + if (mod->type == eModifierType_Armature) { + ob_arm = ((ArmatureModifierData*)mod)->object; + } + + mod = mod->next; + } + } + + return ob_arm; +} + +static int isRecursiveChildOf(Object *ob, Object *child) { + Object *ancestor = child->parent; + while (ancestor) + { + if(ancestor == ob) return TRUE; + ancestor = ancestor->parent; + } + return FALSE; +} + + +static int can_include(Object *ob) +{ + return ob && !(ob->id.flag & LIB_DOIT); +} + +static void add_to_list(LinkNode **links, Object *ob) +{ + BLI_linklist_prepend(links, ob); + ob->id.flag |= LIB_DOIT; +} + +/* + * Iterates over all selected and visible objects of the given scene. + * For each object in the list add related objects according to the given includeFilters. + */ +LinkNode *BKE_object_relational_superset(struct Scene *scene, int includeFilter) +{ + LinkNode *links = NULL; + + Base *base; + + /* Remove markers from all objects */ + for (base = scene->base.first; base; base = base->next) { + base->object->id.flag &= ~LIB_DOIT; + } + + /* iterate over all selected and visible objects */ + for (base = scene->base.first; base; base = base->next) { + if (TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) { + Object *ob = base->object; + + if (can_include(ob)) + add_to_list(&links, ob); + + /* parent relationship */ + if (includeFilter & ( OB_REL_PARENT | OB_REL_PARENT_RECURSIVE )) { + Object *parent = ob->parent; + if (can_include(parent)) { + + add_to_list(&links, parent); + + /* recursive parent relationship */ + if (includeFilter & OB_REL_PARENT_RECURSIVE) { + parent = parent->parent; + while (can_include(parent)){ + + add_to_list(&links, parent); + parent = parent->parent; + } + } + } + } + + /* child relationship */ + if (includeFilter & ( OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE )) { + Base *local_base; + for (local_base = scene->base.first; local_base; local_base = local_base->next) { + if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { + + Object *child = local_base->object; + if (can_include(child)) { + if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && isRecursiveChildOf(ob,child)) + || (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob )) { + add_to_list(&links, child); + } + } + } + } + } + + + /* include related armatures */ + if (includeFilter & OB_REL_MOD_ARMATURE) { + Object *arm = find_assigned_armature(ob); + if (can_include(arm)) { + add_to_list(&links, arm); + } + } + + } + } + + return links; +} Index: source/blender/blenkernel/BKE_object.h =================================================================== --- source/blender/blenkernel/BKE_object.h (revision 47586) +++ source/blender/blenkernel/BKE_object.h (working copy) @@ -158,6 +158,20 @@ struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, int use_default); +/* this function returns a superset of the scenes selection based on relationships */ + +typedef enum eObRelationTypes { + OB_REL_NO_RELATED = 0, /* just the selection as is */ + OB_REL_PARENT = (1<<0), /* immediate parent */ + OB_REL_PARENT_RECURSIVE = (1<<1), /* parents up to root of selection tree*/ + OB_REL_CHILDREN = (1<<2), /* immediate children */ + OB_REL_CHILDREN_RECURSIVE = (1<<3), /* All children */ + OB_REL_MOD_ARMATURE = (1<<4), /* Armatures related to the selected objects */ + OB_REL_SCENE_CAMERA = (1<<5), /* you might want the scene camera too even if unselected? */ +} eObRelationTypes; + +struct LinkNode *BKE_object_relational_superset(struct Scene *scene, int includeFilter); + #ifdef __cplusplus } #endif Index: source/blender/windowmanager/intern/wm_operators.c =================================================================== --- source/blender/windowmanager/intern/wm_operators.c (revision 47586) +++ source/blender/windowmanager/intern/wm_operators.c (working copy) @@ -2165,7 +2165,7 @@ int selected, second_life, include_armatures, apply_modifiers, - include_bone_children, + include_children, use_object_instantiation; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -2179,7 +2179,7 @@ selected = RNA_boolean_get(op->ptr, "selected"); apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); - include_bone_children = RNA_boolean_get(op->ptr, "include_bone_children"); + include_children = RNA_boolean_get(op->ptr, "include_children"); use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); second_life = RNA_boolean_get(op->ptr, "second_life"); @@ -2192,7 +2192,7 @@ selected, apply_modifiers, include_armatures, - include_bone_children, + include_children, use_object_instantiation, second_life)) { return OPERATOR_FINISHED; @@ -2225,8 +2225,8 @@ RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", "Include armature(s) used by the exported objects"); - RNA_def_boolean(ot->srna, "include_bone_children", 0, "Include Bone Children", - "Include all objects attached to bones of selected Armature(s)"); + RNA_def_boolean(ot->srna, "include_children", 0, "Include Children", + "Include all children even if not selected"); RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instantiation", "Instantiate multiple Objects from same Data");