Panda3D
|
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 }