Panda3D
eggMultiFilter.cxx
1 // Filename: eggMultiFilter.cxx
2 // Created by: drose (02Nov00)
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 "eggMultiFilter.h"
16 
17 #include "pnotify.h"
18 #include "eggData.h"
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: EggMultiFilter::Constructor
22 // Access: Public
23 // Description:
24 ////////////////////////////////////////////////////////////////////
25 EggMultiFilter::
26 EggMultiFilter(bool allow_empty) : _allow_empty(allow_empty) {
27  clear_runlines();
28  add_runline("-o output.egg [opts] input.egg");
29  add_runline("-d dirname [opts] file.egg [file.egg ...]");
30  add_runline("-inplace [opts] file.egg [file.egg ...]");
31  add_runline("-inf input_list_filename [opts]");
32 
33  add_option
34  ("o", "filename", 50,
35  "Specify the filename to which the resulting egg file will be written. "
36  "This is only valid when there is only one input egg file on the command "
37  "line. If you want to process multiple files simultaneously, you must "
38  "use either -d or -inplace.",
39  &EggMultiFilter::dispatch_filename, &_got_output_filename, &_output_filename);
40 
41  add_option
42  ("d", "dirname", 50,
43  "Specify the name of the directory in which to write the resulting egg "
44  "files. If you are processing only one egg file, this may be omitted "
45  "in lieu of the -o option. If you are processing multiple egg files, "
46  "this may be omitted only if you specify -inplace instead.",
47  &EggMultiFilter::dispatch_filename, &_got_output_dirname, &_output_dirname);
48 
49  add_option
50  ("inplace", "", 50,
51  "If this option is given, the input egg files will be rewritten in "
52  "place with the results. This obviates the need to specify -d "
53  "for an output directory; however, it's risky because the original "
54  "input egg files are lost.",
55  &EggMultiFilter::dispatch_none, &_inplace);
56 
57  add_option
58  ("inf", "filename", 95,
59  "Reads input args from a text file instead of the command line. "
60  "Useful for really, really large lists of args that break the "
61  "OS-imposed limits on the length of command lines.",
62  &EggMultiFilter::dispatch_filename, &_got_input_filename, &_input_filename);
63 
64  // Derived programs will set this true when they discover some
65  // command-line option that will prevent the program from generating
66  // output. This removes some checks for an output specification in
67  // handle_args.
68  _read_only = false;
69 }
70 
71 
72 ////////////////////////////////////////////////////////////////////
73 // Function: EggMultiFilter::handle_args
74 // Access: Protected, Virtual
75 // Description: Does something with the additional arguments on the
76 // command line (after all the -options have been
77 // parsed). Returns true if the arguments are good,
78 // false otherwise.
79 ////////////////////////////////////////////////////////////////////
80 bool EggMultiFilter::
81 handle_args(ProgramBase::Args &args) {
82  if (_got_input_filename) {
83  nout << "Populating args from input file: " << _input_filename << "\n";
84  // Makes sure the file is set is_text
85  _filename = Filename::text_filename(_input_filename);
86  ifstream input;
87  if (!_filename.open_read(input)) {
88  nout << "Error opening file: " << _input_filename << "\n";
89  return false;
90  }
91  string line;
92  // File should be a space-delimited list of egg files
93  while (getline(input, line, ' ')) {
94  args.push_back(line);
95  }
96  }
97  if (args.empty()) {
98  if (!_allow_empty) {
99  nout << "You must specify the egg file(s) to read on the command line.\n";
100  return false;
101  }
102  } else {
103  // These only apply if we have specified any egg files.
104  if (_got_output_filename && args.size() == 1) {
105  if (_got_output_dirname) {
106  nout << "Cannot specify both -o and -d.\n";
107  return false;
108  } else if (_inplace) {
109  nout << "Cannot specify both -o and -inplace.\n";
110  return false;
111  }
112 
113  } else {
114  if (_got_output_filename) {
115  nout << "Cannot use -o when multiple egg files are specified.\n";
116  return false;
117  }
118 
119  if (_got_output_dirname && _inplace) {
120  nout << "Cannot specify both -inplace and -d.\n";
121  return false;
122 
123  } else if (!_got_output_dirname && !_inplace) {
124  if (!_read_only) {
125  nout << "You must specify either -inplace or -d.\n";
126  return false;
127  }
128  }
129  }
130  }
131 
132  // We need to set up _path_replace before we call read_egg().
133  if (!_got_path_directory) {
134  // Put in the name of the output directory.
135  if (_got_output_filename) {
136  _path_replace->_path_directory = _output_filename.get_dirname();
137  } else if (_got_output_dirname) {
138  _path_replace->_path_directory = _output_dirname;
139  }
140  }
141 
142  Args::const_iterator ai;
143  for (ai = args.begin(); ai != args.end(); ++ai) {
144  PT(EggData) data = read_egg(Filename::from_os_specific(*ai));
145  if (data == (EggData *)NULL) {
146  // Rather than returning false, we simply exit here, so the
147  // ProgramBase won't try to tell the user how to run the program
148  // just because we got a bad egg file.
149  exit(1);
150  }
151 
152  _eggs.push_back(data);
153  }
154 
155  return true;
156 }
157 
158 ////////////////////////////////////////////////////////////////////
159 // Function: EggMultiFilter::post_command_line
160 // Access: Protected, Virtual
161 // Description:
162 ////////////////////////////////////////////////////////////////////
163 bool EggMultiFilter::
164 post_command_line() {
165  Eggs::iterator ei;
166  for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
167  EggData *data = (*ei);
168  if (_got_coordinate_system) {
169  data->set_coordinate_system(_coordinate_system);
170  }
171  append_command_comment(data);
172  }
173 
174  return EggMultiBase::post_command_line();
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: EggMultiFilter::get_output_filename
179 // Access: Protected
180 // Description: Returns the output filename of the egg file with the
181 // given input filename. This is based on the user's
182 // choice of -inplace, -o, or -d.
183 ////////////////////////////////////////////////////////////////////
184 Filename EggMultiFilter::
185 get_output_filename(const Filename &source_filename) const {
186  if (_got_output_filename) {
187  nassertr(!_inplace && !_got_output_dirname && _eggs.size() == 1, Filename());
188  return _output_filename;
189 
190  } else if (_got_output_dirname) {
191  nassertr(!_inplace, Filename());
192  Filename result = source_filename;
193  result.set_dirname(_output_dirname);
194  return result;
195  }
196 
197  nassertr(_inplace, Filename());
198  return source_filename;
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: EggMultiFilter::write_eggs
203 // Access: Protected, Virtual
204 // Description: Writes out all of the egg files in the _eggs vector,
205 // to the output directory if one is specified, or over
206 // the input files if -inplace was specified.
207 ////////////////////////////////////////////////////////////////////
208 void EggMultiFilter::
209 write_eggs() {
210  nassertv(!_read_only);
212  Eggs::iterator ei;
213  for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
214  EggData *data = (*ei);
215  Filename filename = get_output_filename(data->get_egg_filename());
216 
217  nout << "Writing " << filename << "\n";
218  filename.make_dir();
219  if (!data->write_egg(filename)) {
220  // Error writing an egg file; abort.
221  exit(1);
222  }
223  }
224 }
bool write_egg(Filename filename)
The main interface for writing complete egg files.
Definition: eggData.cxx:243
const Filename & get_egg_filename() const
Returns the directory in which the egg file is considered to reside.
Definition: eggData.I:135
This is the primary interface into all the egg data, and the root of the egg file structure...
Definition: eggData.h:41
void set_coordinate_system(CoordinateSystem coordsys)
Changes the coordinate system of the EggData.
Definition: eggData.cxx:279
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
void set_dirname(const string &s)
Replaces the directory part of the filename.
Definition: filename.cxx:726
void post_process_egg_files()
Performs any processing of the egg file(s) that is appropriate before writing them out...
bool make_dir() const
Creates all the directories in the path to the file specified in the filename, except for the basenam...
Definition: filename.cxx:2730
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).
Definition: filename.cxx:332