Panda3D
 All Classes Functions Variables Enumerations
fltCopy.cxx
00001 // Filename: fltCopy.cxx
00002 // Created by:  drose (01Nov00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "fltCopy.h"
00016 
00017 #include "cvsSourceDirectory.h"
00018 #include "fltHeader.h"
00019 #include "fltFace.h"
00020 #include "fltExternalReference.h"
00021 #include "fltError.h"
00022 #include "dcast.h"
00023 #include "pystub.h"
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: FltCopy::Constructor
00027 //       Access: Public
00028 //  Description:
00029 ////////////////////////////////////////////////////////////////////
00030 FltCopy::
00031 FltCopy() {
00032   set_program_description
00033     ("fltcopy copies one or more MultiGen .flt files into a "
00034      "CVS source hierarchy.  "
00035      "Rather than copying the named files immediately into the current "
00036      "directory, it first scans the entire source hierarchy, identifying all "
00037      "the already-existing files.  If the named file to copy matches the "
00038      "name of an already-existing file in the current directory or elsewhere "
00039      "in the hierarchy, that file is overwritten.  Other .flt files, as "
00040      "well as texture files, that are externally referenced by the "
00041      "named .flt file(s) are similarly copied.");
00042 
00043   clear_runlines();
00044   add_runline("[opts] file.flt [file.flt ... ]");
00045 
00046   add_path_replace_options();
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: FltCopy::run
00051 //       Access: Public
00052 //  Description:
00053 ////////////////////////////////////////////////////////////////////
00054 void FltCopy::
00055 run() {
00056   SourceFiles::iterator fi;
00057   for (fi = _source_files.begin(); fi != _source_files.end(); ++fi) {
00058     ExtraData ed;
00059     ed._type = FT_flt;
00060 
00061     CVSSourceTree::FilePath dest = import(*fi, &ed, _model_dir);
00062     if (!dest.is_valid()) {
00063       exit(1);
00064     }
00065   }
00066 }
00067 
00068 ////////////////////////////////////////////////////////////////////
00069 //     Function: FltCopy::copy_file
00070 //       Access: Protected, Virtual
00071 //  Description: Called by import() if verify_file() indicates that a
00072 //               file needs to be copied.  This does the actual copy
00073 //               of a file from source to destination.  If new_file is
00074 //               true, then dest does not already exist.
00075 ////////////////////////////////////////////////////////////////////
00076 bool FltCopy::
00077 copy_file(const Filename &source, const Filename &dest,
00078           CVSSourceDirectory *dir, void *extra_data, bool new_file) {
00079   ExtraData *ed = (ExtraData *)extra_data;
00080   switch (ed->_type) {
00081   case FT_flt:
00082     return copy_flt_file(source, dest, dir);
00083 
00084   case FT_texture:
00085     return copy_texture(source, dest, dir, ed->_texture, new_file);
00086   }
00087 
00088   nout << "Internal error: invalid type " << (int)ed->_type << "\n";
00089   return false;
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: FltCopy::copy_flt_file
00094 //       Access: Private
00095 //  Description:
00096 ////////////////////////////////////////////////////////////////////
00097 bool FltCopy::
00098 copy_flt_file(const Filename &source, const Filename &dest,
00099               CVSSourceDirectory *dir) {
00100   PT(FltHeader) header = new FltHeader(_path_replace);
00101 
00102   // We don't want to automatically generate .attr files--we'd rather
00103   // write them out explicitly.
00104   header->set_auto_attr_update(FltHeader::AU_none);
00105 
00106   FltError result = header->read_flt(source);
00107   if (result != FE_ok) {
00108     nout << "Cannot read " << source << ": " << result << "\n";
00109     return false;
00110   }
00111 
00112   header->check_version();
00113 
00114   // Now scan the flt file for nested references.
00115   Refs refs;
00116   Textures textures;
00117   scan_flt(header, refs, textures);
00118 
00119   Refs::const_iterator ri;
00120   for (ri = refs.begin(); ri != refs.end(); ++ri) {
00121     FltExternalReference *ref = (*ri);
00122     Filename ref_filename = ref->get_ref_filename();
00123 
00124     if (!ref_filename.exists()) {
00125       nout << "*** Warning: external reference " << ref_filename
00126            << " does not exist.\n";
00127     } else {
00128       ExtraData ed;
00129       ed._type = FT_flt;
00130 
00131       CVSSourceTree::FilePath ref_path =
00132         import(ref_filename, &ed, _model_dir);
00133       if (!ref_path.is_valid()) {
00134         return false;
00135       }
00136 
00137       // Update the reference to point to the new flt filename, relative
00138       // to the base flt file.
00139       ref->set_ref_filename(ref_path.get_rel_from(dir));
00140     }
00141   }
00142 
00143   // Remove all the textures from the palette, and then add back only
00144   // those we found in use.  This way we don't copy a file that
00145   // references bogus textures.
00146   header->clear_textures();
00147 
00148   Textures::const_iterator ti;
00149   for (ti = textures.begin(); ti != textures.end(); ++ti) {
00150     FltTexture *tex = (*ti);
00151     Filename texture_filename = tex->get_texture_filename();
00152 
00153     if (!texture_filename.exists()) {
00154       nout << "*** Warning: texture " << texture_filename
00155            << " does not exist.\n";
00156     } else {
00157       ExtraData ed;
00158       ed._type = FT_texture;
00159       ed._texture = tex;
00160 
00161       CVSSourceTree::FilePath texture_path =
00162         import(texture_filename, &ed, _map_dir);
00163       if (!texture_path.is_valid()) {
00164         return false;
00165       }
00166 
00167       // Update the texture reference to point to the new texture
00168       // filename, relative to the flt file.
00169       tex->set_texture_filename(texture_path.get_rel_from(dir));
00170       header->add_texture(tex);
00171     }
00172   }
00173 
00174   // Finally, write the resulting file out.
00175   result = header->write_flt(dest);
00176   if (result != FE_ok) {
00177     nout << "Cannot write " << dest << "\n";
00178     return false;
00179   }
00180 
00181   return true;
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: FltCopy::copy_texture
00186 //       Access: Private
00187 //  Description:
00188 ////////////////////////////////////////////////////////////////////
00189 bool FltCopy::
00190 copy_texture(const Filename &source, const Filename &dest,
00191              CVSSourceDirectory *dir, FltTexture *tex, bool new_file) {
00192   if (!copy_binary_file(source, dest)) {
00193     return false;
00194   }
00195 
00196   // Also write out the .attr file.
00197   Filename attr_filename = dest.get_fullpath() + ".attr";
00198   if (!attr_filename.exists()) {
00199     new_file = true;
00200   }
00201 
00202   tex->write_attr_data(attr_filename);
00203 
00204   if (new_file) {
00205     cvs_add(attr_filename);
00206   }
00207 
00208   return true;
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: FltCopy::scan_flt
00213 //       Access: Private
00214 //  Description: Recursively walks through the flt file hierarchy,
00215 //               looking for texture references and external flt file
00216 //               references.
00217 ////////////////////////////////////////////////////////////////////
00218 void FltCopy::
00219 scan_flt(FltRecord *record, FltCopy::Refs &refs, FltCopy::Textures &textures) {
00220   if (record->is_of_type(FltFace::get_class_type())) {
00221     FltFace *face;
00222     DCAST_INTO_V(face, record);
00223     if (face->has_texture()) {
00224       textures.insert(face->get_texture());
00225     }
00226 
00227   } else if (record->is_of_type(FltExternalReference::get_class_type())) {
00228     FltExternalReference *ref;
00229     DCAST_INTO_V(ref, record);
00230 
00231     refs.insert(ref);
00232   }
00233 
00234   int i;
00235   int num_subfaces = record->get_num_subfaces();
00236   for (i = 0; i < num_subfaces; i++) {
00237     scan_flt(record->get_subface(i), refs, textures);
00238   }
00239 
00240   int num_children = record->get_num_children();
00241   for (i = 0; i < num_children; i++) {
00242     scan_flt(record->get_child(i), refs, textures);
00243   }
00244 }
00245 
00246 
00247 int main(int argc, char *argv[]) {
00248   // A call to pystub() to force libpystub.so to be linked in.
00249   pystub();
00250 
00251   FltCopy prog;
00252   prog.parse_command_line(argc, argv);
00253   prog.run();
00254   return 0;
00255 }
 All Classes Functions Variables Enumerations