Panda3D
fltCopy.cxx
1 // Filename: fltCopy.cxx
2 // Created by: drose (01Nov00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "fltCopy.h"
16 
17 #include "cvsSourceDirectory.h"
18 #include "fltHeader.h"
19 #include "fltFace.h"
20 #include "fltExternalReference.h"
21 #include "fltError.h"
22 #include "dcast.h"
23 #include "pystub.h"
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: FltCopy::Constructor
27 // Access: Public
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 FltCopy::
31 FltCopy() {
32  set_program_brief("copy MultiGen .flt files into a CVS source hierarchy");
33  set_program_description
34  ("fltcopy copies one or more MultiGen .flt files into a "
35  "CVS source hierarchy. "
36  "Rather than copying the named files immediately into the current "
37  "directory, it first scans the entire source hierarchy, identifying all "
38  "the already-existing files. If the named file to copy matches the "
39  "name of an already-existing file in the current directory or elsewhere "
40  "in the hierarchy, that file is overwritten. Other .flt files, as "
41  "well as texture files, that are externally referenced by the "
42  "named .flt file(s) are similarly copied.");
43 
44  clear_runlines();
45  add_runline("[opts] file.flt [file.flt ... ]");
46 
47  add_path_replace_options();
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: FltCopy::run
52 // Access: Public
53 // Description:
54 ////////////////////////////////////////////////////////////////////
55 void FltCopy::
56 run() {
57  SourceFiles::iterator fi;
58  for (fi = _source_files.begin(); fi != _source_files.end(); ++fi) {
59  ExtraData ed;
60  ed._type = FT_flt;
61 
62  CVSSourceTree::FilePath dest = import(*fi, &ed, _model_dir);
63  if (!dest.is_valid()) {
64  exit(1);
65  }
66  }
67 }
68 
69 ////////////////////////////////////////////////////////////////////
70 // Function: FltCopy::copy_file
71 // Access: Protected, Virtual
72 // Description: Called by import() if verify_file() indicates that a
73 // file needs to be copied. This does the actual copy
74 // of a file from source to destination. If new_file is
75 // true, then dest does not already exist.
76 ////////////////////////////////////////////////////////////////////
77 bool FltCopy::
78 copy_file(const Filename &source, const Filename &dest,
79  CVSSourceDirectory *dir, void *extra_data, bool new_file) {
80  ExtraData *ed = (ExtraData *)extra_data;
81  switch (ed->_type) {
82  case FT_flt:
83  return copy_flt_file(source, dest, dir);
84 
85  case FT_texture:
86  return copy_texture(source, dest, dir, ed->_texture, new_file);
87  }
88 
89  nout << "Internal error: invalid type " << (int)ed->_type << "\n";
90  return false;
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: FltCopy::copy_flt_file
95 // Access: Private
96 // Description:
97 ////////////////////////////////////////////////////////////////////
98 bool FltCopy::
99 copy_flt_file(const Filename &source, const Filename &dest,
100  CVSSourceDirectory *dir) {
101  PT(FltHeader) header = new FltHeader(_path_replace);
102 
103  // We don't want to automatically generate .attr files--we'd rather
104  // write them out explicitly.
105  header->set_auto_attr_update(FltHeader::AU_none);
106 
107  FltError result = header->read_flt(source);
108  if (result != FE_ok) {
109  nout << "Cannot read " << source << ": " << result << "\n";
110  return false;
111  }
112 
113  header->check_version();
114 
115  // Now scan the flt file for nested references.
116  Refs refs;
117  Textures textures;
118  scan_flt(header, refs, textures);
119 
120  Refs::const_iterator ri;
121  for (ri = refs.begin(); ri != refs.end(); ++ri) {
122  FltExternalReference *ref = (*ri);
123  Filename ref_filename = ref->get_ref_filename();
124 
125  if (!ref_filename.exists()) {
126  nout << "*** Warning: external reference " << ref_filename
127  << " does not exist.\n";
128  } else {
129  ExtraData ed;
130  ed._type = FT_flt;
131 
132  CVSSourceTree::FilePath ref_path =
133  import(ref_filename, &ed, _model_dir);
134  if (!ref_path.is_valid()) {
135  return false;
136  }
137 
138  // Update the reference to point to the new flt filename, relative
139  // to the base flt file.
140  ref->set_ref_filename(ref_path.get_rel_from(dir));
141  }
142  }
143 
144  // Remove all the textures from the palette, and then add back only
145  // those we found in use. This way we don't copy a file that
146  // references bogus textures.
147  header->clear_textures();
148 
149  Textures::const_iterator ti;
150  for (ti = textures.begin(); ti != textures.end(); ++ti) {
151  FltTexture *tex = (*ti);
152  Filename texture_filename = tex->get_texture_filename();
153 
154  if (!texture_filename.exists()) {
155  nout << "*** Warning: texture " << texture_filename
156  << " does not exist.\n";
157  } else {
158  ExtraData ed;
159  ed._type = FT_texture;
160  ed._texture = tex;
161 
162  CVSSourceTree::FilePath texture_path =
163  import(texture_filename, &ed, _map_dir);
164  if (!texture_path.is_valid()) {
165  return false;
166  }
167 
168  // Update the texture reference to point to the new texture
169  // filename, relative to the flt file.
170  tex->set_texture_filename(texture_path.get_rel_from(dir));
171  header->add_texture(tex);
172  }
173  }
174 
175  // Finally, write the resulting file out.
176  result = header->write_flt(dest);
177  if (result != FE_ok) {
178  nout << "Cannot write " << dest << "\n";
179  return false;
180  }
181 
182  return true;
183 }
184 
185 ////////////////////////////////////////////////////////////////////
186 // Function: FltCopy::copy_texture
187 // Access: Private
188 // Description:
189 ////////////////////////////////////////////////////////////////////
190 bool FltCopy::
191 copy_texture(const Filename &source, const Filename &dest,
192  CVSSourceDirectory *dir, FltTexture *tex, bool new_file) {
193  if (!copy_binary_file(source, dest)) {
194  return false;
195  }
196 
197  // Also write out the .attr file.
198  Filename attr_filename = dest.get_fullpath() + ".attr";
199  if (!attr_filename.exists()) {
200  new_file = true;
201  }
202 
203  tex->write_attr_data(attr_filename);
204 
205  if (new_file) {
206  cvs_add(attr_filename);
207  }
208 
209  return true;
210 }
211 
212 ////////////////////////////////////////////////////////////////////
213 // Function: FltCopy::scan_flt
214 // Access: Private
215 // Description: Recursively walks through the flt file hierarchy,
216 // looking for texture references and external flt file
217 // references.
218 ////////////////////////////////////////////////////////////////////
219 void FltCopy::
220 scan_flt(FltRecord *record, FltCopy::Refs &refs, FltCopy::Textures &textures) {
221  if (record->is_of_type(FltFace::get_class_type())) {
222  FltFace *face;
223  DCAST_INTO_V(face, record);
224  if (face->has_texture()) {
225  textures.insert(face->get_texture());
226  }
227 
228  } else if (record->is_of_type(FltExternalReference::get_class_type())) {
230  DCAST_INTO_V(ref, record);
231 
232  refs.insert(ref);
233  }
234 
235  int i;
236  int num_subfaces = record->get_num_subfaces();
237  for (i = 0; i < num_subfaces; i++) {
238  scan_flt(record->get_subface(i), refs, textures);
239  }
240 
241  int num_children = record->get_num_children();
242  for (i = 0; i < num_children; i++) {
243  scan_flt(record->get_child(i), refs, textures);
244  }
245 }
246 
247 
248 int main(int argc, char *argv[]) {
249  // A call to pystub() to force libpystub.so to be linked in.
250  pystub();
251 
252  FltCopy prog;
253  prog.parse_command_line(argc, argv);
254  prog.run();
255  return 0;
256 }
bool is_valid() const
Returns true if this FilePath represents a valid file, or false if it represents an error return...
Filename get_texture_filename() const
Returns the name of the texture image file.
Definition: fltTexture.cxx:109
string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition: filename.I:398
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
void set_texture_filename(const Filename &filename)
Changes the name of the texture image file.
Definition: fltTexture.cxx:119
int get_num_children() const
Returns the number of child records of this record.
Definition: fltRecord.cxx:70
void set_ref_filename(const Filename &filename)
Changes the name of the referenced file.
A single face bead, e.g.
Definition: fltFace.h:26
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:48
FltError write_attr_data() const
Writes the texture&#39;s .attr file.
Definition: fltTexture.cxx:192
FltRecord * get_subface(int n) const
Returns the nth subface of this record.
Definition: fltRecord.cxx:125
This represents one particular directory in the hierarchy of source directory files.
Represents a single texture in the texture palette.
Definition: fltTexture.h:29
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:40
A program to copy Multigen .flt files into the cvs tree.
Definition: fltCopy.h:37
An external reference to another flt file (possibly to a specific bead within the flt file)...
FltRecord * get_child(int n) const
Returns the nth child of this record.
Definition: fltRecord.cxx:80
Filename get_ref_filename() const
Returns the name of the referenced file.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
bool has_texture() const
Returns true if the face has a texture applied, false otherwise.
Definition: fltGeometry.I:23
Filename get_rel_from(const CVSSourceDirectory *other) const
Returns the relative path to this file as seen from the indicated source directory.
FltTexture * get_texture() const
Returns the texture applied to this face, or NULL if no texture was applied.
Definition: fltGeometry.I:34
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356
int get_num_subfaces() const
Returns the number of subface records of this record.
Definition: fltRecord.cxx:115