[#31739] Collada: New Export selections 'Include Armatures'
This commit is contained in:
parent
64c45caff9
commit
49a5141cde
|
@ -37,6 +37,14 @@
|
|||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_armature.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_library.h"
|
||||
}
|
||||
|
||||
#include "ED_armature.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
@ -45,6 +53,8 @@
|
|||
#include "ArmatureExporter.h"
|
||||
#include "SceneExporter.h"
|
||||
|
||||
#include "collada_utils.h"
|
||||
|
||||
// XXX exporter writes wrong data for shared armatures. A separate
|
||||
// controller should be written for each armature-mesh binding how do
|
||||
// we make controller ids then?
|
||||
|
@ -66,12 +76,12 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene* sce,
|
|||
|
||||
bool ArmatureExporter::is_skinned_mesh(Object *ob)
|
||||
{
|
||||
return get_assigned_armature(ob) != NULL;
|
||||
return bc_get_assigned_armature(ob) != NULL;
|
||||
}
|
||||
|
||||
void ArmatureExporter::add_instance_controller(Object *ob)
|
||||
bool ArmatureExporter::add_instance_controller(Object *ob)
|
||||
{
|
||||
Object *ob_arm = get_assigned_armature(ob);
|
||||
Object *ob_arm = bc_get_assigned_armature(ob);
|
||||
bArmature *arm = (bArmature*)ob_arm->data;
|
||||
|
||||
const std::string& controller_id = get_controller_id(ob_arm, ob);
|
||||
|
@ -79,6 +89,9 @@ void ArmatureExporter::add_instance_controller(Object *ob)
|
|||
COLLADASW::InstanceController ins(mSW);
|
||||
ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
|
||||
|
||||
Mesh *me = (Mesh *)ob->data;
|
||||
if (!me->dvert) return false;
|
||||
|
||||
// write root bone URLs
|
||||
Bone *bone;
|
||||
for (bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) {
|
||||
|
@ -89,6 +102,7 @@ void ArmatureExporter::add_instance_controller(Object *ob)
|
|||
InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob);
|
||||
|
||||
ins.add();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArmatureExporter::export_controllers(Scene *sce)
|
||||
|
@ -105,7 +119,7 @@ void ArmatureExporter::export_controllers(Scene *sce)
|
|||
|
||||
void ArmatureExporter::operator()(Object *ob)
|
||||
{
|
||||
Object *ob_arm = get_assigned_armature(ob);
|
||||
Object *ob_arm = bc_get_assigned_armature(ob);
|
||||
|
||||
if (ob_arm /*&& !already_written(ob_arm)*/)
|
||||
export_controller(ob, ob_arm);
|
||||
|
@ -139,27 +153,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
|
|||
}
|
||||
#endif
|
||||
|
||||
Object *ArmatureExporter::get_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;
|
||||
}
|
||||
|
||||
std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
|
||||
{
|
||||
return get_joint_id(bone, ob_arm);
|
||||
|
@ -325,7 +318,16 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm)
|
|||
*/
|
||||
|
||||
bool use_instantiation = this->export_settings->use_object_instantiation;
|
||||
Mesh *me = (Mesh*)ob->data;
|
||||
Mesh *me;
|
||||
|
||||
if ( this->export_settings->apply_modifiers ) {
|
||||
me = bc_to_mesh_apply_modifiers(scene, ob);
|
||||
}
|
||||
else {
|
||||
me = (Mesh*)ob->data;
|
||||
}
|
||||
BKE_mesh_tessface_ensure(me);
|
||||
|
||||
if (!me->dvert) return;
|
||||
|
||||
std::string controller_name = id_name(ob_arm);
|
||||
|
@ -393,6 +395,10 @@ void ArmatureExporter::export_controller(Object* ob, Object *ob_arm)
|
|||
add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
|
||||
add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
|
||||
|
||||
if (this->export_settings->apply_modifiers)
|
||||
{
|
||||
BKE_libblock_free_us(&(G.main->mesh), me);
|
||||
}
|
||||
closeSkin();
|
||||
closeController();
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
bool is_skinned_mesh(Object *ob);
|
||||
|
||||
void add_instance_controller(Object *ob);
|
||||
bool add_instance_controller(Object *ob);
|
||||
|
||||
void export_controllers(Scene *sce);
|
||||
|
||||
|
@ -85,8 +85,6 @@ private:
|
|||
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
|
||||
#endif
|
||||
|
||||
Object *get_assigned_armature(Object *ob);
|
||||
|
||||
std::string get_joint_sid(Bone *bone, Object *ob_arm);
|
||||
|
||||
// Scene, SceneExporter and the list of child_objects
|
||||
|
|
|
@ -262,8 +262,10 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
|
|||
|
||||
// <library_controllers>
|
||||
ArmatureExporter arm_exporter(&sw, this->export_settings);
|
||||
if (has_object_type(sce, OB_ARMATURE)) {
|
||||
arm_exporter.export_controllers(sce);
|
||||
if (this->export_settings->include_armatures) {
|
||||
if (has_object_type(sce, OB_ARMATURE)) {
|
||||
arm_exporter.export_controllers(sce);
|
||||
}
|
||||
}
|
||||
|
||||
// <library_visual_scenes>
|
||||
|
|
|
@ -32,6 +32,7 @@ struct ExportSettings
|
|||
public:
|
||||
bool selected;
|
||||
bool apply_modifiers;
|
||||
bool include_armatures;
|
||||
bool include_bone_children;
|
||||
bool use_object_instantiation;
|
||||
bool second_life;
|
||||
|
|
|
@ -49,6 +49,7 @@ extern "C" {
|
|||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "collada_internal.h"
|
||||
#include "collada_utils.h"
|
||||
|
||||
// TODO: optimize UV sets by making indexed list with duplicates removed
|
||||
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) {}
|
||||
|
@ -65,25 +66,6 @@ void GeometryExporter::exportGeom(Scene *sce)
|
|||
closeLibrary();
|
||||
}
|
||||
|
||||
Mesh * GeometryExporter::get_mesh(Object *ob, int apply_modifiers)
|
||||
{
|
||||
Mesh *tmpmesh;
|
||||
if (!apply_modifiers)
|
||||
{
|
||||
tmpmesh = (Mesh*)ob->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomDataMask mask = CD_MASK_MESH;
|
||||
DerivedMesh *dm = mesh_create_derived_view(mScene, ob, mask);
|
||||
tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here
|
||||
DM_to_mesh(dm, tmpmesh, ob);
|
||||
dm->release(dm);
|
||||
}
|
||||
BKE_mesh_tessface_ensure(tmpmesh);
|
||||
return tmpmesh;
|
||||
}
|
||||
|
||||
void GeometryExporter::operator()(Object *ob)
|
||||
{
|
||||
// XXX don't use DerivedMesh, Mesh instead?
|
||||
|
@ -93,7 +75,14 @@ void GeometryExporter::operator()(Object *ob)
|
|||
#endif
|
||||
|
||||
bool use_instantiation = this->export_settings->use_object_instantiation;
|
||||
Mesh *me = get_mesh(ob, this->export_settings->apply_modifiers);
|
||||
Mesh *me;
|
||||
if ( this->export_settings->apply_modifiers ) {
|
||||
me = bc_to_mesh_apply_modifiers(mScene, ob);
|
||||
}
|
||||
else {
|
||||
me = (Mesh*)ob->data;
|
||||
}
|
||||
BKE_mesh_tessface_ensure(me);
|
||||
|
||||
std::string geom_id = get_geometry_id(ob, use_instantiation);
|
||||
std::vector<Normal> nor;
|
||||
|
|
|
@ -105,7 +105,7 @@ private:
|
|||
|
||||
const ExportSettings *export_settings;
|
||||
|
||||
Mesh * get_mesh(Object *ob, int apply_modifiers);
|
||||
Mesh * get_mesh(Scene *sce, Object *ob, int apply_modifiers);
|
||||
};
|
||||
|
||||
struct GeometryFunctor {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "SceneExporter.h"
|
||||
#include "collada_utils.h"
|
||||
|
||||
SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings)
|
||||
: COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings)
|
||||
|
@ -40,19 +41,36 @@ void SceneExporter::exportScene(Scene *sce)
|
|||
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;
|
||||
|
||||
if (!ob->parent) {
|
||||
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_ARMATURE:
|
||||
case OB_EMPTY:
|
||||
if (this->export_settings->selected && !(ob->flag & SELECT)) {
|
||||
break;
|
||||
|
@ -70,6 +88,14 @@ void SceneExporter::exportHierarchy(Scene *sce)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
COLLADASW::Node node(mSW);
|
||||
node.setNodeId(translate_id(id_name(ob)));
|
||||
node.setNodeName(translate_id(id_name(ob)));
|
||||
|
@ -80,8 +106,19 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
|
|||
bool is_skinned_mesh = arm_exporter->is_skinned_mesh(ob);
|
||||
std::list<Object*> 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) {
|
||||
|
||||
if (this->export_settings->include_bone_children) {
|
||||
// list child objects
|
||||
Base *b = (Base*) sce->base.first;
|
||||
while (b) {
|
||||
|
@ -105,7 +142,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
|
|||
}
|
||||
|
||||
|
||||
if (ob->type == OB_MESH && is_skinned_mesh)
|
||||
if (ob->type == OB_MESH && this->export_settings->include_armatures && is_skinned_mesh)
|
||||
// for skinned mesh we write obmat in <bind_shape_matrix>
|
||||
TransformWriter::add_node_transform_identity(node);
|
||||
else
|
||||
|
@ -113,10 +150,11 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
|
|||
|
||||
// <instance_geometry>
|
||||
if (ob->type == OB_MESH) {
|
||||
if (is_skinned_mesh) {
|
||||
arm_exporter->add_instance_controller(ob);
|
||||
bool instance_controller_created = false;
|
||||
if (this->export_settings->include_armatures && is_skinned_mesh) {
|
||||
instance_controller_created = arm_exporter->add_instance_controller(ob);
|
||||
}
|
||||
else {
|
||||
if (!instance_controller_created){
|
||||
COLLADASW::InstanceGeometry instGeom(mSW);
|
||||
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
|
||||
|
||||
|
|
|
@ -54,14 +54,18 @@ extern "C"
|
|||
const char *filepath,
|
||||
int selected,
|
||||
int apply_modifiers,
|
||||
|
||||
int include_armatures,
|
||||
int include_bone_children,
|
||||
|
||||
int use_object_instantiation,
|
||||
int second_life)
|
||||
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;
|
||||
|
|
|
@ -38,13 +38,17 @@ extern "C" {
|
|||
*/
|
||||
int collada_import(bContext *C, const char *filepath);
|
||||
int collada_export(
|
||||
Scene *sce,
|
||||
Scene *sce,
|
||||
const char *filepath,
|
||||
int selected,
|
||||
int apply_modifiers,
|
||||
|
||||
int include_armatures,
|
||||
int include_bone_children,
|
||||
|
||||
int use_object_instantiation,
|
||||
int second_life);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -32,8 +32,10 @@
|
|||
#include "COLLADAFWMeshPrimitive.h"
|
||||
#include "COLLADAFWMeshVertexData.h"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
@ -42,8 +44,13 @@
|
|||
#include "BKE_customdata.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BKE_DerivedMesh.h"
|
||||
}
|
||||
|
||||
#include "WM_api.h" // XXX hrm, see if we can do without this
|
||||
#include "WM_types.h"
|
||||
|
||||
|
@ -125,3 +132,35 @@ Object *bc_add_object(Scene *scene, int type, const char *name)
|
|||
return ob;
|
||||
}
|
||||
|
||||
Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob)
|
||||
{
|
||||
Mesh *tmpmesh;
|
||||
CustomDataMask mask = CD_MASK_MESH;
|
||||
DerivedMesh *dm = mesh_create_derived_view(scene, ob, mask);
|
||||
tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here
|
||||
DM_to_mesh(dm, tmpmesh, ob);
|
||||
dm->release(dm);
|
||||
return tmpmesh;
|
||||
}
|
||||
|
||||
Object *bc_get_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <map>
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "BKE_context.h"
|
||||
|
@ -50,5 +51,7 @@ extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_sp
|
|||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,11 +90,14 @@ static void rna_Scene_collada_export(
|
|||
const char *filepath,
|
||||
int selected,
|
||||
int apply_modifiers,
|
||||
int include_armatures,
|
||||
int include_bone_children,
|
||||
int use_object_instantiation,
|
||||
int second_life)
|
||||
{
|
||||
collada_export(scene, filepath, selected, apply_modifiers, include_bone_children, use_object_instantiation, second_life);
|
||||
collada_export(scene, filepath, selected, apply_modifiers,
|
||||
include_armatures, include_bone_children,
|
||||
use_object_instantiation, second_life);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -124,6 +127,7 @@ void RNA_api_scene(StructRNA *srna)
|
|||
RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
|
||||
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, "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");
|
||||
|
|
|
@ -2162,7 +2162,11 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
|
|||
static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char filename[FILE_MAX];
|
||||
int selected, second_life, apply_modifiers, include_bone_children, use_object_instantiation;
|
||||
int selected, second_life,
|
||||
include_armatures,
|
||||
apply_modifiers,
|
||||
include_bone_children,
|
||||
use_object_instantiation;
|
||||
|
||||
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No filename given");
|
||||
|
@ -2174,6 +2178,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
|||
/* Options panel */
|
||||
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");
|
||||
use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
|
||||
second_life = RNA_boolean_get(op->ptr, "second_life");
|
||||
|
@ -2186,6 +2191,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
|
|||
filename,
|
||||
selected,
|
||||
apply_modifiers,
|
||||
include_armatures,
|
||||
include_bone_children,
|
||||
use_object_instantiation,
|
||||
second_life)) {
|
||||
|
@ -2216,6 +2222,9 @@ static void WM_OT_collada_export(wmOperatorType *ot)
|
|||
RNA_def_boolean(ot->srna, "apply_modifiers", 0, "Apply Modifiers",
|
||||
"Apply modifiers (Preview Resolution)");
|
||||
|
||||
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)");
|
||||
|
||||
|
|
Loading…
Reference in New Issue