diff --git a/pandatool/src/mayaprogs/Sources.pp b/pandatool/src/mayaprogs/Sources.pp index 895eb2e813..e9dc8fa979 100644 --- a/pandatool/src/mayaprogs/Sources.pp +++ b/pandatool/src/mayaprogs/Sources.pp @@ -8,6 +8,14 @@ mayapath.cxx #end bin_target +#begin bin_target + #define TARGET maya2egg_server + #define OTHER_LIBS \ + dtoolbase:c dtoolutil:c dtool:m + #define SOURCES \ + mayapath.cxx +#end bin_target + #begin bin_target #define USE_PACKAGES maya #define TARGET maya2egg_bin @@ -29,6 +37,48 @@ #end bin_target +#begin bin_target + #define USE_PACKAGES maya + #define TARGET maya2egg_server_bin + #define LOCAL_LIBS \ + mayabase mayaegg eggbase progbase + #define OTHER_LIBS \ + egg:c pandaegg:m \ + linmath:c putil:c panda:m \ + express:c pandaexpress:m \ + interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m $[if $[WINDOWS_PLATFORM],pystub,] \ + pipeline:c pnmimage:c + + // Irix requires this to be named explicitly. + #define UNIX_SYS_LIBS \ + ExtensionLayer + + #define SOURCES \ + mayaToEgg_server.cxx mayaToEgg_server.h + +#end bin_target + +#begin bin_target + #define USE_PACKAGES maya + #define TARGET maya2egg_client + #define LOCAL_LIBS \ + mayabase mayaegg eggbase progbase + #define OTHER_LIBS \ + egg:c pandaegg:m \ + linmath:c putil:c panda:m \ + express:c pandaexpress:m \ + interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m $[if $[WINDOWS_PLATFORM],pystub,] \ + pipeline:c pnmimage:c + + // Irix requires this to be named explicitly. + #define UNIX_SYS_LIBS \ + ExtensionLayer + + #define SOURCES \ + mayaToEgg_client.cxx mayaToEgg_client.h + +#end bin_target + #begin bin_target #define TARGET egg2maya #define OTHER_LIBS \ diff --git a/pandatool/src/mayaprogs/mayaCopy.cxx b/pandatool/src/mayaprogs/mayaCopy.cxx index db4c121340..88aecc9996 100644 --- a/pandatool/src/mayaprogs/mayaCopy.cxx +++ b/pandatool/src/mayaprogs/mayaCopy.cxx @@ -71,10 +71,16 @@ MayaCopy() { add_option ("omittex", "", 0, - "Character animation files do not need to copy the texures nor its references. " - "This option omits the textures and references of the models to be re-mayacopied", + "Character animation files do not need to copy the texures. " + "This option omits the textures of the models to be re-mayacopied", &CVSCopy::dispatch_none, &_omit_tex); + add_option + ("omitref", "", 0, + "Character animation files do not need to copy internal file references. " + "This option omits the references of the models to be re-mayacopied", + &CVSCopy::dispatch_none, &_omit_ref); + add_option ("ma", "", 0, "Write a .ma file instead of a .mb file (regardless of input type)", @@ -250,33 +256,13 @@ copy_maya_file(const Filename &source, const Filename &dest, maya_cat.debug() << "result = " << result3.asChar() << "\n"; } _exec_string.push_back("file -loadReference \"" + string(result.asChar()) + "\" -type \"mayaBinary\" -options \"v=0\" \"" + new_filename.to_os_generic() + "\";"); - //MGlobal::executeCommand("file -loadReference \"mtpRN\" -type \"mayaBinary\" -options \"v=0\" \"m_t_pear_zero.mb\";"); - maya_cat.info() << "executing command: " << _exec_string[_curr_idx] << "\n"; - status = MGlobal::executeCommand(MString(_exec_string[_curr_idx].c_str())); - if (status != MStatus::kSuccess) { - status.perror("loadReference failed"); - } - /* - Filename filename = - _path_replace->convert_path(Filename::from_os_specific(lookup)); - - CVSSourceTree::FilePath path = - _tree.choose_directory(filename.get_basename(), dir, _force, _interactive); - Filename new_filename = path.get_rel_from(dir); - - maya_cat.info() << "lookup filename: " << filename.to_os_generic() << "\n"; - string cmdStr = "chdir " + string(dir->get_fullpath().to_os_generic().c_str()) + ";"; - maya_cat.info() << "new filename (relative): " << new_filename.to_os_generic() << "\n"; - //maya_cat.info() << "new filename (absolute): " << path.get_fullpath().to_os_generic() << "\n"; - MString loadedFilename = MFileIO::loadReference(MString(new_filename.to_os_generic().c_str()), &status); - //MString loadedFilename = MFileIO::loadReference(MString(path.get_fullpath().to_os_generic().c_str()), &status); - //MString loadedFilename = MFileIO::loadReferenceByNode(result, &status); - maya_cat.info() << "loaded filename: " << loadedFilename << "\n"; - - if (status != MStatus::kSuccess) { - status.perror("loadReference failed"); - } - */ + if (!_omit_ref) { + maya_cat.info() << "executing command: " << _exec_string[_curr_idx] << "\n"; + status = MGlobal::executeCommand(MString(_exec_string[_curr_idx].c_str())); + if (status != MStatus::kSuccess) { + status.perror("loadReference failed"); + } + } _curr_idx++; } @@ -344,11 +330,13 @@ extract_texture(MayaShaderColorDef &color_def, CVSSourceDirectory *dir) { Filename texture_filename = _path_replace->convert_path(color_def._texture_filename); if (!texture_filename.exists()) { - nout << "*** Warning: texture " << texture_filename + nout << "*** Error: texture " << texture_filename << " does not exist.\n"; + return false; } else if (!texture_filename.is_regular_file()) { - nout << "*** Warning: texture " << texture_filename + nout << "*** Error: texture " << texture_filename << " is not a regular file.\n"; + return false; } else { ExtraData ed; ed._type = FT_texture; diff --git a/pandatool/src/mayaprogs/mayaCopy.h b/pandatool/src/mayaprogs/mayaCopy.h index c388405d94..18bba49c9e 100644 --- a/pandatool/src/mayaprogs/mayaCopy.h +++ b/pandatool/src/mayaprogs/mayaCopy.h @@ -69,6 +69,7 @@ private: bool _keep_ver; bool _omit_tex; + bool _omit_ref; int _curr_idx; bool _maya_ascii; /* diff --git a/pandatool/src/mayaprogs/mayaToEgg_client.cxx b/pandatool/src/mayaprogs/mayaToEgg_client.cxx new file mode 100755 index 0000000000..b40db443e9 --- /dev/null +++ b/pandatool/src/mayaprogs/mayaToEgg_client.cxx @@ -0,0 +1,372 @@ +// Filename: mayaToEgg.cxx +// Created by: drose (15Feb00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#include "mayaToEgg_client.h" +#include "mayaToEggConverter.h" +#include "config_mayaegg.h" +#include "config_maya.h" // for maya_cat +#include "globPattern.h" +#ifdef _WIN32 + #include "pystub.h" +#endif + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +MayaToEgg:: +MayaToEgg() : + SomethingToEgg("Maya", ".mb") +{ + add_path_replace_options(); + add_path_store_options(); + add_animation_options(); + add_units_options(); + add_normals_options(); + add_transform_options(); + + set_program_description + ("This program converts Maya model files to egg. Static and animatable " + "models can be converted, with polygon or NURBS output. Animation tables " + "can also be generated to apply to an animatable model."); + + add_option + ("p", "", 0, + "Generate polygon output only. Tesselate all NURBS surfaces to " + "polygons via the built-in Maya tesselator. The tesselation will " + "be based on the tolerance factor given by -ptol.", + &MayaToEgg::dispatch_none, &_polygon_output); + + add_option + ("ptol", "tolerance", 0, + "Specify the fit tolerance for Maya polygon tesselation. The smaller " + "the number, the more polygons will be generated. The default is " + "0.01.", + &MayaToEgg::dispatch_double, NULL, &_polygon_tolerance); + + add_option + ("bface", "", 0, + "Respect the Maya \"double sided\" rendering flag to indicate whether " + "polygons should be double-sided or single-sided. Since this flag " + "is set to double-sided by default in Maya, it is often better to " + "ignore this flag (unless your modelers are diligent in turning it " + "off where it is not desired). If this flag is not specified, the " + "default is to treat all polygons as single-sided, unless an " + "egg object type of \"double-sided\" is set.", + &MayaToEgg::dispatch_none, &_respect_maya_double_sided); + + add_option + ("suppress-vcolor", "", 0, + "Ignore vertex color for geometry that has a texture applied. " + "(This is the way Maya normally renders internally.) The egg flag " + "'vertex-color' may be applied to a particular model to override " + "this setting locally.", + &MayaToEgg::dispatch_none, &_suppress_vertex_color); + + add_option + ("keep-uvs", "", 0, + "Convert all UV sets on all vertices, even those that do not appear " + "to be referenced by any textures.", + &MayaToEgg::dispatch_none, &_keep_all_uvsets); + + add_option + ("round-uvs", "", 0, + "round up uv coordinates to the nearest 1/100th. i.e. -0.001 becomes" + "0.0; 0.444 becomes 0.44; 0.778 becomes 0.78.", + &MayaToEgg::dispatch_none, &_round_uvs); + + add_option + ("trans", "type", 0, + "Specifies which transforms in the Maya file should be converted to " + "transforms in the egg file. The option may be one of all, model, " + "dcs, or none. The default is model, which means only transforms on " + "nodes that have the model flag or the dcs flag are preserved.", + &MayaToEgg::dispatch_transform_type, NULL, &_transform_type); + + add_option + ("subroot", "name", 0, + "Specifies that only a subroot 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, &_subroots); + + 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 + ("exclude", "name", 0, + "Specifies that a subset of the geometry in the Maya file should " + "not 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.", + &MayaToEgg::dispatch_vector_string, NULL, &_excludes); + + add_option + ("ignore-slider", "name", 0, + "Specifies the name of a slider (blend shape deformer) that maya2egg " + "should not process. The slider will not be touched during conversion " + "and it will not become a part of the animation. This " + "parameter may including globbing characters, and it may be repeated " + "as needed.", + &MayaToEgg::dispatch_vector_string, NULL, &_ignore_sliders); + + add_option + ("force-joint", "name", 0, + "Specifies the name of a DAG node that maya2egg " + "should treat as a joint, even if it does not appear to be a Maya joint " + "and does not appear to be animated.", + &MayaToEgg::dispatch_vector_string, NULL, &_force_joints); + + add_option + ("v", "", 0, + "Increase verbosity. More v's means more verbose.", + &MayaToEgg::dispatch_count, NULL, &_verbose); + + // Unfortunately, the Maya API doesn't allow us to differentiate + // between relative and absolute pathnames--everything comes out as + // an absolute pathname, even if it is stored in the Maya file as a + // relative path. So we can't support -noabs. + remove_option("noabs"); + + _verbose = 0; + _polygon_tolerance = 0.01; + _transform_type = MayaToEggConverter::TT_model; + _got_tbnauto = true; + manager = new QueuedConnectionManager(); + reader = new QueuedConnectionReader(manager, 0); + writer = new ConnectionWriter(manager, 0); + server.set_host("localhost", 4242); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void MayaToEgg:: +run() { + // Set the verbose level by using Notify. + if (_verbose >= 3) { + maya_cat->set_severity(NS_spam); + mayaegg_cat->set_severity(NS_spam); + } else if (_verbose >= 2) { + maya_cat->set_severity(NS_debug); + mayaegg_cat->set_severity(NS_debug); + } else if (_verbose >= 1) { + maya_cat->set_severity(NS_info); + mayaegg_cat->set_severity(NS_info); + } + + // Let's convert the output file to a full path before we initialize + // Maya, since Maya now has a nasty habit of changing the current + // directory. + if (_got_output_filename) { + _output_filename.make_absolute(); + } + + nout << "Initializing Maya.\n"; + MayaToEggConverter converter(_program_name); + if (!converter.open_api()) { + nout << "Unable to initialize Maya.\n"; + exit(1); + } + + // Copy in the command-line parameters. + converter._polygon_output = _polygon_output; + converter._polygon_tolerance = _polygon_tolerance; + converter._respect_maya_double_sided = _respect_maya_double_sided; + converter._always_show_vertex_color = !_suppress_vertex_color; + converter._keep_all_uvsets = _keep_all_uvsets; + converter._round_uvs = _round_uvs; + converter._transform_type = _transform_type; + + vector_string::const_iterator si; + if (!_subroots.empty()) { + converter.clear_subroots(); + for (si = _subroots.begin(); si != _subroots.end(); ++si) { + converter.add_subroot(GlobPattern(*si)); + } + } + + if (!_subsets.empty()) { + converter.clear_subsets(); + for (si = _subsets.begin(); si != _subsets.end(); ++si) { + converter.add_subset(GlobPattern(*si)); + } + } + + if (!_excludes.empty()) { + converter.clear_excludes(); + for (si = _excludes.begin(); si != _excludes.end(); ++si) { + converter.add_exclude(GlobPattern(*si)); + } + } + + if (!_ignore_sliders.empty()) { + converter.clear_ignore_sliders(); + for (si = _ignore_sliders.begin(); si != _ignore_sliders.end(); ++si) { + converter.add_ignore_slider(GlobPattern(*si)); + } + } + + if (!_force_joints.empty()) { + converter.clear_force_joints(); + for (si = _force_joints.begin(); si != _force_joints.end(); ++si) { + converter.add_force_joint(GlobPattern(*si)); + } + } + + // Copy in the path and animation parameters. + apply_parameters(converter); + + // Set the coordinate system to match Maya's. + if (!_got_coordinate_system) { + _coordinate_system = converter._maya->get_coordinate_system(); + } + _data->set_coordinate_system(_coordinate_system); + + converter.set_egg_data(_data); + + if (!converter.convert_file(_input_filename)) { + nout << "Errors in conversion.\n"; + exit(1); + } + + // Use the standard Maya units, if the user didn't specify + // otherwise. This always returns centimeters, which is the way all + // Maya files are stored internally (and is the units returned by + // all of the API functions called here). + if (_input_units == DU_invalid) { + _input_units = converter.get_input_units(); + } + + write_egg_file(); + nout << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::dispatch_transform_type +// Access: Protected, Static +// Description: Dispatches a parameter that expects a +// MayaToEggConverter::TransformType option. +//////////////////////////////////////////////////////////////////// +bool MayaToEgg:: +dispatch_transform_type(const string &opt, const string &arg, void *var) { + MayaToEggConverter::TransformType *ip = (MayaToEggConverter::TransformType *)var; + (*ip) = MayaToEggConverter::string_transform_type(arg); + + if ((*ip) == MayaToEggConverter::TT_invalid) { + nout << "Invalid type for -" << opt << ": " << arg << "\n" + << "Valid types are all, model, dcs, and none.\n"; + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::poll +// Access: Public +// Description: Checks for any network activity and handles it, if +// appropriate, and then returns. This must be called +// periodically +//////////////////////////////////////////////////////////////////// +void MayaToEgg:: +poll() { + // Delete all the readers that we couldn't delete before. + while (!_lost_readers.empty()) { + QueuedConnectionReader *reader = _lost_readers.back(); + _lost_readers.pop_back(); + + delete reader; + } + while (!_removed_readers.empty()) { + QueuedConnectionReader *reader = _removed_readers.back(); + _removed_readers.pop_back(); + delete reader; + } + + // listener->poll(); + + Readers::const_iterator ri = _readers.begin(); + while (ri != _readers.end()) { + // Preincrement the iterator, in case we remove it as a result of + // calling poll(). + Readers::const_iterator rnext = ri; + ++rnext; + QueuedConnectionReader *reader = (*ri).second; + + reader->poll(); + + ri = rnext; + } +} + +int main(int argc, char *argv[]) { + // We don't want pystub on linux, since it gives problems with Maya's python. +#ifdef _WIN32 + // A call to pystub() to force libpystub.so to be linked in. + pystub(); +#endif + + MayaToEgg prog; + // prog.parse_command_line(argc, argv); + // prog.run(); + + // TODO: + // - Open a socket and wait for communications + // - When communication is received, send along argc and argv to + // prog.parase_command_line and prog.run() + // [ see commented out section above ] + // - Go back to waiting + PT(Connection) con = prog.manager->open_TCP_client_connection(prog.server,0); + if (con.is_null()) { + nout << "port opened fail"; + } + + prog.reader->add_connection(con); + + Filename cwd = ExecutionEnvironment::get_cwd(); + string s_cwd = (string)cwd.to_os_specific(); + nout << "CWD: " << s_cwd << "\n"; + + nout << "building datagram\n"; + NetDatagram datagram; + + datagram.add_uint8(argc); + + int i; + for (i = 0; i < argc; i++) { + datagram.add_string(argv[i]); + } + + datagram.add_string(s_cwd); + nout << "sending datagram\n"; + prog.writer->send(datagram, con); + prog.manager->close_connection(con); + return 0; +} + diff --git a/pandatool/src/mayaprogs/mayaToEgg_client.h b/pandatool/src/mayaprogs/mayaToEgg_client.h new file mode 100755 index 0000000000..a5952db498 --- /dev/null +++ b/pandatool/src/mayaprogs/mayaToEgg_client.h @@ -0,0 +1,64 @@ +// Filename: mayaToEgg.h +// Created by: drose (15Feb00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef MAYATOEGG_H +#define MAYATOEGG_H + +#include "pandatoolbase.h" +#include "somethingToEgg.h" +#include "mayaToEggConverter.h" +#include "queuedConnectionManager.h" +#include "queuedConnectionReader.h" +#include "connectionWriter.h" + +//////////////////////////////////////////////////////////////////// +// Class : MayaToEgg +// Description : +//////////////////////////////////////////////////////////////////// +class MayaToEgg : public SomethingToEgg { +public: + MayaToEgg(); + + void run(); + void poll(); + QueuedConnectionManager *manager; + QueuedConnectionReader *reader; + ConnectionWriter *writer; + NetAddress server; + +protected: + static bool dispatch_transform_type(const string &opt, const string &arg, void *var); + + int _verbose; + bool _polygon_output; + double _polygon_tolerance; + bool _respect_maya_double_sided; + bool _suppress_vertex_color; + bool _keep_all_uvsets; + bool _round_uvs; + MayaToEggConverter::TransformType _transform_type; + vector_string _subroots; + vector_string _subsets; + vector_string _excludes; + vector_string _ignore_sliders; + vector_string _force_joints; + + typedef pmap Readers; + Readers _readers; + typedef pvector LostReaders; + LostReaders _lost_readers; + LostReaders _removed_readers; +}; + +#endif diff --git a/pandatool/src/mayaprogs/mayaToEgg_server.cxx b/pandatool/src/mayaprogs/mayaToEgg_server.cxx new file mode 100755 index 0000000000..6deb109504 --- /dev/null +++ b/pandatool/src/mayaprogs/mayaToEgg_server.cxx @@ -0,0 +1,432 @@ +// Filename: mayaToEgg.cxx +// Created by: drose (15Feb00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifdef WIN32_VC +#include // for chdir +#endif +#include "mayaToEgg_server.h" +#include "mayaToEggConverter.h" +#include "config_mayaegg.h" +#include "config_maya.h" // for maya_cat +#include "globPattern.h" +#ifdef _WIN32 + #include "pystub.h" +#endif + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +MayaToEgg:: +MayaToEgg() : + SomethingToEgg("Maya", ".mb") +{ + add_path_replace_options(); + add_path_store_options(); + add_animation_options(); + add_units_options(); + add_normals_options(); + add_transform_options(); + + set_program_description + ("This program converts Maya model files to egg. Static and animatable " + "models can be converted, with polygon or NURBS output. Animation tables " + "can also be generated to apply to an animatable model."); + + add_option + ("p", "", 0, + "Generate polygon output only. Tesselate all NURBS surfaces to " + "polygons via the built-in Maya tesselator. The tesselation will " + "be based on the tolerance factor given by -ptol.", + &MayaToEgg::dispatch_none, &_polygon_output); + + add_option + ("ptol", "tolerance", 0, + "Specify the fit tolerance for Maya polygon tesselation. The smaller " + "the number, the more polygons will be generated. The default is " + "0.01.", + &MayaToEgg::dispatch_double, NULL, &_polygon_tolerance); + + add_option + ("bface", "", 0, + "Respect the Maya \"double sided\" rendering flag to indicate whether " + "polygons should be double-sided or single-sided. Since this flag " + "is set to double-sided by default in Maya, it is often better to " + "ignore this flag (unless your modelers are diligent in turning it " + "off where it is not desired). If this flag is not specified, the " + "default is to treat all polygons as single-sided, unless an " + "egg object type of \"double-sided\" is set.", + &MayaToEgg::dispatch_none, &_respect_maya_double_sided); + + add_option + ("suppress-vcolor", "", 0, + "Ignore vertex color for geometry that has a texture applied. " + "(This is the way Maya normally renders internally.) The egg flag " + "'vertex-color' may be applied to a particular model to override " + "this setting locally.", + &MayaToEgg::dispatch_none, &_suppress_vertex_color); + + add_option + ("keep-uvs", "", 0, + "Convert all UV sets on all vertices, even those that do not appear " + "to be referenced by any textures.", + &MayaToEgg::dispatch_none, &_keep_all_uvsets); + + add_option + ("round-uvs", "", 0, + "round up uv coordinates to the nearest 1/100th. i.e. -0.001 becomes" + "0.0; 0.444 becomes 0.44; 0.778 becomes 0.78.", + &MayaToEgg::dispatch_none, &_round_uvs); + + add_option + ("trans", "type", 0, + "Specifies which transforms in the Maya file should be converted to " + "transforms in the egg file. The option may be one of all, model, " + "dcs, or none. The default is model, which means only transforms on " + "nodes that have the model flag or the dcs flag are preserved.", + &MayaToEgg::dispatch_transform_type, NULL, &_transform_type); + + add_option + ("subroot", "name", 0, + "Specifies that only a subroot 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, &_subroots); + + 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 + ("exclude", "name", 0, + "Specifies that a subset of the geometry in the Maya file should " + "not 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.", + &MayaToEgg::dispatch_vector_string, NULL, &_excludes); + + add_option + ("ignore-slider", "name", 0, + "Specifies the name of a slider (blend shape deformer) that maya2egg " + "should not process. The slider will not be touched during conversion " + "and it will not become a part of the animation. This " + "parameter may including globbing characters, and it may be repeated " + "as needed.", + &MayaToEgg::dispatch_vector_string, NULL, &_ignore_sliders); + + add_option + ("force-joint", "name", 0, + "Specifies the name of a DAG node that maya2egg " + "should treat as a joint, even if it does not appear to be a Maya joint " + "and does not appear to be animated.", + &MayaToEgg::dispatch_vector_string, NULL, &_force_joints); + + add_option + ("v", "", 0, + "Increase verbosity. More v's means more verbose.", + &MayaToEgg::dispatch_count, NULL, &_verbose); + + // Unfortunately, the Maya API doesn't allow us to differentiate + // between relative and absolute pathnames--everything comes out as + // an absolute pathname, even if it is stored in the Maya file as a + // relative path. So we can't support -noabs. + remove_option("noabs"); + + _verbose = 0; + _polygon_tolerance = 0.01; + _transform_type = MayaToEggConverter::TT_model; + _got_tbnauto = true; + qManager = new QueuedConnectionManager(); + qListener = new QueuedConnectionListener(qManager, 0); + qReader = new QueuedConnectionReader(qManager, 0); + dummy = new MayaToEggConverter(); + nout << "Initializing Maya...\n"; + if (!dummy->open_api()) { + nout << "Unable to initialize May.\n"; + exit(1); + } +} +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +MayaToEgg:: +~MayaToEgg() { + delete qManager; + delete qReader; + delete qListener; + delete dummy; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void MayaToEgg:: +run() { + // Set the verbose level by using Notify. + if (_verbose >= 3) { + maya_cat->set_severity(NS_spam); + mayaegg_cat->set_severity(NS_spam); + } else if (_verbose >= 2) { + maya_cat->set_severity(NS_debug); + mayaegg_cat->set_severity(NS_debug); + } else if (_verbose >= 1) { + maya_cat->set_severity(NS_info); + mayaegg_cat->set_severity(NS_info); + } + + // Let's convert the output file to a full path before we initialize + // Maya, since Maya now has a nasty habit of changing the current + // directory. + if (_got_output_filename) { + _output_filename.make_absolute(); + } + + // Make sure we have good clean data to start with + _data = new EggData(); + + // So our relative path names come out correctly + _path_replace->_path_directory = get_output_filename().get_dirname(); + + MayaToEggConverter converter(_program_name); + + // Copy in the command-line parameters. + converter._polygon_output = _polygon_output; + converter._polygon_tolerance = _polygon_tolerance; + converter._respect_maya_double_sided = _respect_maya_double_sided; + converter._always_show_vertex_color = !_suppress_vertex_color; + converter._keep_all_uvsets = _keep_all_uvsets; + converter._round_uvs = _round_uvs; + converter._transform_type = _transform_type; + + vector_string::const_iterator si; + if (!_subroots.empty()) { + converter.clear_subroots(); + for (si = _subroots.begin(); si != _subroots.end(); ++si) { + converter.add_subroot(GlobPattern(*si)); + } + } + + if (!_subsets.empty()) { + converter.clear_subsets(); + for (si = _subsets.begin(); si != _subsets.end(); ++si) { + converter.add_subset(GlobPattern(*si)); + } + } + + if (!_excludes.empty()) { + converter.clear_excludes(); + for (si = _excludes.begin(); si != _excludes.end(); ++si) { + converter.add_exclude(GlobPattern(*si)); + } + } + + if (!_ignore_sliders.empty()) { + converter.clear_ignore_sliders(); + for (si = _ignore_sliders.begin(); si != _ignore_sliders.end(); ++si) { + converter.add_ignore_slider(GlobPattern(*si)); + } + } + + if (!_force_joints.empty()) { + converter.clear_force_joints(); + for (si = _force_joints.begin(); si != _force_joints.end(); ++si) { + converter.add_force_joint(GlobPattern(*si)); + } + } + + // Copy in the path and animation parameters. + apply_parameters(converter); + + // Set the coordinate system to match Maya's. + if (!_got_coordinate_system) { + _coordinate_system = converter._maya->get_coordinate_system(); + } + _data->set_coordinate_system(_coordinate_system); + + converter.set_egg_data(_data); + + if (!converter.convert_file(_input_filename)) { + nout << "Errors in conversion.\n"; + exit(1); + } + + // Use the standard Maya units, if the user didn't specify + // otherwise. This always returns centimeters, which is the way all + // Maya files are stored internally (and is the units returned by + // all of the API functions called here). + if (_input_units == DU_invalid) { + _input_units = converter.get_input_units(); + } + write_egg_file(); + + // Clean and out + close_output(); + _data->clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::dispatch_transform_type +// Access: Protected, Static +// Description: Dispatches a parameter that expects a +// MayaToEggConverter::TransformType option. +//////////////////////////////////////////////////////////////////// +bool MayaToEgg:: +dispatch_transform_type(const string &opt, const string &arg, void *var) { + MayaToEggConverter::TransformType *ip = (MayaToEggConverter::TransformType *)var; + (*ip) = MayaToEggConverter::string_transform_type(arg); + + if ((*ip) == MayaToEggConverter::TT_invalid) { + nout << "Invalid type for -" << opt << ": " << arg << "\n" + << "Valid types are all, model, dcs, and none.\n"; + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEgg::poll +// Access: Public +// Description: Checks for any network activity and handles it, if +// appropriate, and then returns. This must be called +// periodically +//////////////////////////////////////////////////////////////////// +void MayaToEgg:: +poll() { + // Listen for new connections + qListener->poll(); + + // If we have a new connection from a client create a new connection + // pointer and add it to the reader list + if (qListener->new_connection_available()) { + PT(Connection) con; + if (qListener->get_new_connection(con)) { + qReader->add_connection(con); + } + } + + // Poll the readers (created above) and if they have data process it + qReader->poll(); + if (qReader->data_available()) { + // Grab the incomming data and unpack it + NetDatagram datagram; + if (qReader->get_data(datagram)) { + DatagramIterator data(datagram); + nout << "receiving data\n"; + // First data should be the "argc" (argument count) from the client + int argc = data.get_uint8(); + + // Now we have to get clever because the rest of the data comes as strings + // and parse_command_line() expects arguments of the standard argc, argv*[] + // variety. + // First, we need a string vector to hold all the strings from the datagram. + // We also need a char * array to keep track of all the pointers we're gonna + // malloc. Needed later for cleanup. + vector_string vargv; + vector buffers; + + // Get the strings from the datagram and put them into the string vector + int i; + for ( i = 0; i < argc; i++ ) { + vargv.push_back(data.get_string()); + } + + // Last string is the current directory the client was run from. Not part of + // the argument list, but we still need it + string cwd = data.get_string(); + + // We allocate some memory to hold the pointers to the pointers we're going to + // pass in to parse_command_line(). + char ** cargv = (char**) malloc(sizeof(char**) * argc); + + // Loop through the string arguments we got from the datagram and convert + // them to const char *'s. parse_command_line() expects char *'s, so we have + // to copy these const versions into fresh char *, since there is no casting + // from const char * to char *. + for ( i = 0; i < argc; i++) { + // string to const char * + const char * cptr = vargv[i].c_str(); + // memory allocated for a new char * of size of the string + char * buffer = (char*) malloc(vargv[i].capacity()+1); + // Copy the const char * to the char * + strcpy(buffer, cptr); + // put this into the arry we defined above. This is what will eventually + // be passed to parse_command_line() + cargv[i] = buffer; + // keep track of the pointers to the allocated memory for cleanup later + buffers.push_back(buffer); + } + // Change to the client's current dir + chdir(cwd.c_str()); + + // Pass in the 'new' argc and argv we got from the client + this->parse_command_line(argc, cargv); + // Actually run the damn thing + this->run(); + + // Cleanup + // First, release the string vector + vargv.clear(); + // No, iterate through the char * vector and cleanup the malloc'd + // pointers + vector::iterator vi; + for ( vi = buffers.begin() ; vi != buffers.end(); vi++) { + free(*vi); + } + // Clean up the malloc'd pointer pointer + free(cargv); + } // qReader->get_data + } // qReader->data_available +} // poll + +int main(int argc, char *argv[]) { + // We don't want pystub on linux, since it gives problems with Maya's python. +#ifdef _WIN32 + // A call to pystub() to force libpystub.so to be linked in. + pystub(); +#endif + + MayaToEgg prog; + // Open a rendezvous port for receiving new connections from the client + PT(Connection) rend = prog.qManager->open_TCP_server_rendezvous(4242, 50); + if (rend.is_null()) { + nout << "port opened fail"; + } + + // Add this connection to the listeners list + prog.qListener->add_connection(rend); + + // Main loop. Keep polling for connections, but don't eat up all the CPU. + while (true) { + prog.poll(); + Thread::force_yield(); + } + return 0; +} + diff --git a/pandatool/src/mayaprogs/mayaToEgg_server.h b/pandatool/src/mayaprogs/mayaToEgg_server.h new file mode 100755 index 0000000000..0b1991463b --- /dev/null +++ b/pandatool/src/mayaprogs/mayaToEgg_server.h @@ -0,0 +1,63 @@ +// Filename: mayaToEgg.h +// Created by: drose (15Feb00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef MAYATOEGG_H +#define MAYATOEGG_H + +#include "pandatoolbase.h" +#include "somethingToEgg.h" +#include "mayaToEggConverter.h" +#include "queuedConnectionManager.h" +#include "queuedConnectionListener.h" +#include "queuedConnectionReader.h" + +//////////////////////////////////////////////////////////////////// +// Class : MayaToEgg +// Description : +//////////////////////////////////////////////////////////////////// +class MayaToEgg : public SomethingToEgg { +public: + MayaToEgg(); + ~MayaToEgg(); + + void run(); + void poll(); + + void add_reader(Connection *connection, QueuedConnectionReader *reader); + void remove_reader(Connection *connection, QueuedConnectionReader *reader); + QueuedConnectionManager *qManager; + QueuedConnectionListener *qListener; + QueuedConnectionReader *qReader; + MayaToEggConverter *dummy; + + +protected: + static bool dispatch_transform_type(const string &opt, const string &arg, void *var); + + int _verbose; + bool _polygon_output; + double _polygon_tolerance; + bool _respect_maya_double_sided; + bool _suppress_vertex_color; + bool _keep_all_uvsets; + bool _round_uvs; + MayaToEggConverter::TransformType _transform_type; + vector_string _subroots; + vector_string _subsets; + vector_string _excludes; + vector_string _ignore_sliders; + vector_string _force_joints; +}; + +#endif