Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/mayaprogs/mayaCopy.cxx

Go to the documentation of this file.
00001 // Filename: mayaCopy.cxx
00002 // Created by:  drose (10May02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "mayaCopy.h"
00020 #include "config_maya.h"
00021 #include "cvsSourceDirectory.h"
00022 #include "mayaShader.h"
00023 #include "dcast.h"
00024 
00025 #include "pre_maya_include.h"
00026 #include <maya/MStringArray.h>
00027 #include <maya/MFileIO.h>
00028 #include <maya/MItDag.h>
00029 #include <maya/MFnDagNode.h>
00030 #include <maya/MFnNurbsSurface.h>
00031 #include <maya/MFnMesh.h>
00032 #include <maya/MObject.h>
00033 #include <maya/MDagPath.h>
00034 #include <maya/MIntArray.h>
00035 #include "post_maya_include.h"
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: MayaCopy::Constructor
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 MayaCopy::
00043 MayaCopy() {
00044   set_program_description
00045     ("mayacopy copies one or more Maya .mb files into a "
00046      "CVS source hierarchy.  "
00047      "Rather than copying the named files immediately into the current "
00048      "directory, it first scans the entire source hierarchy, identifying all "
00049      "the already-existing files.  If the named file to copy matches the "
00050      "name of an already-existing file in the current directory or elsewhere "
00051      "in the hierarchy, that file is overwritten.  Other .mb files, as "
00052      "well as texture files, that are externally referenced by the "
00053      "named .mb file(s) are similarly copied.");
00054 
00055   clear_runlines();
00056   add_runline("[opts] file.mb [file.mb ... ]");
00057 
00058   add_option
00059     ("keepver", "", 0,
00060      "Don't attempt to strip the Maya version number from the tail of the "
00061      "source filename before it is copied into the tree.",
00062      &CVSCopy::dispatch_none, &_keep_ver);
00063 
00064   add_path_replace_options();
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: MayaCopy::run
00069 //       Access: Public
00070 //  Description:
00071 ////////////////////////////////////////////////////////////////////
00072 void MayaCopy::
00073 run() {
00074   _maya = MayaApi::open_api(_program_name);
00075   if (!_maya->is_valid()) {
00076     nout << "Unable to initialize Maya.\n";
00077     exit(1);
00078   }
00079 
00080   SourceFiles::iterator fi;
00081   for (fi = _source_files.begin(); fi != _source_files.end(); ++fi) {
00082     ExtraData ed;
00083     ed._type = FT_maya;
00084 
00085     CVSSourceDirectory *dest = import(*fi, &ed, _model_dir);
00086     if (dest == (CVSSourceDirectory *)NULL) {
00087       nout << "\nUnable to copy, aborting!\n\n";
00088       exit(1);
00089     }
00090   }
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: MayaCopy::copy_file
00095 //       Access: Protected, Virtual
00096 //  Description: Called by import() if verify_file() indicates that a
00097 //               file needs to be copied.  This does the actual copy
00098 //               of a file from source to destination.  If new_file is
00099 //               true, then dest does not already exist.
00100 ////////////////////////////////////////////////////////////////////
00101 bool MayaCopy::
00102 copy_file(const Filename &source, const Filename &dest,
00103           CVSSourceDirectory *dir, void *extra_data, bool new_file) {
00104   ExtraData *ed = (ExtraData *)extra_data;
00105   switch (ed->_type) {
00106   case FT_maya:
00107     return copy_maya_file(source, dest, dir);
00108 
00109   case FT_texture:
00110     return copy_texture(source, dest, dir);
00111   }
00112 
00113   nout << "Internal error: invalid type " << (int)ed->_type << "\n";
00114   return false;
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: MayaCopy::filter_filename
00119 //       Access: Protected, Virtual
00120 //  Description: Given a source filename (including the basename only,
00121 //               without a dirname), return the appropriate
00122 //               corresponding filename within the source directory.
00123 //               This may be used by derived classes to, for instance,
00124 //               strip a version number from the filename.
00125 ////////////////////////////////////////////////////////////////////
00126 string MayaCopy::
00127 filter_filename(const string &source) {
00128   if (_keep_ver) {
00129     return source;
00130   }
00131 
00132   size_t dot = source.rfind('.');
00133   size_t underscore = source.rfind("_v", dot);
00134 
00135   string extension = source.substr(dot);
00136   if (extension == ".ma") {
00137     // By convention, we always write out Maya binary files (even if
00138     // we receive a Maya ascii file for input).
00139     extension = ".mb";
00140   }
00141 
00142   if (underscore == string::npos) {
00143     // No version number appears to be present.
00144     return source.substr(0, dot) + extension;
00145   } else {
00146     return source.substr(0, underscore) + extension;
00147   }
00148 }
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: MayaCopy::copy_maya_file
00152 //       Access: Private
00153 //  Description:
00154 ////////////////////////////////////////////////////////////////////
00155 bool MayaCopy::
00156 copy_maya_file(const Filename &source, const Filename &dest,
00157                CVSSourceDirectory *dir) {
00158   if (!_maya->read(source)) {
00159     maya_cat.error()
00160       << "Unable to read " << source << "\n";
00161     return false;
00162   }
00163 
00164   // Get all the shaders so we can determine the set of textures.
00165   _shaders.clear();
00166   collect_shaders();
00167   int num_shaders = _shaders.get_num_shaders();
00168   for (int i = 0; i < num_shaders; i++) {
00169     MayaShader *shader = _shaders.get_shader(i);
00170     if (!extract_texture(shader->_color, dir)) {
00171       return false;
00172     }
00173     if (!extract_texture(shader->_transparency, dir)) {
00174       return false;
00175     }
00176   }
00177 
00178   // Get the set of externally referenced Maya files.
00179   MStringArray refs;
00180   MStatus status = MFileIO::getReferences(refs);
00181   if (!status) {
00182     status.perror("MItDag constructor");
00183     return false;
00184   }
00185 
00186   // Now write out the Maya file.
00187   if (!_maya->write(dest)) {
00188     maya_cat.error()
00189       << "Cannot write " << dest << "\n";
00190     return false;
00191   }
00192 
00193   // Finally, copy in any referenced Maya files.  This is untested code.
00194   unsigned int num_refs = refs.length();
00195   if (num_refs != 0) {
00196     maya_cat.warning()
00197       << "External references are not yet properly supported by mayacopy!\n";
00198   }
00199   for (unsigned int ref_index = 0; ref_index < num_refs; ref_index++) {
00200     Filename filename = 
00201       _path_replace->convert_path(refs[ref_index].asChar());
00202     maya_cat.warning()
00203       << "External ref: " << filename << "\n";
00204     /*
00205     ExtraData ed;
00206     ed._type = FT_maya;
00207 
00208     CVSSourceDirectory *dest = import(filename, &ed, _model_dir);
00209     if (dest == (CVSSourceDirectory *)NULL) {
00210       exit(1);
00211     }
00212     */
00213   }
00214 
00215   return true;
00216 }
00217 
00218 ////////////////////////////////////////////////////////////////////
00219 //     Function: MayaCopy::extract_texture
00220 //       Access: Private
00221 //  Description: Gets the texture out of the indicated color channel
00222 //               and copies it in, updating the channel with the new
00223 //               texture filename.  Returns true on success, false on
00224 //               failure.
00225 ////////////////////////////////////////////////////////////////////
00226 bool MayaCopy::
00227 extract_texture(MayaShaderColorDef &color_def, CVSSourceDirectory *dir) {
00228   if (color_def._has_texture) {
00229     Filename texture_filename = 
00230       _path_replace->convert_path(color_def._texture);
00231     if (!texture_filename.exists()) {
00232       nout << "*** Warning: texture " << texture_filename
00233            << " does not exist.\n";
00234     } else if (!texture_filename.is_regular_file()) {
00235       nout << "*** Warning: texture " << texture_filename
00236            << " is not a regular file.\n";
00237     } else {
00238       ExtraData ed;
00239       ed._type = FT_texture;
00240       
00241       CVSSourceDirectory *texture_dir =
00242         import(texture_filename, &ed, _map_dir);
00243       if (texture_dir == (CVSSourceDirectory *)NULL) {
00244         return false;
00245       }
00246       
00247       // Update the texture reference to point to the new texture
00248       // filename, relative to the maya file.
00249       Filename new_filename = dir->get_rel_to(texture_dir) + "/" +
00250         texture_filename.get_basename();
00251       color_def.reset_maya_texture(new_filename);
00252     }
00253   }
00254 
00255   return true;
00256 }
00257 
00258 ////////////////////////////////////////////////////////////////////
00259 //     Function: MayaCopy::copy_texture
00260 //       Access: Private
00261 //  Description:
00262 ////////////////////////////////////////////////////////////////////
00263 bool MayaCopy::
00264 copy_texture(const Filename &source, const Filename &dest,
00265              CVSSourceDirectory *dir) {
00266   if (!copy_binary_file(source, dest)) {
00267     return false;
00268   }
00269 
00270   return true;
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: MayaCopy::collect_shaders
00275 //       Access: Private
00276 //  Description: Recursively walks through the maya scene graph
00277 //               hierarchy, looking for shaders.
00278 ////////////////////////////////////////////////////////////////////
00279 bool MayaCopy::
00280 collect_shaders() {
00281   MStatus status;
00282 
00283   MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
00284   if (!status) {
00285     status.perror("MItDag constructor");
00286     return false;
00287   }
00288 
00289   // This while loop walks through the entire Maya hierarchy, one node
00290   // at a time.  Maya's MItDag object automatically performs a
00291   // depth-first traversal of its scene graph.
00292   bool all_ok = true;
00293   while (!dag_iterator.isDone()) {
00294     MDagPath dag_path;
00295     status = dag_iterator.getPath(dag_path);
00296     if (!status) {
00297       status.perror("MItDag::getPath");
00298     } else {
00299       if (!collect_shader_for_node(dag_path)) {
00300         all_ok = false;
00301       }
00302     }
00303 
00304     dag_iterator.next();
00305   }
00306 
00307   if (!all_ok) {
00308     nout << "Errors encountered in traversal.\n";
00309     return false;
00310   }
00311 
00312   return true;
00313 }
00314 
00315 ////////////////////////////////////////////////////////////////////
00316 //     Function: MayaCopy::collect_shader_for_node
00317 //       Access: Private
00318 //  Description: Gets the relevant shader on the current node, if it
00319 //               has one.
00320 ////////////////////////////////////////////////////////////////////
00321 bool MayaCopy::
00322 collect_shader_for_node(const MDagPath &dag_path) {
00323   MStatus status;
00324   MFnDagNode dag_node(dag_path, &status);
00325   if (!status) {
00326     status.perror("MFnDagNode constructor");
00327     return false;
00328   }
00329 
00330   if (dag_path.hasFn(MFn::kNurbsSurface)) {
00331     MFnNurbsSurface surface(dag_path, &status);
00332     if (status) {
00333       _shaders.find_shader_for_node(surface.object());
00334     }
00335 
00336   } else if (dag_path.hasFn(MFn::kMesh)) {
00337     MFnMesh mesh(dag_path, &status);
00338     if (status) {
00339       // Meshes may have multiple different shaders.
00340       MObjectArray shaders;
00341       MIntArray poly_shader_indices;
00342 
00343       status = mesh.getConnectedShaders(dag_path.instanceNumber(),
00344                                         shaders, poly_shader_indices);
00345       if (status) {
00346         unsigned int num_shaders = shaders.length();
00347         for (unsigned int shader_index = 0;
00348              shader_index < num_shaders; 
00349              shader_index++) {
00350           MObject engine = shaders[shader_index];
00351           _shaders.find_shader_for_shading_engine(engine);
00352         }
00353       }
00354     }
00355 
00356   } else {
00357     // Ignoring other kinds of node.
00358   }
00359 
00360   return true;
00361 }
00362 
00363 
00364 int main(int argc, char *argv[]) {
00365   MayaCopy prog;
00366   prog.parse_command_line(argc, argv);
00367   prog.run();
00368   return 0;
00369 }

Generated on Fri May 2 03:21:26 2003 for Panda-Tool by doxygen1.3