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