From e2393582ba2e2da4d665d9fb5cc878f64a0df633 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 12 Apr 2001 03:52:59 +0000 Subject: [PATCH] *** empty log message *** --- pandatool/src/eggbase/eggConverter.cxx | 6 +- pandatool/src/eggbase/eggConverter.h | 1 - pandatool/src/eggbase/eggFilter.cxx | 2 +- pandatool/src/eggbase/eggToSomething.cxx | 19 +-- pandatool/src/eggbase/eggWriter.cxx | 130 +--------------- pandatool/src/eggbase/eggWriter.h | 16 +- pandatool/src/eggprogs/eggTextureCards.cxx | 2 +- pandatool/src/flt/Sources.pp | 14 -- pandatool/src/flt/fltGeometry.cxx | 13 +- pandatool/src/flt/fltHeader.cxx | 92 ++++++++--- pandatool/src/flt/fltHeader.h | 1 + pandatool/src/flt/fltMaterial.cxx | 31 ++++ pandatool/src/flt/fltMaterial.h | 1 + pandatool/src/flt/fltVertex.cxx | 63 +++++--- pandatool/src/flt/test_flt.cxx | 63 -------- pandatool/src/fltprogs/Sources.pp | 14 ++ pandatool/src/fltprogs/fltTrans.cxx | 130 ++++++++++++++++ pandatool/src/fltprogs/fltTrans.h | 38 +++++ pandatool/src/progbase/Sources.pp | 8 +- pandatool/src/progbase/withOutputFile.cxx | 169 +++++++++++++++++++++ pandatool/src/progbase/withOutputFile.h | 53 +++++++ 21 files changed, 587 insertions(+), 279 deletions(-) delete mode 100644 pandatool/src/flt/test_flt.cxx create mode 100644 pandatool/src/fltprogs/fltTrans.cxx create mode 100644 pandatool/src/fltprogs/fltTrans.h create mode 100644 pandatool/src/progbase/withOutputFile.cxx create mode 100644 pandatool/src/progbase/withOutputFile.h diff --git a/pandatool/src/eggbase/eggConverter.cxx b/pandatool/src/eggbase/eggConverter.cxx index f4aebdbc80..4e706e3c86 100644 --- a/pandatool/src/eggbase/eggConverter.cxx +++ b/pandatool/src/eggbase/eggConverter.cxx @@ -22,7 +22,9 @@ EggConverter(const string &format_name, bool allow_last_param, bool allow_stdout) : EggFilter(allow_last_param, allow_stdout), - _format_name(format_name), - _preferred_extension(preferred_extension) + _format_name(format_name) { + // Indicate the extension name we expect the user to supply for + // output files. + _preferred_extension = preferred_extension; } diff --git a/pandatool/src/eggbase/eggConverter.h b/pandatool/src/eggbase/eggConverter.h index 01b6de843a..f6565f5746 100644 --- a/pandatool/src/eggbase/eggConverter.h +++ b/pandatool/src/eggbase/eggConverter.h @@ -25,7 +25,6 @@ public: protected: string _format_name; - string _preferred_extension; }; #endif diff --git a/pandatool/src/eggbase/eggFilter.cxx b/pandatool/src/eggbase/eggFilter.cxx index 145c0eccca..1e41aab127 100644 --- a/pandatool/src/eggbase/eggFilter.cxx +++ b/pandatool/src/eggbase/eggFilter.cxx @@ -42,7 +42,7 @@ EggFilter(bool allow_last_param, bool allow_stdout) : //////////////////////////////////////////////////////////////////// bool EggFilter:: handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args)) { + if (!check_last_arg(args, 0)) { return false; } diff --git a/pandatool/src/eggbase/eggToSomething.cxx b/pandatool/src/eggbase/eggToSomething.cxx index b742eeaaf1..4512d3f95f 100644 --- a/pandatool/src/eggbase/eggToSomething.cxx +++ b/pandatool/src/eggbase/eggToSomething.cxx @@ -81,23 +81,8 @@ EggToSomething(const string &format_name, //////////////////////////////////////////////////////////////////// bool EggToSomething:: handle_args(ProgramBase::Args &args) { - if (_allow_last_param && !_got_output_filename && args.size() > 1) { - _got_output_filename = true; - _output_filename = args.back(); - args.pop_back(); - - if (!_preferred_extension.empty() && - ("." + _output_filename.get_extension()) != _preferred_extension) { - nout << "Output filename " << _output_filename - << " does not end in " << _preferred_extension - << ". If this is really what you intended, " - "use the -o output_file syntax.\n"; - return false; - } - - if (!verify_output_file_safe()) { - return false; - } + if (!check_last_arg(args, 1)) { + return false; } return EggConverter::handle_args(args); diff --git a/pandatool/src/eggbase/eggWriter.cxx b/pandatool/src/eggbase/eggWriter.cxx index 944a767dde..284babbd65 100644 --- a/pandatool/src/eggbase/eggWriter.cxx +++ b/pandatool/src/eggbase/eggWriter.cxx @@ -28,9 +28,12 @@ // inappropriate when writing binary file formats). //////////////////////////////////////////////////////////////////// EggWriter:: -EggWriter(bool allow_last_param, bool allow_stdout) { - _allow_last_param = allow_last_param; - _allow_stdout = allow_stdout; +EggWriter(bool allow_last_param, bool allow_stdout) : + WithOutputFile(allow_last_param, allow_stdout, false) +{ + // Indicate the extension name we expect the user to supply for + // output files. + _preferred_extension = ".egg"; clear_runlines(); if (_allow_last_param) { @@ -77,8 +80,6 @@ EggWriter(bool allow_last_param, bool allow_stdout) { "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is " "y-up."); - _output_ptr = (ostream *)NULL; - _normals_mode = NM_preserve; _normals_threshold = 0.0; @@ -178,68 +179,6 @@ as_writer() { return this; } -//////////////////////////////////////////////////////////////////// -// Function: EggWriter::get_output -// Access: Public -// Description: Returns an output stream that corresponds to the -// user's intended egg file output--either stdout, or -// the named output file. Normally, you should not need -// to call this directly, as write_egg_file() will write -// the egg file to the resulting stream. Call this only -// if you cannot use write_egg_file() to write out the -// egg file for some reason. -//////////////////////////////////////////////////////////////////// -ostream &EggWriter:: -get_output() { - if (_output_ptr == (ostream *)NULL) { - if (!_got_output_filename) { - // No filename given; use standard output. - assert(_allow_stdout); - _output_ptr = &cout; - - } else { - // Attempt to open the named file. - unlink(_output_filename.c_str()); - _output_filename.make_dir(); - _output_filename.set_text(); - if (!_output_filename.open_write(_output_stream)) { - nout << "Unable to write to " << _output_filename << "\n"; - exit(1); - } - nout << "Writing " << _output_filename << "\n"; - _output_ptr = &_output_stream; - } - } - return *_output_ptr; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggWriter::has_output_filename -// Access: Public -// Description: Returns true if the user specified an output -// filename, false otherwise (e.g. the output file is -// implicitly stdout). -//////////////////////////////////////////////////////////////////// -bool EggWriter:: -has_output_filename() const { - return _got_output_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggWriter::get_output_filename -// Access: Public -// Description: If has_output_filename() returns true, this is the -// filename that the user specified. Otherwise, it -// returns the empty string. -//////////////////////////////////////////////////////////////////// -Filename EggWriter:: -get_output_filename() const { - if (_got_output_filename) { - return _output_filename; - } - return Filename(); -} - //////////////////////////////////////////////////////////////////// // Function: EggWriter::post_process_egg_file // Access: Public, Virtual @@ -316,7 +255,7 @@ write_egg_file() { //////////////////////////////////////////////////////////////////// bool EggWriter:: handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args)) { + if (!check_last_arg(args, 0)) { return false; } @@ -330,33 +269,6 @@ handle_args(ProgramBase::Args &args) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: EggWriter::check_last_arg -// Access: Protected -// Description: Checks if the last filename on the argument list is -// an egg file (if _allow_last_param was set true), and -// removes it from the argument list if it is. Returns -// true if the arguments are good, false if something is -// invalid. -//////////////////////////////////////////////////////////////////// -bool EggWriter:: -check_last_arg(ProgramBase::Args &args) { - if (_allow_last_param && !_got_output_filename && !args.empty()) { - Filename filename = args.back(); - if (filename.get_extension() == "egg") { - _got_output_filename = true; - _output_filename = filename; - args.pop_back(); - - if (!verify_output_file_safe()) { - return false; - } - } - } - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: EggWriter::post_command_line // Access: Protected, Virtual @@ -585,31 +497,3 @@ dispatch_translate(const string &opt, const string &arg, void *var) { return true; } - -//////////////////////////////////////////////////////////////////// -// Function: EggWriter::verify_output_file_safe -// Access: Protected -// Description: This is called when the output file is given as the -// last parameter on the command line. Since this is a -// fairly dangerous way to specify the output file (it's -// easy to accidentally overwrite an input file this -// way), the convention is to disallow this syntax if -// the output file already exists. -// -// This function will test if the output file exists, -// and issue a warning message if it does, returning -// false. If all is well, it will return true. -//////////////////////////////////////////////////////////////////// -bool EggWriter:: -verify_output_file_safe() const { - nassertr(_got_output_filename, false); - - if (_output_filename.exists()) { - nout << "The output filename " << _output_filename << " already exists. " - "If you wish to overwrite it, you must use the -o option to specify " - "the output filename, instead of simply specifying it as the last " - "parameter.\n"; - return false; - } - return true; -} diff --git a/pandatool/src/eggbase/eggWriter.h b/pandatool/src/eggbase/eggWriter.h index e3b03a7496..59e3d210e1 100644 --- a/pandatool/src/eggbase/eggWriter.h +++ b/pandatool/src/eggbase/eggWriter.h @@ -10,6 +10,8 @@ #include "eggBase.h" +#include + #include #include @@ -18,7 +20,7 @@ // Description : This is the base class for a program that generates // an egg file output, but doesn't read any for input. //////////////////////////////////////////////////////////////////// -class EggWriter : virtual public EggBase { +class EggWriter : virtual public EggBase, public WithOutputFile { public: EggWriter(bool allow_last_param = false, bool allow_stdout = true); @@ -27,16 +29,11 @@ public: virtual EggWriter *as_writer(); - ostream &get_output(); - bool has_output_filename() const; - Filename get_output_filename() const; - virtual void post_process_egg_file(); void write_egg_file(); protected: virtual bool handle_args(Args &args); - bool check_last_arg(Args &args); virtual bool post_command_line(); static bool dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode); @@ -49,14 +46,7 @@ protected: bool ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var); static bool dispatch_translate(const string &opt, const string &arg, void *var); - bool verify_output_file_safe() const; - protected: - bool _allow_last_param; - bool _allow_stdout; - bool _got_output_filename; - Filename _output_filename; - enum NormalsMode { NM_strip, NM_polygon, diff --git a/pandatool/src/eggprogs/eggTextureCards.cxx b/pandatool/src/eggprogs/eggTextureCards.cxx index 8796a5369f..90e336afbc 100644 --- a/pandatool/src/eggprogs/eggTextureCards.cxx +++ b/pandatool/src/eggprogs/eggTextureCards.cxx @@ -61,7 +61,7 @@ EggTextureCards() : EggWriter(true, true) { //////////////////////////////////////////////////////////////////// bool EggTextureCards:: handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args)) { + if (!check_last_arg(args, 0)) { return false; } diff --git a/pandatool/src/flt/Sources.pp b/pandatool/src/flt/Sources.pp index 2433da6cf4..9d90886a66 100644 --- a/pandatool/src/flt/Sources.pp +++ b/pandatool/src/flt/Sources.pp @@ -54,17 +54,3 @@ fltVertex.h fltVertexList.h #end ss_lib_target - -#begin test_bin_target - #define TARGET test_flt - #define LOCAL_LIBS \ - flt - #define OTHER_LIBS \ - express:c pandaexpress:m \ - dtoolutil:c dconfig:c dtoolconfig:m dtool:m pystub - - #define SOURCES \ - test_flt.cxx - -#end test_bin_target - diff --git a/pandatool/src/flt/fltGeometry.cxx b/pandatool/src/flt/fltGeometry.cxx index 31f0a58dd0..a5bccbd735 100644 --- a/pandatool/src/flt/fltGeometry.cxx +++ b/pandatool/src/flt/fltGeometry.cxx @@ -231,11 +231,14 @@ build_record(FltRecordWriter &writer) const { return false; } - datagram.add_be_int16(_texture_mapping_index); - datagram.pad_bytes(2); - datagram.add_be_uint32(_color_index); - datagram.add_be_uint32(_alt_color_index); - datagram.pad_bytes(2 + 2); + if (_header->get_flt_version() >= 15.2) { + // New with 15.2 + datagram.add_be_int16(_texture_mapping_index); + datagram.pad_bytes(2); + datagram.add_be_uint32(_color_index); + datagram.add_be_uint32(_alt_color_index); + datagram.pad_bytes(2 + 2); + } return true; } diff --git a/pandatool/src/flt/fltHeader.cxx b/pandatool/src/flt/fltHeader.cxx index 06ffcc1ad1..22cebe2729 100644 --- a/pandatool/src/flt/fltHeader.cxx +++ b/pandatool/src/flt/fltHeader.cxx @@ -10,6 +10,7 @@ #include "config_flt.h" #include +#include TypeHandle FltHeader::_type_handle; @@ -55,6 +56,8 @@ FltHeader() : FltBeadID(this) { _next_light_id = 1; _next_road_id = 1; _next_cat_id = 1; + + // New with 15.2 _earth_model = EM_wgs84; // New with 15.6 @@ -228,6 +231,21 @@ get_flt_version() const { } } +//////////////////////////////////////////////////////////////////// +// Function: FltHeader::set_flt_version +// Access: Public +// Description: Changes the version number of the flt file that will +// be reported in the header. +//////////////////////////////////////////////////////////////////// +void FltHeader:: +set_flt_version(double version) { + if (version < 14.2) { + _format_revision_level = (int)floor(version + 0.5); + } else { + _format_revision_level = (int)floor(version * 100.0 + 0.5); + } +} + //////////////////////////////////////////////////////////////////// // Function: FltHeader::min_flt_version // Access: Public, Static @@ -1289,24 +1307,28 @@ build_record(FltRecordWriter &writer) const { datagram.pad_bytes(2); datagram.add_be_int16(_next_road_id); datagram.add_be_int16(_next_cat_id); - datagram.pad_bytes(2 + 2 + 2 + 2); - datagram.add_be_int32(_earth_model); - datagram.pad_bytes(4); + if (get_flt_version() >= 15.2) { + // New with 15.2 + datagram.pad_bytes(2 + 2 + 2 + 2); + datagram.add_be_int32(_earth_model); - if (get_flt_version() >= 15.6) { - // New with 15.6 - datagram.add_be_int16(_next_adaptive_id); - datagram.add_be_int16(_next_curve_id); - datagram.pad_bytes(4); + datagram.pad_bytes(4); - if (get_flt_version() >= 15.7) { - // New with 15.7 - datagram.add_be_float64(_delta_z); - datagram.add_be_float64(_radius); - datagram.add_be_int16(_next_mesh_id); - datagram.pad_bytes(2); + if (get_flt_version() >= 15.6) { + // New with 15.6 + datagram.add_be_int16(_next_adaptive_id); + datagram.add_be_int16(_next_curve_id); datagram.pad_bytes(4); + + if (get_flt_version() >= 15.7) { + // New with 15.7 + datagram.add_be_float64(_delta_z); + datagram.add_be_float64(_radius); + datagram.add_be_int16(_next_mesh_id); + datagram.pad_bytes(2); + datagram.pad_bytes(4); + } } } @@ -1660,10 +1682,44 @@ FltError FltHeader:: write_material_palette(FltRecordWriter &writer) const { FltError result; - Materials::const_iterator mi; - for (mi = _materials.begin(); mi != _materials.end(); ++mi) { - FltMaterial *material = (*mi).second; - material->build_record(writer); + if (get_flt_version() >= 15.2) { + // Write a version 15 material palette. + Materials::const_iterator mi; + for (mi = _materials.begin(); mi != _materials.end(); ++mi) { + FltMaterial *material = (*mi).second; + material->build_record(writer); + + result = writer.advance(); + if (result != FE_ok) { + return result; + } + } + + } else { + // Write a version 14 material palette. + if (_materials.empty()) { + // No palette is OK. + return FE_ok; + } + writer.set_opcode(FO_14_material_palette); + Datagram &datagram = writer.update_datagram(); + + PT(FltMaterial) dummy_material = new FltMaterial(_header); + + Materials::const_iterator mi = _materials.lower_bound(0); + int index; + static const int expected_material_entries = 64; + for (index = 0; index < expected_material_entries; index++) { + if (mi == _materials.end() || index < (*mi).first) { + dummy_material->build_14_record(datagram); + } else { + nassertr(index == (*mi).first, FE_internal); + FltMaterial *material = (*mi).second; + material->build_14_record(datagram); + ++mi; + } + } + result = writer.advance(); if (result != FE_ok) { return result; diff --git a/pandatool/src/flt/fltHeader.h b/pandatool/src/flt/fltHeader.h index 28e87c0638..8d2ab15062 100644 --- a/pandatool/src/flt/fltHeader.h +++ b/pandatool/src/flt/fltHeader.h @@ -128,6 +128,7 @@ public: public: double get_flt_version() const; + void set_flt_version(double version); static double min_flt_version(); static double max_flt_version(); bool check_version() const; diff --git a/pandatool/src/flt/fltMaterial.cxx b/pandatool/src/flt/fltMaterial.cxx index 36647796f8..124c4b5c83 100644 --- a/pandatool/src/flt/fltMaterial.cxx +++ b/pandatool/src/flt/fltMaterial.cxx @@ -137,3 +137,34 @@ extract_14_record(int index, DatagramIterator &di) { return true; } + +//////////////////////////////////////////////////////////////////// +// Function: FltMaterial::build_14_record +// Access: Public +// Description: Fills up the current record on the FltRecordWriter +// with data for this record, formatted as a part of a +// v14 material palette. Returns true on success, false +// if there is some error. +//////////////////////////////////////////////////////////////////// +bool FltMaterial:: +build_14_record(Datagram &datagram) { + datagram.add_be_float32(_ambient[0]); + datagram.add_be_float32(_ambient[1]); + datagram.add_be_float32(_ambient[2]); + datagram.add_be_float32(_diffuse[0]); + datagram.add_be_float32(_diffuse[1]); + datagram.add_be_float32(_diffuse[2]); + datagram.add_be_float32(_specular[0]); + datagram.add_be_float32(_specular[1]); + datagram.add_be_float32(_specular[2]); + datagram.add_be_float32(_emissive[0]); + datagram.add_be_float32(_emissive[1]); + datagram.add_be_float32(_emissive[2]); + datagram.add_be_float32(_shininess); + datagram.add_be_float32(_alpha); + datagram.add_be_uint32(_flags); + datagram.add_fixed_string(_material_name, 12); + datagram.pad_bytes(4 * 28); + + return true; +} diff --git a/pandatool/src/flt/fltMaterial.h b/pandatool/src/flt/fltMaterial.h index a7c22ab784..c5526e9256 100644 --- a/pandatool/src/flt/fltMaterial.h +++ b/pandatool/src/flt/fltMaterial.h @@ -42,6 +42,7 @@ protected: public: bool extract_14_record(int index, DatagramIterator &di); + bool build_14_record(Datagram &datagram); public: virtual TypeHandle get_type() const { diff --git a/pandatool/src/flt/fltVertex.cxx b/pandatool/src/flt/fltVertex.cxx index 3a3ca4335a..ea29533aad 100644 --- a/pandatool/src/flt/fltVertex.cxx +++ b/pandatool/src/flt/fltVertex.cxx @@ -59,21 +59,43 @@ get_opcode() const { //////////////////////////////////////////////////////////////////// int FltVertex:: get_record_length() const { - switch (get_opcode()) { - case FO_vertex_c: - return 40; + if (_header->get_flt_version() < 15.2) { + // Version 14.2 + switch (get_opcode()) { + case FO_vertex_c: + return 36; + + case FO_vertex_cn: + return 48; + + case FO_vertex_cnu: + return 56; + + case FO_vertex_cu: + return 44; + + default: + nassertr(false, 0); + } - case FO_vertex_cn: - return 56; - - case FO_vertex_cnu: - return 64; - - case FO_vertex_cu: - return 48; - - default: - nassertr(false, 0); + } else { + // Version 15.2 and higher + switch (get_opcode()) { + case FO_vertex_c: + return 40; + + case FO_vertex_cn: + return 56; + + case FO_vertex_cnu: + return 64; + + case FO_vertex_cu: + return 48; + + default: + nassertr(false, 0); + } } return 0; @@ -222,12 +244,15 @@ build_record(FltRecordWriter &writer) const { return false; } - datagram.add_be_uint32(_color_index); + if (_header->get_flt_version() >= 15.2) { + // New with 15.2 + datagram.add_be_uint32(_color_index); - if (_has_normal) { - // If we added a normal, our double-word alignment is off; now we - // have a few extra bytes to add. - datagram.pad_bytes(4); + if (_has_normal) { + // If we added a normal, our double-word alignment is off; now we + // have a few extra bytes to add. + datagram.pad_bytes(4); + } } nassertr((int)datagram.get_length() == get_record_length() - 4, true); diff --git a/pandatool/src/flt/test_flt.cxx b/pandatool/src/flt/test_flt.cxx deleted file mode 100644 index 59e0c94a2f..0000000000 --- a/pandatool/src/flt/test_flt.cxx +++ /dev/null @@ -1,63 +0,0 @@ -// Filename: test_flt.cxx -// Created by: drose (24Aug00) -// -//////////////////////////////////////////////////////////////////// - -#include "fltHeader.h" - -#include - -void -usage() { - cerr << "Usage: test_flt [opts] filename.flt\n"; -} - -int -main(int argc, char *argv[]) { - static const char * const opts = "t:"; - extern char *optarg; - extern int optind; - - DSearchPath texture_path; - - int flag = getopt(argc, argv, opts); - while (flag != EOF) { - switch (flag) { - case 't': - // t: Texture search path. - texture_path.append_directory(optarg); - break; - - default: - usage(); - exit(1); - } - flag = getopt(argc, argv, opts); - } - argc -= (optind - 1); - argv += (optind - 1); - - if (argc != 2) { - usage(); - exit(1); - } - - Filename filename = argv[1]; - - PT(FltHeader) header = new FltHeader; - header->set_texture_path(texture_path); - - FltError result = header->read_flt(filename); - cerr << "Read result is " << result << "\n" - << "Version is " << header->get_flt_version() << "\n"; - header->check_version(); - - if (result == FE_ok) { - //header->write(cerr); - - result = header->write_flt("t.flt"); - cerr << "Write result is " << result << "\n\n"; - } - - return (0); -} diff --git a/pandatool/src/fltprogs/Sources.pp b/pandatool/src/fltprogs/Sources.pp index 5d0837e74a..5af8c41b18 100644 --- a/pandatool/src/fltprogs/Sources.pp +++ b/pandatool/src/fltprogs/Sources.pp @@ -11,3 +11,17 @@ fltCopy.cxx fltCopy.h #end bin_target + +#begin bin_target + #define TARGET flt-trans + #define LOCAL_LIBS \ + progbase flt + #define OTHER_LIBS \ + linmath:c panda:m \ + express:c pandaexpress:m \ + dtoolutil:c dconfig:c dtoolconfig:m dtool:m pystub + + #define SOURCES \ + fltTrans.cxx fltTrans.h + +#end bin_target diff --git a/pandatool/src/fltprogs/fltTrans.cxx b/pandatool/src/fltprogs/fltTrans.cxx new file mode 100644 index 0000000000..8b7bf69a86 --- /dev/null +++ b/pandatool/src/fltprogs/fltTrans.cxx @@ -0,0 +1,130 @@ +// Filename: fltTrans.cxx +// Created by: drose (11Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "fltTrans.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Function: FltTrans::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +FltTrans:: +FltTrans() : + WithOutputFile(true, false, true) +{ + // Indicate the extension name we expect the user to supply for + // output files. + _preferred_extension = ".flt"; + + set_program_description + ("This program reads a MultiGen OpenFlight (.flt) file and writes an " + "essentially equivalent .flt file, to the file specified with -o (or " + "as the second parameter). Some simple operations may be performed."); + + clear_runlines(); + add_runline("[opts] input.flt output.flt"); + add_runline("[opts] -o output.flt input.flt"); + + add_option + ("tp", "path", 0, + "Add the indicated colon-delimited paths to the path that is searched " + "for textures referenced by the flt file. This " + "option may also be repeated to add multiple paths.", + &FltTrans::dispatch_search_path, NULL, &_texture_path); + + add_option + ("v", "version", 0, + "Upgrade (or downgrade) the flt file to the indicated version. This " + "may not be completely correct for all version-to-version combinations.", + &FltTrans::dispatch_double, &_got_new_version, &_new_version); + + add_option + ("o", "filename", 0, + "Specify the filename to which the resulting .flt file will be written. " + "If this option is omitted, the last parameter name is taken to be the " + "name of the output file.", + &FltTrans::dispatch_filename, &_got_output_filename, &_output_filename); +} + + +//////////////////////////////////////////////////////////////////// +// Function: FltTrans::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void FltTrans:: +run() { + if (_got_new_version) { + if (_new_version < FltHeader::min_flt_version() || + _new_version > FltHeader::max_flt_version()) { + nout << "Cannot write flt files of version " << _new_version + << ". This program only understands how to write flt files between version " + << FltHeader::min_flt_version() << " and " + << FltHeader::max_flt_version() << ".\n"; + exit(1); + } + } + + PT(FltHeader) header = new FltHeader; + header->set_texture_path(_texture_path); + + nout << "Reading " << _input_filename << "\n"; + FltError result = header->read_flt(_input_filename); + if (result != FE_ok) { + nout << "Unable to read: " << result << "\n"; + exit(1); + } else { + if (header->check_version()) { + nout << "Version is " << header->get_flt_version() << "\n"; + } + + if (_got_new_version) { + header->set_flt_version(_new_version); + } + + result = header->write_flt(get_output()); + if (result != FE_ok) { + nout << "Unable to write: " << result << "\n"; + } else { + nout << "Successfully written.\n"; + } + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: FltTrans::handle_args +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool FltTrans:: +handle_args(ProgramBase::Args &args) { + if (!check_last_arg(args, 1)) { + return false; + } + + if (args.empty()) { + nout << "You must specify the .flt file to read on the command line.\n"; + return false; + + } else if (args.size() != 1) { + nout << "You must specify only one .flt file to read on the command line.\n"; + return false; + } + + _input_filename = args[0]; + + return true; +} + + +int main(int argc, char *argv[]) { + FltTrans prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandatool/src/fltprogs/fltTrans.h b/pandatool/src/fltprogs/fltTrans.h new file mode 100644 index 0000000000..34e987ab80 --- /dev/null +++ b/pandatool/src/fltprogs/fltTrans.h @@ -0,0 +1,38 @@ +// Filename: fltTrans.h +// Created by: drose (11Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef FLTTRANS_H +#define FLTTRANS_H + +#include + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : FltTrans +// Description : A program to read a flt file and write an equivalent +// flt file, possibly performing some minor operations +// along the way. +//////////////////////////////////////////////////////////////////// +class FltTrans : public ProgramBase, public WithOutputFile { +public: + FltTrans(); + + void run(); + +protected: + virtual bool handle_args(Args &args); + + Filename _input_filename; + DSearchPath _texture_path; + bool _got_new_version; + double _new_version; +}; + +#endif + diff --git a/pandatool/src/progbase/Sources.pp b/pandatool/src/progbase/Sources.pp index 2380348ed3..40327689bd 100644 --- a/pandatool/src/progbase/Sources.pp +++ b/pandatool/src/progbase/Sources.pp @@ -6,12 +6,16 @@ linmath:c putil:c express:c panda:m pystub dtool #define SOURCES \ - programBase.I programBase.cxx programBase.h wordWrapStream.cxx \ + programBase.I programBase.cxx programBase.h \ + withOutputFile.cxx withOutputFile.h \ + wordWrapStream.cxx \ wordWrapStream.h wordWrapStreamBuf.I wordWrapStreamBuf.cxx \ wordWrapStreamBuf.h #define INSTALL_HEADERS \ - programBase.I programBase.h wordWrapStream.h wordWrapStreamBuf.I \ + programBase.I programBase.h \ + withOutputFile.h \ + wordWrapStream.h wordWrapStreamBuf.I \ wordWrapStreamBuf.h #end ss_lib_target diff --git a/pandatool/src/progbase/withOutputFile.cxx b/pandatool/src/progbase/withOutputFile.cxx new file mode 100644 index 0000000000..623802a71d --- /dev/null +++ b/pandatool/src/progbase/withOutputFile.cxx @@ -0,0 +1,169 @@ +// Filename: withOutputFile.cxx +// Created by: drose (11Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "withOutputFile.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +WithOutputFile:: +WithOutputFile(bool allow_last_param, bool allow_stdout, + bool binary_output) { + _allow_last_param = allow_last_param; + _allow_stdout = allow_stdout; + _binary_output = binary_output; + _got_output_filename = false; + _output_ptr = (ostream *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +WithOutputFile:: +~WithOutputFile() { +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::get_output +// Access: Public +// Description: Returns an output stream that corresponds to the +// user's intended egg file output--either stdout, or +// the named output file. +//////////////////////////////////////////////////////////////////// +ostream &WithOutputFile:: +get_output() { + if (_output_ptr == (ostream *)NULL) { + if (!_got_output_filename) { + // No filename given; use standard output. + nassertr(_allow_stdout, _output_stream); + _output_ptr = &cout; + + } else { + // Attempt to open the named file. + unlink(_output_filename.c_str()); + _output_filename.make_dir(); + + if (_binary_output) { + _output_filename.set_binary(); + } else { + _output_filename.set_text(); + } + + if (!_output_filename.open_write(_output_stream)) { + nout << "Unable to write to " << _output_filename << "\n"; + exit(1); + } + nout << "Writing " << _output_filename << "\n"; + _output_ptr = &_output_stream; + } + } + return *_output_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::has_output_filename +// Access: Public +// Description: Returns true if the user specified an output +// filename, false otherwise (e.g. the output file is +// implicitly stdout). +//////////////////////////////////////////////////////////////////// +bool WithOutputFile:: +has_output_filename() const { + return _got_output_filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::get_output_filename +// Access: Public +// Description: If has_output_filename() returns true, this is the +// filename that the user specified. Otherwise, it +// returns the empty string. +//////////////////////////////////////////////////////////////////// +Filename WithOutputFile:: +get_output_filename() const { + if (_got_output_filename) { + return _output_filename; + } + return Filename(); +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::check_last_arg +// Access: Protected +// Description: Checks if the last filename on the argument list is +// a file with the expected extension (if +// _allow_last_param was set true), and removes it from +// the argument list if it is. Returns true if the +// arguments are good, false if something is invalid. +// +// minimum_args is the number of arguments we know must +// be input parameters and therefore cannot be +// interpreted as output filenames. +//////////////////////////////////////////////////////////////////// +bool WithOutputFile:: +check_last_arg(ProgramBase::Args &args, int minimum_args) { + if (_allow_last_param && !_got_output_filename && + (int)args.size() > minimum_args) { + Filename filename = args.back(); + + if (!_preferred_extension.empty() && + ("." + filename.get_extension()) != _preferred_extension) { + // This argument must not be an output filename. + if (!_allow_stdout) { + nout << "Output filename " << filename + << " does not end in " << _preferred_extension + << ". If this is really what you intended, " + "use the -o output_file syntax.\n"; + return false; + } + + } else { + // This argument appears to be an output filename. + _got_output_filename = true; + _output_filename = filename; + args.pop_back(); + + if (!verify_output_file_safe()) { + return false; + } + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: WithOutputFile::verify_output_file_safe +// Access: Protected +// Description: This is called when the output file is given as the +// last parameter on the command line. Since this is a +// fairly dangerous way to specify the output file (it's +// easy to accidentally overwrite an input file this +// way), the convention is to disallow this syntax if +// the output file already exists. +// +// This function will test if the output file exists, +// and issue a warning message if it does, returning +// false. If all is well, it will return true. +//////////////////////////////////////////////////////////////////// +bool WithOutputFile:: +verify_output_file_safe() const { + nassertr(_got_output_filename, false); + + if (_output_filename.exists()) { + nout << "The output filename " << _output_filename << " already exists. " + "If you wish to overwrite it, you must use the -o option to specify " + "the output filename, instead of simply specifying it as the last " + "parameter.\n"; + return false; + } + return true; +} diff --git a/pandatool/src/progbase/withOutputFile.h b/pandatool/src/progbase/withOutputFile.h new file mode 100644 index 0000000000..2d328ec686 --- /dev/null +++ b/pandatool/src/progbase/withOutputFile.h @@ -0,0 +1,53 @@ +// Filename: outputFile.h +// Created by: drose (11Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef WITHOUTPUTFILE_H +#define WITHOUTPUTFILE_H + +#include + +#include "programBase.h" +#include + +//////////////////////////////////////////////////////////////////// +// Class : WithOutputFile +// Description : This is the bare functionality (intended to be +// inherited from along with ProgramBase or some +// derivative) for a program that might generate an +// output file. +// +// This provides the has_output_filename() and +// get_output_filename() methods. +//////////////////////////////////////////////////////////////////// +class WithOutputFile { +public: + WithOutputFile(bool allow_last_param, bool allow_stdout, + bool binary_output); + virtual ~WithOutputFile(); + + ostream &get_output(); + bool has_output_filename() const; + Filename get_output_filename() const; + +protected: + bool check_last_arg(ProgramBase::Args &args, int minimum_args); + bool verify_output_file_safe() const; + +protected: + bool _allow_last_param; + bool _allow_stdout; + bool _binary_output; + string _preferred_extension; + bool _got_output_filename; + Filename _output_filename; + +private: + ofstream _output_stream; + ostream *_output_ptr; +}; + +#endif + +