diff --git a/pandatool/src/mayaegg/mayaNodeDesc.cxx b/pandatool/src/mayaegg/mayaNodeDesc.cxx index f5720399f9..820536e7fc 100755 --- a/pandatool/src/mayaegg/mayaNodeDesc.cxx +++ b/pandatool/src/mayaegg/mayaNodeDesc.cxx @@ -35,6 +35,7 @@ MayaNodeDesc(MayaNodeDesc *parent, const string &name) : _egg_table = (EggTable *)NULL; _anim = (EggXfmSAnim *)NULL; _joint_type = JT_none; + _tagged = false; // Add ourselves to our parent. if (_parent != (MayaNodeDesc *)NULL) { @@ -101,7 +102,7 @@ get_dag_path() const { //////////////////////////////////////////////////////////////////// // Function: MayaNodeDesc::is_joint -// Access: Private +// Access: Public // Description: Returns true if the node should be treated as a joint // by the converter. //////////////////////////////////////////////////////////////////// @@ -112,7 +113,7 @@ is_joint() const { //////////////////////////////////////////////////////////////////// // Function: MayaNodeDesc::is_joint_parent -// Access: Private +// Access: Public // Description: Returns true if the node is the parent or ancestor of // a joint. //////////////////////////////////////////////////////////////////// @@ -121,6 +122,46 @@ is_joint_parent() const { return _joint_type == JT_joint_parent; } +//////////////////////////////////////////////////////////////////// +// Function: MayaNodeDesc::is_tagged +// Access: Public +// Description: Returns true if the node has been tagged to be +// converted, false otherwise. +//////////////////////////////////////////////////////////////////// +bool MayaNodeDesc:: +is_tagged() const { + return _tagged; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaNodeDesc::tag +// Access: Private +// Description: Tags this node for conversion, but does not tag child +// nodes. +//////////////////////////////////////////////////////////////////// +void MayaNodeDesc:: +tag() { + _tagged = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaNodeDesc::tag_recursively +// Access: Private +// Description: Tags this node and all descendant nodes for +// conversion. +//////////////////////////////////////////////////////////////////// +void MayaNodeDesc:: +tag_recursively() { + _tagged = true; + + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + MayaNodeDesc *child = (*ci); + child->tag_recursively(); + } +} + + //////////////////////////////////////////////////////////////////// // Function: MayaNodeDesc::clear_egg // Access: Private diff --git a/pandatool/src/mayaegg/mayaNodeDesc.h b/pandatool/src/mayaegg/mayaNodeDesc.h index 8e4678641d..65187b26a6 100755 --- a/pandatool/src/mayaegg/mayaNodeDesc.h +++ b/pandatool/src/mayaegg/mayaNodeDesc.h @@ -52,11 +52,16 @@ public: bool is_joint() const; bool is_joint_parent() const; + bool is_tagged() const; + MayaNodeDesc *_parent; typedef pvector< PT(MayaNodeDesc) > Children; Children _children; private: + void tag(); + void tag_recursively(); + void clear_egg(); void mark_joint_parent(); void check_pseudo_joints(bool joint_above); @@ -76,6 +81,8 @@ private: }; JointType _joint_type; + bool _tagged; + public: static TypeHandle get_class_type() { diff --git a/pandatool/src/mayaegg/mayaNodeTree.cxx b/pandatool/src/mayaegg/mayaNodeTree.cxx index fb760c13ee..df2c4f0639 100755 --- a/pandatool/src/mayaegg/mayaNodeTree.cxx +++ b/pandatool/src/mayaegg/mayaNodeTree.cxx @@ -62,13 +62,14 @@ build_node(const MDagPath &dag_path) { } //////////////////////////////////////////////////////////////////// -// Function: MayaNodeTree::build_complete_hierarchy +// Function: MayaNodeTree::build_hierarchy // Access: Public // Description: Walks through the complete Maya hierarchy and builds -// up the corresponding tree. +// up the corresponding tree, but does not tag any nodes +// for conversion. //////////////////////////////////////////////////////////////////// bool MayaNodeTree:: -build_complete_hierarchy() { +build_hierarchy() { MStatus status; MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status); @@ -104,14 +105,25 @@ build_complete_hierarchy() { } //////////////////////////////////////////////////////////////////// -// Function: MayaNodeTree::build_selected_hierarchy +// Function: MayaNodeTree::tag_all // Access: Public -// Description: Walks through the selected subset of the Maya -// hierarchy (or the complete hierarchy, if nothing is -// selected) and builds up the corresponding tree. +// Description: Tags the entire hierarchy for conversion. This is +// the normal behavior. +//////////////////////////////////////////////////////////////////// +void MayaNodeTree:: +tag_all() { + _root->tag_recursively(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaNodeTree::tag_selected +// Access: Public +// Description: Tags the just the selected hierarchy for conversion, +// or the entire hierarchy if nothing is selected. +// Returns true on success, false on failure. //////////////////////////////////////////////////////////////////// bool MayaNodeTree:: -build_selected_hierarchy() { +tag_selected() { MStatus status; MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status); @@ -120,7 +132,6 @@ build_selected_hierarchy() { return false; } - // Get only the selected geometry. MSelectionList selection; status = MGlobal::getActiveSelectionList(selection); if (!status) { @@ -128,12 +139,11 @@ build_selected_hierarchy() { return false; } - // Get the selected geometry only if the selection is nonempty; - // otherwise, get the whole scene anyway. if (selection.isEmpty()) { mayaegg_cat.info() << "Selection list is empty.\n"; - return build_complete_hierarchy(); + tag_all(); + return true; } bool all_ok = true; @@ -153,7 +163,7 @@ build_selected_hierarchy() { if (!status) { status.perror("MItDag::getPath"); } else { - build_node(dag_path); + build_node(dag_path)->tag(); } dag_iterator.next(); @@ -168,6 +178,32 @@ build_selected_hierarchy() { return all_ok; } +//////////////////////////////////////////////////////////////////// +// Function: MayaNodeTree::tag_named +// Access: Public +// Description: Tags nodes matching the indicated glob (and all of +// their children) for conversion. Returns true on +// success, false otherwise (e.g. the named node does +// not exist). +//////////////////////////////////////////////////////////////////// +bool MayaNodeTree:: +tag_named(const GlobPattern &glob) { + // There might be multiple nodes matching the name; search for all + // of them. + bool found_any = false; + + Nodes::iterator ni; + for (ni = _nodes.begin(); ni != _nodes.end(); ++ni) { + MayaNodeDesc *node = (*ni); + if (glob.matches(node->get_name())) { + node->tag_recursively(); + found_any = true; + } + } + + return found_any; +} + //////////////////////////////////////////////////////////////////// // Function: MayaNodeTree::get_num_nodes // Access: Public diff --git a/pandatool/src/mayaegg/mayaNodeTree.h b/pandatool/src/mayaegg/mayaNodeTree.h index 486d277bff..fa21f84bc4 100755 --- a/pandatool/src/mayaegg/mayaNodeTree.h +++ b/pandatool/src/mayaegg/mayaNodeTree.h @@ -22,6 +22,7 @@ #include "pandatoolbase.h" #include "mayaNodeDesc.h" +#include "globPattern.h" class EggData; class EggGroupNode; @@ -35,8 +36,11 @@ class MayaNodeTree { public: MayaNodeTree(); MayaNodeDesc *build_node(const MDagPath &dag_path); - bool build_complete_hierarchy(); - bool build_selected_hierarchy(); + bool build_hierarchy(); + + void tag_all(); + bool tag_selected(); + bool tag_named(const GlobPattern &glob); int get_num_nodes() const; MayaNodeDesc *get_node(int n) const; diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index 6caf31e04a..4677f99517 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -103,6 +103,7 @@ MayaToEggConverter(const string &program_name) : MayaToEggConverter:: MayaToEggConverter(const MayaToEggConverter ©) : _from_selection(copy._from_selection), + _subsets(copy._subsets), _maya(copy._maya), _polygon_output(copy._polygon_output), _polygon_tolerance(copy._polygon_tolerance), @@ -201,7 +202,47 @@ convert_file(const Filename &filename) { _character_name = filename.get_basename_wo_extension(); } - return convert_maya(false); + return convert_maya(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::clear_subsets +// Access: Public +// Description: Empties the list of subset nodes added via +// add_subset(). The entire file will once again be +// converted. +//////////////////////////////////////////////////////////////////// +void MayaToEggConverter:: +clear_subsets() { + _subsets.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::add_subset +// Access: Public +// Description: Adds a name pattern to the list of subset nodes. If +// the list of subset nodes is not empty, then only a +// subset of the nodes in the maya file will be +// converted: those whose names match one of the +// patterns given on this list. +//////////////////////////////////////////////////////////////////// +void MayaToEggConverter:: +add_subset(const GlobPattern &glob) { + _subsets.push_back(glob); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::set_from_selection +// Access: Public +// Description: Sets the flag that indicates whether the currently +// selected Maya geometry will be converted. If this is +// true, and the selection is nonempty, then only the +// selected geometry will be converted. If this is +// false, the entire file will be converted. +//////////////////////////////////////////////////////////////////// +void MayaToEggConverter:: +set_from_selection(bool from_selection) { + _from_selection = from_selection; } //////////////////////////////////////////////////////////////////// @@ -223,14 +264,10 @@ get_input_units() { // Access: Public // Description: Fills up the egg_data structure according to the // global maya model data. Returns true if successful, -// false if there is an error. If from_selection is -// true, the converted geometry is based on that which -// is selected; otherwise, it is the entire Maya scene. +// false if there is an error. //////////////////////////////////////////////////////////////////// bool MayaToEggConverter:: -convert_maya(bool from_selection) { - _from_selection = from_selection; - +convert_maya() { clear(); if (!open_api()) { @@ -277,12 +314,24 @@ convert_maya(bool from_selection) { frame_inc = frame_inc * input_frame_rate / output_frame_rate; - bool all_ok = true; + bool all_ok = _tree.build_hierarchy(); - if (_from_selection) { - all_ok = _tree.build_selected_hierarchy(); - } else { - all_ok = _tree.build_complete_hierarchy(); + if (all_ok) { + if (_from_selection) { + all_ok = _tree.tag_selected(); + + } else if (!_subsets.empty()) { + Subsets::const_iterator si; + for (si = _subsets.begin(); si != _subsets.end(); ++si) { + if (!_tree.tag_named(*si)) { + mayaegg_cat.info() + << "No node matching " << *si << " found.\n"; + } + } + + } else { + _tree.tag_all(); + } } if (all_ok) { @@ -557,8 +606,11 @@ convert_hierarchy(EggGroupNode *egg_root) { _tree.clear_egg(&get_egg_data(), egg_root, NULL); for (int i = 0; i < num_nodes; i++) { - if (!process_model_node(_tree.get_node(i))) { - return false; + MayaNodeDesc *node = _tree.get_node(i); + if (node->is_tagged()) { + if (!process_model_node(node)) { + return false; + } } } diff --git a/pandatool/src/mayaegg/mayaToEggConverter.h b/pandatool/src/mayaegg/mayaToEggConverter.h index e702a455b5..23a120c16c 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.h +++ b/pandatool/src/mayaegg/mayaToEggConverter.h @@ -28,6 +28,8 @@ #include "eggTextureCollection.h" #include "distanceUnit.h" #include "coordinateSystem.h" +#include "globPattern.h" +#include "pvector.h" #include "pre_maya_include.h" #include @@ -74,7 +76,12 @@ public: virtual bool convert_file(const Filename &filename); virtual DistanceUnit get_input_units(); - bool convert_maya(bool from_selection); + + void clear_subsets(); + void add_subset(const GlobPattern &glob); + void set_from_selection(bool from_selection); + + bool convert_maya(); bool open_api(); void close_api(); @@ -124,7 +131,10 @@ private: bool reparent_decals(EggGroupNode *egg_parent); string _program_name; + bool _from_selection; + typedef pvector Subsets; + Subsets _subsets; MayaNodeTree _tree; diff --git a/pandatool/src/mayaprogs/mayaPview.cxx b/pandatool/src/mayaprogs/mayaPview.cxx index 61cf8580da..7ed6ebd023 100755 --- a/pandatool/src/mayaprogs/mayaPview.cxx +++ b/pandatool/src/mayaprogs/mayaPview.cxx @@ -148,8 +148,9 @@ convert(const NodePath &parent) { EggData egg_data; converter.set_egg_data(&egg_data, false); + converter.set_from_selection(true); - if (!converter.convert_maya(true)) { + if (!converter.convert_maya()) { nout << "Errors in conversion.\n"; return false; } diff --git a/pandatool/src/mayaprogs/mayaToEgg.cxx b/pandatool/src/mayaprogs/mayaToEgg.cxx index 0a6c88dcdd..e6663692f3 100644 --- a/pandatool/src/mayaprogs/mayaToEgg.cxx +++ b/pandatool/src/mayaprogs/mayaToEgg.cxx @@ -20,6 +20,7 @@ #include "mayaToEggConverter.h" #include "config_mayaegg.h" #include "config_maya.h" // for maya_cat +#include "globPattern.h" //////////////////////////////////////////////////////////////////// // Function: MayaToEgg::Constructor @@ -73,6 +74,16 @@ MayaToEgg() : "nodes that have the model flag or the dcs flag are preserved.", &MayaToEgg::dispatch_transform_type, NULL, &_transform_type); + add_option + ("subset", "name", 0, + "Specifies that only a subset of the geometry in the Maya file should " + "be converted; specifically, the geometry under the node or nodes whose " + "name matches the parameter (which may include globbing characters " + "like * or ?). This parameter may be repeated multiple times to name " + "multiple roots. If it is omitted altogether, the entire file is " + "converted.", + &MayaToEgg::dispatch_vector_string, NULL, &_subsets); + add_option ("v", "", 0, "Increase verbosity. More v's means more verbose.", @@ -122,6 +133,11 @@ run() { converter._respect_maya_double_sided = _respect_maya_double_sided; converter._transform_type = _transform_type; + vector_string::const_iterator si; + for (si = _subsets.begin(); si != _subsets.end(); ++si) { + converter.add_subset(GlobPattern(*si)); + } + // Copy in the path and animation parameters. apply_parameters(converter); diff --git a/pandatool/src/mayaprogs/mayaToEgg.h b/pandatool/src/mayaprogs/mayaToEgg.h index debdccf241..0d5ebbe8b3 100644 --- a/pandatool/src/mayaprogs/mayaToEgg.h +++ b/pandatool/src/mayaprogs/mayaToEgg.h @@ -41,6 +41,7 @@ protected: double _polygon_tolerance; bool _respect_maya_double_sided; MayaToEggConverter::TransformType _transform_type; + vector_string _subsets; }; #endif