Panda3D
somethingToEgg.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 somethingToEgg.cxx
10  * @author drose
11  * @date 2000-02-15
12  */
13 
14 #include "somethingToEgg.h"
16 
17 #include "config_putil.h"
18 
19 /**
20  * The first parameter to the constructor should be the one-word name of the
21  * file format that is to be read, for instance "OpenFlight" or "Alias". It's
22  * just used in printing error messages and such.
23  */
25 SomethingToEgg(const std::string &format_name,
26  const std::string &preferred_extension,
27  bool allow_last_param, bool allow_stdout) :
28  EggConverter(format_name, preferred_extension, allow_last_param, allow_stdout)
29 {
30  clear_runlines();
31  if (_allow_last_param) {
32  add_runline("[opts] input" + _preferred_extension + " output.egg");
33  }
34  add_runline("[opts] -o output.egg input" + _preferred_extension);
35  if (_allow_stdout) {
36  add_runline("[opts] input" + _preferred_extension + " >output.egg");
37  }
38 
39  // -f doesn't make sense if we aren't reading egg files.
40  remove_option("f");
41 
42  redescribe_option
43  ("cs",
44  "Specify the coordinate system of the input " + _format_name +
45  " file. Normally, this can inferred from the file itself.");
46 
47  add_option
48  ("noabs", "", 0,
49  "Don't allow the input " + _format_name + " file to have absolute pathnames. "
50  "If it does, abort with an error. This option is designed to help "
51  "detect errors when populating or building a standalone model tree, "
52  "which should be self-contained and include only relative pathnames.",
53  &SomethingToEgg::dispatch_none, &_noabs);
54 
55  add_option
56  ("noexist", "", 0,
57  "Don't treat it as an error if the input file references pathnames "
58  "(e.g. textures) that don't exist. Normally, this will be flagged as "
59  "an error and the command aborted; with this option, an egg file will "
60  "be generated anyway, referencing pathnames that do not exist.",
61  &SomethingToEgg::dispatch_none, &_noexist);
62 
63  add_option
64  ("ignore", "", 0,
65  "Ignore non-fatal errors and generate an egg file anyway.",
66  &SomethingToEgg::dispatch_none, &_allow_errors);
67 
68  _input_units = DU_invalid;
69  _output_units = DU_invalid;
70  _animation_convert = AC_none;
71  _got_start_frame = false;
72  _got_end_frame = false;
73  _got_frame_inc = false;
74  _got_neutral_frame = false;
75  _got_input_frame_rate = false;
76  _got_output_frame_rate = false;
77  _merge_externals = false;
78 }
79 
80 /**
81  * Adds -ui and -uo as valid options for this program. If the user specifies
82  * -uo and -ui, or just -uo and the program specifies -ui by setting
83  * _input_units, the indicated units conversion will be automatically applied
84  * before writing out the egg file.
85  */
88  add_option
89  ("ui", "units", 40,
90  "Specify the units of the input " + _format_name +
91  " file. Normally, this can be inferred from the file itself.",
92  &SomethingToEgg::dispatch_units, nullptr, &_input_units);
93 
94  add_option
95  ("uo", "units", 40,
96  "Specify the units of the resulting egg file. If this is "
97  "specified, the vertices in the egg file will be scaled as "
98  "necessary to make the appropriate units conversion; otherwise, "
99  "the vertices will be left as they are.",
100  &SomethingToEgg::dispatch_units, nullptr, &_output_units);
101 }
102 
103 /**
104  * Adds options appropriate to animation packages.
105  */
106 void SomethingToEgg::
108  add_option
109  ("a", "animation-mode", 40,
110  "Specifies how animation from the " + _format_name + " file is "
111  "converted to egg, if at all. At present, the following keywords "
112  "are supported: none, pose, flip, strobe, model, chan, or both. "
113  "The default is none, which means not to convert animation.",
114  &SomethingToEgg::dispatch_animation_convert, nullptr, &_animation_convert);
115 
116  add_option
117  ("cn", "name", 40,
118  "Specifies the name of the animation character. This should match "
119  "between all of the model files and all of the channel files for a "
120  "particular model and its associated channels.",
121  &SomethingToEgg::dispatch_string, nullptr, &_character_name);
122 
123  add_option
124  ("sf", "start-frame", 40,
125  "Specifies the starting frame of animation to extract. If omitted, "
126  "the first frame of the time slider will be used. For -a pose, this "
127  "is the one frame of animation to extract.",
128  &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame);
129 
130  add_option
131  ("ef", "end-frame", 40,
132  "Specifies the ending frame of animation to extract. If omitted, "
133  "the last frame of the time slider will be used.",
134  &SomethingToEgg::dispatch_double, &_got_end_frame, &_end_frame);
135 
136  add_option
137  ("if", "frame-inc", 40,
138  "Specifies the increment between successive frames. If omitted, "
139  "this is taken from the time slider settings, or 1.0 if the time "
140  "slider does not specify.",
141  &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc);
142 
143  add_option
144  ("nf", "neutral-frame", 40,
145  "Specifies the frame number to use for the neutral pose. The model "
146  "will be set to this frame before extracting out the neutral character. "
147  "If omitted, the current frame of the model is used. This is only "
148  "relevant for -a model or -a both.",
149  &SomethingToEgg::dispatch_double, &_got_neutral_frame, &_neutral_frame);
150 
151  add_option
152  ("fri", "fps", 40,
153  "Specify the frame rate (frames per second) of the input " + _format_name +
154  " file. Normally, this can be inferred from the file itself.",
155  &SomethingToEgg::dispatch_double, &_got_input_frame_rate, &_input_frame_rate);
156 
157  add_option
158  ("fro", "fps", 40,
159  "Specify the frame rate (frames per second) of the generated animation. "
160  "If this is specified, the animation speed is scaled by the appropriate "
161  "factor based on the frame rate of the input file (see -fri).",
162  &SomethingToEgg::dispatch_double, &_got_output_frame_rate, &_output_frame_rate);
163 }
164 
165 /**
166  * Adds -f.
167  */
168 void SomethingToEgg::
170  add_option
171  ("f", "", 40,
172  "Follow and convert all external references in the source file.",
173  &SomethingToEgg::dispatch_none, &_merge_externals);
174 }
175 
176 /**
177  * Applies the scale indicated by the input and output units to the indicated
178  * egg file. This is normally done automatically when the file is written
179  * out.
180  */
181 void SomethingToEgg::
182 apply_units_scale(EggData *data) {
183  if (_output_units != DU_invalid && _input_units != DU_invalid &&
184  _input_units != _output_units) {
185  nout << "Converting from " << format_long_unit(_input_units)
186  << " to " << format_long_unit(_output_units) << "\n";
187  double scale = convert_units(_input_units, _output_units);
188  data->transform(LMatrix4d::scale_mat(scale));
189  }
190 }
191 
192 /**
193  * Copies the relevant parameters specified by the user on the command line
194  * (if add_path_replace_options(), add_path_store_options(), or
195  * add_animation_options() was used) to the converter.
196  */
197 void SomethingToEgg::
198 apply_parameters(SomethingToEggConverter &converter) {
199  _path_replace->_noabs = _noabs;
200  _path_replace->_exists = !_noexist;
201  converter.set_path_replace(_path_replace);
202 
203  converter.set_animation_convert(_animation_convert);
204  converter.set_character_name(_character_name);
205  if (_got_start_frame) {
206  converter.set_start_frame(_start_frame);
207  }
208  if (_got_end_frame) {
209  converter.set_end_frame(_end_frame);
210  }
211  if (_got_frame_inc) {
212  converter.set_frame_inc(_frame_inc);
213  }
214  if (_got_neutral_frame) {
215  converter.set_neutral_frame(_neutral_frame);
216  }
217  if (_got_input_frame_rate) {
218  converter.set_input_frame_rate(_input_frame_rate);
219  }
220  if (_got_output_frame_rate) {
221  converter.set_output_frame_rate(_output_frame_rate);
222  }
223 }
224 
225 /**
226  *
227  */
228 bool SomethingToEgg::
229 handle_args(Args &args) {
230  if (_allow_last_param && !_got_output_filename && args.size() > 1) {
231  _got_output_filename = true;
232  _output_filename = Filename::from_os_specific(args.back());
233  args.pop_back();
234 
235  if (!(_output_filename.get_extension() == "egg")) {
236  nout << "Output filename " << _output_filename
237  << " does not end in .egg. If this is really what you intended, "
238  "use the -o output_file syntax.\n";
239  return false;
240  }
241 
242  if (!verify_output_file_safe()) {
243  return false;
244  }
245  }
246 
247  if (args.empty()) {
248  nout << "You must specify the " << _format_name
249  << " file to read on the command line.\n";
250  return false;
251  }
252 
253  if (args.size() != 1) {
254  nout << "You may only specify one " << _format_name
255  << " file to read on the command line. "
256  << "You specified: ";
257  Args::const_iterator ai;
258  for (ai = args.begin(); ai != args.end(); ++ai) {
259  nout << (*ai) << " ";
260  }
261  nout << "\n";
262  return false;
263  }
264 
265  _input_filename = Filename::from_os_specific(args[0]);
266 
267  if (!_input_filename.exists()) {
268  nout << "Cannot find input file " << _input_filename << "\n";
269  return false;
270  }
271 
272  if (!_got_path_directory && _got_output_filename) {
273  // Put in the name of the output directory.
274  _path_replace->_path_directory = _output_filename.get_dirname();
275  }
276 
277  return true;
278 }
279 
280 /**
281  * This is called after the command line has been completely processed, and it
282  * gives the program a chance to do some last-minute processing and validation
283  * of the options and arguments. It should return true if everything is fine,
284  * false if there is an error.
285  */
286 bool SomethingToEgg::
287 post_command_line() {
288  // Prepend the source filename to the model path.
289  ConfigVariableSearchPath &model_path = get_model_path();
290  Filename directory = _input_filename.get_dirname();
291  if (directory.empty()) {
292  directory = ".";
293  }
294  model_path.prepend_directory(directory);
295 
296  return EggConverter::post_command_line();
297 }
298 
299 /**
300  * Performs any processing of the egg file that is appropriate before writing
301  * it out. This includes any normal adjustments the user requested via -np,
302  * etc.
303  *
304  * Normally, you should not need to call this function directly;
305  * write_egg_file() calls it for you. You should call this only if you do not
306  * use write_egg_file() to write out the resulting egg file.
307  */
308 void SomethingToEgg::
309 post_process_egg_file() {
310  apply_units_scale(_data);
312 }
313 
314 /**
315  * Dispatch function to set the given animation convert mode according to the
316  * specified parameter. var is a pointer to an AnimationConvert variable.
317  */
318 bool SomethingToEgg::
319 dispatch_animation_convert(const std::string &opt, const std::string &arg, void *var) {
320  AnimationConvert *ip = (AnimationConvert *)var;
321  (*ip) = string_animation_convert(arg);
322  if ((*ip) == AC_invalid) {
323  nout << "Invalid keyword for -" << opt << ": " << arg << "\n";
324  return false;
325  }
326 
327  return true;
328 }
std::string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:358
This is similar to a ConfigVariableList, but it returns its list as a DSearchPath,...
void set_character_name(const std::string &character_name)
Specifies the name of the character generated.
AnimationConvert
This enumerated type lists the methods by which animation from an animation package might be represen...
string format_long_unit(DistanceUnit unit)
Returns the string representing the full name (plural) for the given unit.
void set_frame_inc(double frame_inc)
Specifies the increment between frames to extract.
void add_animation_options()
Adds options appropriate to animation packages.
double convert_units(DistanceUnit from, DistanceUnit to)
Returns the scaling factor that must be applied to convert from units of "from" to "to".
void set_neutral_frame(double neutral_frame)
Specifies the frame of animation to represent the neutral pose of the model.
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a general base class for programs that convert between egg files and some other format.
Definition: eggConverter.h:25
void set_start_frame(double start_frame)
Specifies the starting frame of the animation to convert, in the units specified by set_input_frame_r...
void set_end_frame(double end_frame)
Specifies the ending frame of the animation to convert, in the units specified by set_input_frame_rat...
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_path_replace(PathReplace *path_replace)
Replaces the PathReplace object (which specifies how to mangle paths from the source to the destinati...
void set_animation_convert(AnimationConvert animation_convert)
Specifies how source animation will be converted into egg structures.
virtual void post_process_egg_file()
Performs any processing of the egg file that is appropriate before writing it out.
Definition: eggWriter.cxx:112
AnimationConvert string_animation_convert(const std::string &str)
Converts from a string, as might be input by the user, to one of the known AnimationConvert types.
void add_merge_externals_options()
Adds -f.
void set_output_frame_rate(double output_frame_rate)
Specifies the number of frames per second that the resulting animation should be played at.
void set_input_frame_rate(double input_frame_rate)
Specifies the number of frames per second that is represented by the "frame" unit in the animation pa...
This is a base class for a family of converter classes that manage a conversion from some file type t...
void prepend_directory(const Filename &directory)
Adds a new directory to the front of the search list.
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
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
SomethingToEgg(const std::string &format_name, const std::string &preferred_extension=std::string(), bool allow_last_param=true, bool allow_stdout=true)
The first parameter to the constructor should be the one-word name of the file format that is to be r...
void add_units_options()
Adds -ui and -uo as valid options for this program.