Panda3D
 All Classes Functions Variables Enumerations
eggTexture.cxx
00001 // Filename: eggTexture.cxx
00002 // Created by:  drose (18Jan99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "eggTexture.h"
00016 #include "eggMiscFuncs.h"
00017 #include "lexerDefs.h"
00018 
00019 #include "indent.h"
00020 #include "string_utils.h"
00021 
00022 TypeHandle EggTexture::_type_handle;
00023 
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: EggTexture::Constructor
00027 //       Access: Published
00028 //  Description:
00029 ////////////////////////////////////////////////////////////////////
00030 EggTexture::
00031 EggTexture(const string &tref_name, const Filename &filename)
00032   : EggFilenameNode(tref_name, filename)
00033 {
00034   _texture_type = TT_unspecified;
00035   _format = F_unspecified;
00036   _compression_mode = CM_default;
00037   _wrap_mode = WM_unspecified;
00038   _wrap_u = WM_unspecified;
00039   _wrap_v = WM_unspecified;
00040   _wrap_w = WM_unspecified;
00041   _minfilter = FT_unspecified;
00042   _magfilter = FT_unspecified;
00043   _anisotropic_degree = 0;
00044   _env_type = ET_unspecified;
00045   _saved_result = false;
00046   _multiview = false;
00047   _num_views = 0;
00048   _tex_gen = TG_unspecified;
00049   _quality_level = QL_unspecified;
00050   _priority = 0;
00051   _color.set(0.0f, 0.0f, 0.0f, 1.0f);
00052   _border_color.set(0.0f, 0.0f, 0.0f, 1.0f);
00053   _flags = 0;
00054   _alpha_file_channel = 0;
00055   _read_mipmaps = false;
00056   _multitexture_sort = 0;
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: EggTexture::Copy constructor
00061 //       Access: Published
00062 //  Description:
00063 ////////////////////////////////////////////////////////////////////
00064 EggTexture::
00065 EggTexture(const EggTexture &copy) {
00066   (*this) = copy;
00067 }
00068 
00069 ////////////////////////////////////////////////////////////////////
00070 //     Function: EggTexture::Copy assignment operator
00071 //       Access: Published
00072 //  Description:
00073 ////////////////////////////////////////////////////////////////////
00074 EggTexture &EggTexture::
00075 operator = (const EggTexture &copy) {
00076   clear_multitexture();
00077 
00078   EggFilenameNode::operator = (copy);
00079   EggRenderMode::operator = (copy);
00080   EggTransform::operator = (copy);
00081 
00082   _texture_type = copy._texture_type;
00083   _format = copy._format;
00084   _compression_mode = copy._compression_mode;
00085   _wrap_mode = copy._wrap_mode;
00086   _wrap_u = copy._wrap_u;
00087   _wrap_v = copy._wrap_v;
00088   _wrap_w = copy._wrap_w;
00089   _minfilter = copy._minfilter;
00090   _magfilter = copy._magfilter;
00091   _anisotropic_degree = copy._anisotropic_degree;
00092   _env_type = copy._env_type;
00093   _saved_result = copy._saved_result;
00094   _multiview = copy._multiview;
00095   _num_views = copy._num_views;
00096   _tex_gen = copy._tex_gen;
00097   _quality_level = copy._quality_level;
00098   _stage_name = copy._stage_name;
00099   _priority = copy._priority;
00100   _color = copy._color;
00101   _border_color = copy._border_color;
00102   _uv_name = copy._uv_name;
00103   _rgb_scale = 1;
00104   _alpha_scale = 1;
00105   _flags = copy._flags;
00106   _alpha_filename = copy._alpha_filename;
00107   _alpha_fullpath = copy._alpha_fullpath;
00108   _alpha_file_channel = copy._alpha_file_channel;
00109   _read_mipmaps = copy._read_mipmaps;
00110   _multitexture_sort = 0;
00111   _combiner[0] = copy._combiner[0];
00112   _combiner[1] = copy._combiner[1];
00113 
00114   return *this;
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: EggTexture::Destructor
00119 //       Access: Published, Virtual
00120 //  Description:
00121 ////////////////////////////////////////////////////////////////////
00122 EggTexture::
00123 ~EggTexture() {
00124   clear_multitexture();
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: EggTexture::write
00129 //       Access: Public, Virtual
00130 //  Description: Writes the texture definition to the indicated output
00131 //               stream in Egg format.
00132 ////////////////////////////////////////////////////////////////////
00133 void EggTexture::
00134 write(ostream &out, int indent_level) const {
00135   write_header(out, indent_level, "<Texture>");
00136   enquote_string(out, get_filename(), indent_level + 2) << "\n";
00137 
00138   if (has_alpha_filename()) {
00139     indent(out, indent_level + 2)
00140       << "<Scalar> alpha-file { ";
00141     enquote_string(out, get_alpha_filename());
00142     out << " }\n";
00143   }
00144 
00145   if (has_alpha_file_channel()) {
00146     indent(out, indent_level + 2)
00147       << "<Scalar> alpha-file-channel { " 
00148       << get_alpha_file_channel() << " }\n";
00149   }
00150 
00151   if (get_read_mipmaps()) {
00152     indent(out, indent_level + 2)
00153       << "<Scalar> read-mipmaps { 1 }\n";
00154   }
00155 
00156   if (get_texture_type() != TT_unspecified) {
00157     indent(out, indent_level + 2)
00158       << "<Scalar> type { " << get_texture_type() << " }\n";
00159   }
00160 
00161   if (get_format() != F_unspecified) {
00162     indent(out, indent_level + 2)
00163       << "<Scalar> format { " << get_format() << " }\n";
00164   }
00165 
00166   if (get_compression_mode() != CM_default) {
00167     indent(out, indent_level + 2)
00168       << "<Scalar> compression { " << get_compression_mode() << " }\n";
00169   }
00170 
00171   if (get_wrap_mode() != WM_unspecified) {
00172     indent(out, indent_level + 2)
00173       << "<Scalar> wrap { " << get_wrap_mode() << " }\n";
00174   }
00175 
00176   if (get_wrap_u() != WM_unspecified) {
00177     indent(out, indent_level + 2)
00178       << "<Scalar> wrapu { " << get_wrap_u() << " }\n";
00179   }
00180 
00181   if (get_wrap_v() != WM_unspecified) {
00182     indent(out, indent_level + 2)
00183       << "<Scalar> wrapv { " << get_wrap_v() << " }\n";
00184   }
00185 
00186   if (get_wrap_w() != WM_unspecified) {
00187     indent(out, indent_level + 2)
00188       << "<Scalar> wrapw { " << get_wrap_w() << " }\n";
00189   }
00190 
00191   if (get_minfilter() != FT_unspecified) {
00192     indent(out, indent_level + 2)
00193       << "<Scalar> minfilter { " << get_minfilter() << " }\n";
00194   }
00195 
00196   if (get_magfilter() != FT_unspecified) {
00197     indent(out, indent_level + 2)
00198       << "<Scalar> magfilter { " << get_magfilter() << " }\n";
00199   }
00200 
00201   if (has_anisotropic_degree()) {
00202     indent(out, indent_level + 2)
00203       << "<Scalar> anisotropic-degree { " << get_anisotropic_degree() << " }\n";
00204   }
00205 
00206   if (get_env_type() != ET_unspecified) {
00207     indent(out, indent_level + 2)
00208       << "<Scalar> envtype { " << get_env_type() << " }\n";
00209   }
00210 
00211   for (int ci = 0; ci < (int)CC_num_channels; ci++) {
00212     CombineChannel channel = (CombineChannel)ci;
00213     if (get_combine_mode(channel) != CM_unspecified) {
00214       indent(out, indent_level + 2)
00215         << "<Scalar> combine-" << channel 
00216         << " { " << get_combine_mode(channel) << " }\n";
00217     }
00218     for (int i = 0; i < (int)CI_num_indices; i++) {
00219       if (get_combine_source(channel, i) != CS_unspecified) {
00220         indent(out, indent_level + 2)
00221           << "<Scalar> combine-" << channel << "-source" << i
00222           << " { " << get_combine_source(channel, i) << " }\n";
00223       }
00224       if (get_combine_operand(channel, i) != CO_unspecified) {
00225         indent(out, indent_level + 2)
00226           << "<Scalar> combine-" << channel << "-operand" << i
00227           << " { " << get_combine_operand(channel, i) << " }\n";
00228       }
00229     }
00230   }
00231 
00232   if (get_saved_result()) {
00233     indent(out, indent_level + 2)
00234       << "<Scalar> saved-result { 1 }\n";
00235   }
00236 
00237   if (get_tex_gen() != TG_unspecified) {
00238     indent(out, indent_level + 2)
00239       << "<Scalar> tex-gen { " << get_tex_gen() << " }\n";
00240   }
00241 
00242   if (get_quality_level() != QL_unspecified) {
00243     indent(out, indent_level + 2)
00244       << "<Scalar> quality-level { " << get_quality_level() << " }\n";
00245   }
00246 
00247   if (has_stage_name()) {
00248     indent(out, indent_level + 2)
00249       << "<Scalar> stage-name { " << get_stage_name() << " }\n";
00250   }
00251 
00252   if (has_priority()) {
00253     indent(out, indent_level + 2)
00254       << "<Scalar> priority { " << get_priority() << " }\n";
00255   }
00256 
00257   if (has_color()) {
00258     indent(out, indent_level + 2)
00259       << "<Scalar> blendr { " << _color[0] << " }\n";
00260     indent(out, indent_level + 2)
00261       << "<Scalar> blendg { " << _color[1] << " }\n";
00262     indent(out, indent_level + 2)
00263       << "<Scalar> blendb { " << _color[2] << " }\n";
00264     indent(out, indent_level + 2)
00265       << "<Scalar> blenda { " << _color[3] << " }\n";
00266   }
00267 
00268   if (has_border_color()) {
00269     indent(out, indent_level + 2)
00270       << "<Scalar> borderr { " << _border_color[0] << " }\n";
00271     indent(out, indent_level + 2)
00272       << "<Scalar> borderg { " << _border_color[1] << " }\n";
00273     indent(out, indent_level + 2)
00274       << "<Scalar> borderb { " << _border_color[2] << " }\n";
00275     indent(out, indent_level + 2)
00276       << "<Scalar> bordera { " << _border_color[3] << " }\n";
00277   }
00278 
00279   if (has_uv_name()) {
00280     indent(out, indent_level + 2)
00281       << "<Scalar> uv-name { " << get_uv_name() << " }\n";
00282   }
00283 
00284   if (has_rgb_scale()) {
00285     indent(out, indent_level + 2)
00286       << "<Scalar> rgb-scale { " << get_rgb_scale() << " }\n";
00287   }
00288 
00289   if (has_alpha_scale()) {
00290     indent(out, indent_level + 2)
00291       << "<Scalar> alpha-scale { " << get_alpha_scale() << " }\n";
00292   }
00293 
00294   if (get_multiview()) {
00295     indent(out, indent_level + 2)
00296       << "<Scalar> multiview { 1 }\n";
00297   }
00298 
00299   if (has_num_views()) {
00300     indent(out, indent_level + 2)
00301       << "<Scalar> num-views { " << get_num_views() << " }\n";
00302   }
00303 
00304   EggRenderMode::write(out, indent_level + 2);
00305 
00306   if (has_transform()) {
00307     EggTransform::write(out, indent_level + 2, "<Transform>");
00308   }
00309 
00310   indent(out, indent_level) << "}\n";
00311 }
00312 
00313 ////////////////////////////////////////////////////////////////////
00314 //     Function: EggTexture::is_equivalent_to
00315 //       Access: Published
00316 //  Description: Returns true if the two textures are equivalent in
00317 //               all relevant properties (according to eq), false
00318 //               otherwise.
00319 //
00320 //               The Equivalence parameter, eq, should be set to the
00321 //               bitwise OR of the following properties, according to
00322 //               what you consider relevant:
00323 //
00324 //               EggTexture::E_basename:
00325 //                 The basename part of the texture filename, without
00326 //                 the directory prefix *or* the filename extension.
00327 //
00328 //               EggTexture::E_extension:
00329 //                 The extension part of the texture filename.
00330 //
00331 //               EggTexture::E_dirname:
00332 //                 The directory prefix of the texture filename.
00333 //
00334 //               EggTexture::E_complete_filename:
00335 //                 The union of the above three; that is, the complete
00336 //                 filename, with directory, basename, and extension.
00337 //
00338 //               EggTexture::E_transform:
00339 //                 The texture matrix.
00340 //
00341 //               EggTexture::E_attributes:
00342 //                 All remaining texture attributes (mode, mipmap,
00343 //                 etc.) except TRef name.
00344 //
00345 //               EggTexture::E_tref_name:
00346 //                 The TRef name.
00347 ////////////////////////////////////////////////////////////////////
00348 bool EggTexture::
00349 is_equivalent_to(const EggTexture &other, int eq) const {
00350   if ((eq & E_complete_filename) == E_complete_filename) {
00351     //cout << "compared by filename" << endl;
00352     if (get_filename() != other.get_filename()) {
00353       return false;
00354     }
00355   } else {
00356     //cout << "compared by not complete filename" << endl;
00357     const Filename &a = get_filename();
00358     const Filename &b = other.get_filename();
00359 
00360     if (eq & E_basename) {
00361       if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
00362         return false;
00363       }
00364     }
00365     if (eq & E_extension) {
00366       if (a.get_extension() != b.get_extension()) {
00367         return false;
00368       }
00369     }
00370     if (eq & E_dirname) {
00371       if (a.get_dirname() != b.get_dirname()) {
00372         return false;
00373       }
00374     }
00375   }
00376 
00377   if (eq & E_transform) {
00378     //cout << "compared by transform" << endl;
00379     if (transform_is_identity() != other.transform_is_identity()) {
00380       return false;
00381     }
00382 
00383     if (has_transform() && other.has_transform()) {
00384       if (!get_transform3d().almost_equal(other.get_transform3d(), 0.0001)) {
00385         return false;
00386       }
00387     }
00388   }
00389 
00390   if (eq & E_attributes) {
00391     //cout << "compared by attributes" << endl;
00392     if (_texture_type != other._texture_type ||
00393         _format != other._format ||
00394         _compression_mode != other._compression_mode ||
00395         _wrap_mode != other._wrap_mode ||
00396         _wrap_u != other._wrap_u ||
00397         _wrap_v != other._wrap_v ||
00398         _wrap_w != other._wrap_w ||
00399         _minfilter != other._minfilter ||
00400         _magfilter != other._magfilter ||
00401         _env_type != other._env_type) {
00402       return false;
00403     }
00404     if (EggRenderMode::operator != (other)) {
00405       return false;
00406     }
00407   }
00408 
00409   if (eq & E_tref_name) {
00410     //cout << "compared by tref_name" << endl;
00411     if (get_name() != other.get_name()) {
00412       return false;
00413     }
00414   }
00415 
00416   return true;
00417 }
00418 
00419 ////////////////////////////////////////////////////////////////////
00420 //     Function: EggTexture::sorts_less_than
00421 //       Access: Published
00422 //  Description: An ordering operator to compare two textures for
00423 //               sorting order.  This imposes an arbitrary ordering
00424 //               useful to identify unique textures, according to the
00425 //               indicated Equivalence factor.  See
00426 //               is_equivalent_to().
00427 ////////////////////////////////////////////////////////////////////
00428 bool EggTexture::
00429 sorts_less_than(const EggTexture &other, int eq) const {
00430   if ((eq & E_complete_filename) == E_complete_filename) {
00431     if (get_filename() != other.get_filename()) {
00432       return get_filename() < other.get_filename();
00433     }
00434   } else {
00435     const Filename &a = get_filename();
00436     const Filename &b = other.get_filename();
00437 
00438     if (eq & E_basename) {
00439       if (a.get_basename_wo_extension() != b.get_basename_wo_extension()) {
00440         return a.get_basename_wo_extension() < b.get_basename_wo_extension();
00441       }
00442     }
00443     if (eq & E_extension) {
00444       if (a.get_extension() != b.get_extension()) {
00445         return a.get_extension() < b.get_extension();
00446       }
00447     }
00448     if (eq & E_dirname) {
00449       if (a.get_dirname() != b.get_dirname()) {
00450         return a.get_dirname() < b.get_dirname();
00451       }
00452     }
00453   }
00454 
00455   if (eq & E_transform) {
00456     bool is_identity = transform_is_identity();
00457     bool other_is_identity = other.transform_is_identity();
00458     if (is_identity != other_is_identity) {
00459       return (int)is_identity < (int)other_is_identity;
00460     }
00461 
00462     if (has_transform() && other.has_transform()) {
00463       int compare = get_transform3d().compare_to(other.get_transform3d());
00464       if (compare != 0) {
00465         return compare < 0;
00466       }
00467     }
00468   }
00469 
00470   if (eq & E_attributes) {
00471     if (_texture_type != other._texture_type) {
00472       return (int)_texture_type < (int)other._texture_type;
00473     }
00474     if (_format != other._format) {
00475       return (int)_format < (int)other._format;
00476     }
00477     if (_compression_mode != other._compression_mode) {
00478       return (int)_compression_mode < (int)other._compression_mode;
00479     }
00480     if (_wrap_mode != other._wrap_mode) {
00481       return (int)_wrap_mode < (int)other._wrap_mode;
00482     }
00483     if (_wrap_u != other._wrap_u) {
00484       return (int)_wrap_u < (int)other._wrap_u;
00485     }
00486     if (_wrap_v != other._wrap_v) {
00487       return (int)_wrap_v < (int)other._wrap_v;
00488     }
00489     if (_wrap_w != other._wrap_w) {
00490       return (int)_wrap_w < (int)other._wrap_w;
00491     }
00492     if (_minfilter != other._minfilter) {
00493       return (int)_minfilter < (int)other._minfilter;
00494     }
00495     if (_magfilter != other._magfilter) {
00496       return (int)_magfilter < (int)other._magfilter;
00497     }
00498     if (_anisotropic_degree != other._anisotropic_degree) {
00499       return _anisotropic_degree < other._anisotropic_degree;
00500     }
00501     if (_env_type != other._env_type) {
00502       return (int)_env_type < (int)other._env_type;
00503     }
00504     if (EggRenderMode::operator != (other)) {
00505       return EggRenderMode::operator < (other);
00506     }
00507   }
00508 
00509   if (eq & E_tref_name) {
00510     if (get_name() != other.get_name()) {
00511       return get_name() < other.get_name();
00512     }
00513   }
00514 
00515   return false;
00516 }
00517 
00518 ////////////////////////////////////////////////////////////////////
00519 //     Function: EggTexture::has_alpha_channel
00520 //       Access: Published
00521 //  Description: Given the number of color components (channels) in
00522 //               the image file as actually read from the disk, return
00523 //               true if this texture seems to have an alpha channel
00524 //               or not.  This depends on the EggTexture's format as
00525 //               well as the number of channels.
00526 ////////////////////////////////////////////////////////////////////
00527 bool EggTexture::
00528 has_alpha_channel(int num_components) const {
00529   switch (_format) {
00530   case F_red:
00531   case F_green:
00532   case F_blue:
00533   case F_luminance:
00534   case F_rgb:
00535   case F_rgb12:
00536   case F_rgb8:
00537   case F_rgb5:
00538   case F_rgb332:
00539     // These formats never use alpha, regardless of the number of
00540     // components we have.
00541     return false;
00542 
00543   case F_alpha:
00544     // This format always uses alpha.
00545     return true;
00546 
00547   case F_luminance_alpha:
00548   case F_luminance_alphamask:
00549   case F_rgba:
00550   case F_rgbm:
00551   case F_rgba12:
00552   case F_rgba8:
00553   case F_rgba4:
00554   case F_rgba5:
00555   case F_unspecified:
00556     // These formats use alpha if the image had alpha.
00557     return (num_components == 2 || num_components == 4);
00558   }
00559 
00560   return false;
00561 }
00562 
00563 ////////////////////////////////////////////////////////////////////
00564 //     Function: EggTexture::affects_polygon_alpha
00565 //       Access: Published
00566 //  Description: Returns true if this texture's environment type or
00567 //               combine mode allows the texture to have an effect on
00568 //               the polygon's alpha values, false otherwise.
00569 ////////////////////////////////////////////////////////////////////
00570 bool EggTexture::
00571 affects_polygon_alpha() const {
00572   switch (_env_type) {
00573   case ET_modulate:
00574   case ET_replace:
00575     return true;
00576 
00577   case ET_decal:
00578   case ET_blend:
00579   case ET_add:
00580   case ET_blend_color_scale:
00581   case ET_modulate_glow:
00582   case ET_modulate_gloss:
00583   case ET_normal:
00584   case ET_normal_height:
00585   case ET_glow:
00586   case ET_gloss:
00587   case ET_height:
00588   case ET_normal_gloss:
00589     return false;
00590 
00591   case ET_selector:
00592     return true;
00593 
00594   case ET_unspecified:
00595     break;
00596   }
00597 
00598   switch (_combiner[CC_alpha]._mode) {
00599   case CM_replace:
00600   case CM_modulate:
00601   case CM_add_signed:
00602   case CM_subtract:
00603     return true;
00604 
00605   case CM_interpolate:
00606   case CM_add:
00607   case CM_dot3_rgb:
00608   case CM_dot3_rgba:
00609     return false;
00610 
00611   case CM_unspecified:
00612     break;
00613   }
00614 
00615   // A completely unspecified texture environment implies "modulate",
00616   // which does affect alpha.
00617   return true;
00618 }
00619 
00620 
00621 ////////////////////////////////////////////////////////////////////
00622 //     Function: EggTexture::clear_multitexture
00623 //       Access: Published
00624 //  Description: Resets the multitexture flags set by
00625 //               multitexture_over().  After this call,
00626 //               get_multitexture() will return false, and
00627 //               get_multitexture_sort() will return 0.
00628 ////////////////////////////////////////////////////////////////////
00629 void EggTexture::
00630 clear_multitexture() {
00631   _multitexture_sort = 0;
00632 
00633   // Now empty out the _over_textures and _under_textures sets.  This
00634   // requires a bit of care so we don't end up in mutual recursion or
00635   // iterating through self-modifying structures.  To avoid this, we
00636   // empty the sets first, and then walk through their original
00637   // contents.
00638   MultiTextures orig_over_textures, orig_under_textures;
00639   orig_over_textures.swap(_over_textures);
00640   orig_under_textures.swap(_under_textures);
00641 
00642   MultiTextures::iterator mti;
00643   for (mti = orig_over_textures.begin(); 
00644        mti != orig_over_textures.end(); 
00645        ++mti) {
00646     EggTexture *other = (*mti);
00647     other->_under_textures.erase(this);
00648   }
00649   for (mti = orig_under_textures.begin(); 
00650        mti != orig_under_textures.end(); 
00651        ++mti) {
00652     EggTexture *other = (*mti);
00653     other->_over_textures.erase(this);
00654   }
00655 }
00656 
00657 ////////////////////////////////////////////////////////////////////
00658 //     Function: EggTexture::multitexture_over
00659 //       Access: Published
00660 //  Description: Indicates that this texture should be layered on top
00661 //               of the other texture.  This will guarantee that
00662 //               this->get_multitexture_sort() >
00663 //               other->get_multitexture_sort(), at least until
00664 //               clear_multitexture() is called on either one.
00665 //
00666 //               The return value is true if successful, or false if
00667 //               there is a failure because the other texture was
00668 //               already layered on top of this one (or there is a
00669 //               three- or more-way cycle).
00670 ////////////////////////////////////////////////////////////////////
00671 bool EggTexture::
00672 multitexture_over(EggTexture *other) {
00673   if (get_multitexture_sort() <= other->get_multitexture_sort()) {
00674     MultiTextures cycle_detector;
00675     if (!r_min_multitexture_sort(other->get_multitexture_sort() + 1,
00676                                  cycle_detector)) {
00677       // Found a cycle right off the bat!
00678       return false;
00679     }
00680   }
00681 
00682   if (_over_textures.insert(other).second) {
00683     bool inserted_under = other->_under_textures.insert(this).second;
00684     nassertr(inserted_under, false);
00685   }
00686   nassertr(get_multitexture_sort() > other->get_multitexture_sort(), false);
00687 
00688   return true;
00689 }
00690 
00691 ////////////////////////////////////////////////////////////////////
00692 //     Function: EggTexture::string_texture_type
00693 //       Access: Published, Static
00694 //  Description: Returns the Texture_ype value associated with the given
00695 //               string representation, or TT_unspecified if the string
00696 //               does not match any known TextureType value.
00697 ////////////////////////////////////////////////////////////////////
00698 EggTexture::TextureType EggTexture::
00699 string_texture_type(const string &string) {
00700   if (cmp_nocase_uh(string, "1d") == 0 ||
00701       cmp_nocase_uh(string, "1dtexture") == 0 ||
00702       cmp_nocase_uh(string, "1d_texture") == 0) {
00703     return TT_1d_texture;
00704 
00705   } else if (cmp_nocase_uh(string, "2d") == 0 ||
00706              cmp_nocase_uh(string, "2dtexture") == 0 ||
00707              cmp_nocase_uh(string, "2d_texture") == 0) {
00708     return TT_2d_texture;
00709 
00710   } else if (cmp_nocase_uh(string, "3d") == 0 ||
00711              cmp_nocase_uh(string, "3dtexture") == 0 ||
00712              cmp_nocase_uh(string, "3d_texture") == 0) {
00713     return TT_3d_texture;
00714 
00715   } else if (cmp_nocase_uh(string, "cube") == 0 ||
00716              cmp_nocase_uh(string, "cubemap") == 0 ||
00717              cmp_nocase_uh(string, "cube_map") == 0) {
00718     return TT_cube_map;
00719 
00720   } else {
00721     return TT_unspecified;
00722   }
00723 }
00724 
00725 ////////////////////////////////////////////////////////////////////
00726 //     Function: EggTexture::string_format
00727 //       Access: Published, Static
00728 //  Description: Returns the Format value associated with the given
00729 //               string representation, or F_unspecified if the string
00730 //               does not match any known Format value.
00731 ////////////////////////////////////////////////////////////////////
00732 EggTexture::Format EggTexture::
00733 string_format(const string &string) {
00734   if (cmp_nocase_uh(string, "rgba") == 0) {
00735     return F_rgba;
00736   } else if (cmp_nocase_uh(string, "rgbm") == 0) {
00737     return F_rgbm;
00738   } else if (cmp_nocase_uh(string, "rgba12") == 0) {
00739     return F_rgba12;
00740   } else if (cmp_nocase_uh(string, "rgba8") == 0) {
00741     return F_rgba8;
00742   } else if (cmp_nocase_uh(string, "rgba4") == 0) {
00743     return F_rgba4;
00744 
00745   } else if (cmp_nocase_uh(string, "rgb") == 0) {
00746     return F_rgb;
00747   } else if (cmp_nocase_uh(string, "rgb12") == 0) {
00748     return F_rgb12;
00749   } else if (cmp_nocase_uh(string, "rgb8") == 0) {
00750     return F_rgb8;
00751   } else if (cmp_nocase_uh(string, "rgb5") == 0) {
00752     return F_rgb5;
00753   } else if (cmp_nocase_uh(string, "rgba5") == 0) {
00754     return F_rgba5;
00755   } else if (cmp_nocase_uh(string, "rgb332") == 0) {
00756     return F_rgb332;
00757   } else if (cmp_nocase_uh(string, "red") == 0) {
00758     return F_red;
00759   } else if (cmp_nocase_uh(string, "green") == 0) {
00760     return F_green;
00761   } else if (cmp_nocase_uh(string, "blue") == 0) {
00762     return F_blue;
00763   } else if (cmp_nocase_uh(string, "alpha") == 0) {
00764     return F_alpha;
00765   } else if (cmp_nocase_uh(string, "luminance") == 0) {
00766     return F_luminance;
00767   } else if (cmp_nocase_uh(string, "luminance_alpha") == 0) {
00768     return F_luminance_alpha;
00769   } else if (cmp_nocase_uh(string, "luminance_alphamask") == 0) {
00770     return F_luminance_alphamask;
00771   } else {
00772     return F_unspecified;
00773   }
00774 }
00775 
00776 ////////////////////////////////////////////////////////////////////
00777 //     Function: EggTexture::string_compression_mode
00778 //       Access: Published, Static
00779 //  Description: Returns the CompressionMode value associated with the given
00780 //               string representation, or CM_default if the string
00781 //               does not match any known CompressionMode value.
00782 ////////////////////////////////////////////////////////////////////
00783 EggTexture::CompressionMode EggTexture::
00784 string_compression_mode(const string &string) {
00785   if (cmp_nocase_uh(string, "off") == 0) {
00786     return CM_off;
00787   } else if (cmp_nocase_uh(string, "on") == 0) {
00788     return CM_on;
00789   } else if (cmp_nocase_uh(string, "fxt1") == 0) {
00790     return CM_fxt1;
00791   } else if (cmp_nocase_uh(string, "dxt1") == 0) {
00792     return CM_dxt1;
00793   } else if (cmp_nocase_uh(string, "dxt2") == 0) {
00794     return CM_dxt2;
00795   } else if (cmp_nocase_uh(string, "dxt3") == 0) {
00796     return CM_dxt3;
00797   } else if (cmp_nocase_uh(string, "dxt4") == 0) {
00798     return CM_dxt4;
00799   } else if (cmp_nocase_uh(string, "dxt5") == 0) {
00800     return CM_dxt5;
00801   } else {
00802     return CM_default;
00803   }
00804 }
00805 
00806 ////////////////////////////////////////////////////////////////////
00807 //     Function: EggTexture::string_wrap_mode
00808 //       Access: Published, Static
00809 //  Description: Returns the WrapMode value associated with the given
00810 //               string representation, or WM_unspecified if the string
00811 //               does not match any known WrapMode value.
00812 ////////////////////////////////////////////////////////////////////
00813 EggTexture::WrapMode EggTexture::
00814 string_wrap_mode(const string &string) {
00815   if (cmp_nocase_uh(string, "repeat") == 0) {
00816     return WM_repeat;
00817   } else if (cmp_nocase_uh(string, "clamp") == 0) {
00818     return WM_clamp;
00819   } else if (cmp_nocase_uh(string, "mirror") == 0) {
00820     return WM_mirror;
00821   } else if (cmp_nocase_uh(string, "mirror_once") == 0) {
00822     return WM_mirror_once;
00823   } else if (cmp_nocase_uh(string, "border_color") == 0) {
00824     return WM_border_color;
00825   } else {
00826     return WM_unspecified;
00827   }
00828 }
00829 
00830 ////////////////////////////////////////////////////////////////////
00831 //     Function: EggTexture::string_filter_type
00832 //       Access: Published, Static
00833 //  Description: Returns the FilterType value associated with the given
00834 //               string representation, or FT_unspecified if the string
00835 //               does not match any known FilterType value.
00836 ////////////////////////////////////////////////////////////////////
00837 EggTexture::FilterType EggTexture::
00838 string_filter_type(const string &string) {
00839   // Old egg filter types.
00840   if (cmp_nocase_uh(string, "point") == 0) {
00841     return FT_nearest;
00842   } else if (cmp_nocase_uh(string, "linear") == 0) {
00843     return FT_linear;
00844   } else if (cmp_nocase_uh(string, "bilinear") == 0) {
00845     return FT_linear;
00846   } else if (cmp_nocase_uh(string, "trilinear") == 0) {
00847     return FT_linear_mipmap_linear;
00848   } else if (cmp_nocase_uh(string, "mipmap") == 0) {
00849     return FT_linear_mipmap_linear;
00850   } else if (cmp_nocase_uh(string, "mipmap_point") == 0) {
00851     return FT_nearest_mipmap_nearest;
00852   } else if (cmp_nocase_uh(string, "mipmap_linear") == 0) {
00853     return FT_nearest_mipmap_linear;
00854   } else if (cmp_nocase_uh(string, "mipmap_bilinear") == 0) {
00855     return FT_linear_mipmap_nearest;
00856   } else if (cmp_nocase_uh(string, "mipmap_trilinear") == 0) {
00857     return FT_linear_mipmap_linear;
00858 
00859     // Current egg filter types, that match those in Texture.
00860   } else if (cmp_nocase_uh(string, "nearest") == 0) {
00861     return FT_nearest;
00862   } else if (cmp_nocase_uh(string, "linear") == 0) {
00863     return FT_linear;
00864   } else if (cmp_nocase_uh(string, "nearest_mipmap_nearest") == 0) {
00865     return FT_nearest_mipmap_nearest;
00866   } else if (cmp_nocase_uh(string, "linear_mipmap_nearest") == 0) {
00867     return FT_linear_mipmap_nearest;
00868   } else if (cmp_nocase_uh(string, "nearest_mipmap_linear") == 0) {
00869     return FT_nearest_mipmap_linear;
00870   } else if (cmp_nocase_uh(string, "linear_mipmap_linear") == 0) {
00871     return FT_linear_mipmap_linear;
00872 
00873   } else {
00874     return FT_unspecified;
00875   }
00876 }
00877 
00878 ////////////////////////////////////////////////////////////////////
00879 //     Function: EggTexture::string_env_type
00880 //       Access: Published, Static
00881 //  Description: Returns the EnvType value associated with the given
00882 //               string representation, or ET_unspecified if the string
00883 //               does not match any known EnvType value.
00884 ////////////////////////////////////////////////////////////////////
00885 EggTexture::EnvType EggTexture::
00886 string_env_type(const string &string) {
00887   if (cmp_nocase_uh(string, "modulate") == 0) {
00888     return ET_modulate;
00889 
00890   } else if (cmp_nocase_uh(string, "decal") == 0) {
00891     return ET_decal;
00892 
00893   } else if (cmp_nocase_uh(string, "blend") == 0) {
00894     return ET_blend;
00895 
00896   } else if (cmp_nocase_uh(string, "replace") == 0) {
00897     return ET_replace;
00898 
00899   } else if (cmp_nocase_uh(string, "add") == 0) {
00900     return ET_add;
00901 
00902   } else if (cmp_nocase_uh(string, "blend_color_scale") == 0) {
00903     return ET_blend_color_scale;
00904 
00905   } else if (cmp_nocase_uh(string, "modulate_glow") == 0) {
00906     return ET_modulate_glow;
00907 
00908   } else if (cmp_nocase_uh(string, "modulate_gloss") == 0) {
00909     return ET_modulate_gloss;
00910 
00911   } else if (cmp_nocase_uh(string, "normal") == 0) {
00912     return ET_normal;
00913 
00914   } else if (cmp_nocase_uh(string, "normal_height") == 0) {
00915     return ET_normal_height;
00916 
00917   } else if (cmp_nocase_uh(string, "glow") == 0) {
00918     return ET_glow;
00919 
00920   } else if (cmp_nocase_uh(string, "gloss") == 0) {
00921     return ET_gloss;
00922 
00923   } else if (cmp_nocase_uh(string, "height") == 0) {
00924     return ET_height;
00925 
00926   } else if (cmp_nocase_uh(string, "selector") == 0) {
00927     return ET_selector;
00928 
00929   } else if (cmp_nocase_uh(string, "normal_gloss") == 0) {
00930     return ET_normal_gloss;
00931 
00932   } else {
00933     return ET_unspecified;
00934   }
00935 }
00936 
00937 ////////////////////////////////////////////////////////////////////
00938 //     Function: EggTexture::string_combine_mode
00939 //       Access: Published, Static
00940 //  Description: Returns the CombineMode value associated with the given
00941 //               string representation, or CM_unspecified if the string
00942 //               does not match any known CombineMode value.
00943 ////////////////////////////////////////////////////////////////////
00944 EggTexture::CombineMode EggTexture::
00945 string_combine_mode(const string &string) {
00946   if (cmp_nocase_uh(string, "replace") == 0) {
00947     return CM_replace;
00948 
00949   } else if (cmp_nocase_uh(string, "modulate") == 0) {
00950     return CM_modulate;
00951 
00952   } else if (cmp_nocase_uh(string, "add") == 0) {
00953     return CM_add;
00954 
00955   } else if (cmp_nocase_uh(string, "add_signed") == 0) {
00956     return CM_add_signed;
00957 
00958   } else if (cmp_nocase_uh(string, "interpolate") == 0) {
00959     return CM_interpolate;
00960 
00961   } else if (cmp_nocase_uh(string, "subtract") == 0) {
00962     return CM_subtract;
00963 
00964   } else if (cmp_nocase_uh(string, "dot3_rgb") == 0) {
00965     return CM_dot3_rgb;
00966 
00967   } else if (cmp_nocase_uh(string, "dot3_rgba") == 0) {
00968     return CM_dot3_rgba;
00969 
00970   } else {
00971     return CM_unspecified;
00972   }
00973 }
00974 
00975 ////////////////////////////////////////////////////////////////////
00976 //     Function: EggTexture::string_combine_source
00977 //       Access: Published, Static
00978 //  Description: Returns the CombineSource value associated with the given
00979 //               string representation, or CS_unspecified if the string
00980 //               does not match any known CombineSource value.
00981 ////////////////////////////////////////////////////////////////////
00982 EggTexture::CombineSource EggTexture::
00983 string_combine_source(const string &string) {
00984   if (cmp_nocase_uh(string, "texture") == 0) {
00985     return CS_texture;
00986 
00987   } else if (cmp_nocase_uh(string, "constant") == 0) {
00988     return CS_constant;
00989 
00990   } else if (cmp_nocase_uh(string, "primary_color") == 0) {
00991     return CS_primary_color;
00992 
00993   } else if (cmp_nocase_uh(string, "previous") == 0) {
00994     return CS_previous;
00995 
00996   } else if (cmp_nocase_uh(string, "constant_color_scale") == 0) {
00997     return CS_constant_color_scale;
00998 
00999   } else if (cmp_nocase_uh(string, "last_saved_result") == 0) {
01000     return CS_last_saved_result;
01001 
01002   } else {
01003     return CS_unspecified;
01004   }
01005 }
01006 
01007 ////////////////////////////////////////////////////////////////////
01008 //     Function: EggTexture::string_combine_operand
01009 //       Access: Published, Static
01010 //  Description: Returns the CombineOperand value associated with the given
01011 //               string representation, or CO_unspecified if the string
01012 //               does not match any known CombineOperand value.
01013 ////////////////////////////////////////////////////////////////////
01014 EggTexture::CombineOperand EggTexture::
01015 string_combine_operand(const string &string) {
01016   if (cmp_nocase_uh(string, "src_color") == 0) {
01017     return CO_src_color;
01018 
01019   } else if (cmp_nocase_uh(string, "one_minus_src_color") == 0) {
01020     return CO_one_minus_src_color;
01021 
01022   } else if (cmp_nocase_uh(string, "src_alpha") == 0) {
01023     return CO_src_alpha;
01024 
01025   } else if (cmp_nocase_uh(string, "one_minus_src_alpha") == 0) {
01026     return CO_one_minus_src_alpha;
01027 
01028   } else {
01029     return CO_unspecified;
01030   }
01031 }
01032 
01033 ////////////////////////////////////////////////////////////////////
01034 //     Function: EggTexture::string_tex_gen
01035 //       Access: Published, Static
01036 //  Description: Returns the TexGen value associated with the given
01037 //               string representation, or ET_unspecified if the string
01038 //               does not match any known TexGen value.
01039 ////////////////////////////////////////////////////////////////////
01040 EggTexture::TexGen EggTexture::
01041 string_tex_gen(const string &string) {
01042   if (cmp_nocase_uh(string, "unspecified") == 0) {
01043     return TG_unspecified;
01044 
01045   } else if (cmp_nocase_uh(string, "sphere_map") == 0 ||
01046              cmp_nocase_uh(string, "eye_sphere_map") == 0) {
01047     return TG_eye_sphere_map;
01048 
01049   } else if (cmp_nocase_uh(string, "world_cube_map") == 0) {
01050     return TG_world_cube_map;
01051 
01052   } else if (cmp_nocase_uh(string, "cube_map") == 0 ||
01053              cmp_nocase_uh(string, "eye_cube_map") == 0) {
01054     return TG_eye_cube_map;
01055 
01056   } else if (cmp_nocase_uh(string, "world_normal") == 0) {
01057     return TG_world_normal;
01058 
01059   } else if (cmp_nocase_uh(string, "eye_normal") == 0) {
01060     return TG_eye_normal;
01061 
01062   } else if (cmp_nocase_uh(string, "world_position") == 0) {
01063     return TG_world_position;
01064 
01065   } else if (cmp_nocase_uh(string, "eye_position") == 0) {
01066     return TG_eye_position;
01067 
01068   } else if (cmp_nocase_uh(string, "point_sprite") == 0) {
01069     return TG_point_sprite;
01070 
01071   } else {
01072     return TG_unspecified;
01073   }
01074 }
01075 
01076 ////////////////////////////////////////////////////////////////////
01077 //     Function: EggTexture::string_quality_level
01078 //       Access: Published, Static
01079 //  Description: Returns the TexGen value associated with the given
01080 //               string representation, or ET_unspecified if the string
01081 //               does not match any known TexGen value.
01082 ////////////////////////////////////////////////////////////////////
01083 EggTexture::QualityLevel EggTexture::
01084 string_quality_level(const string &string) {
01085   if (cmp_nocase_uh(string, "unspecified") == 0) {
01086     return QL_unspecified;
01087 
01088   } else if (cmp_nocase_uh(string, "default") == 0) {
01089     return QL_default;
01090 
01091   } else if (cmp_nocase_uh(string, "fastest") == 0) {
01092     return QL_fastest;
01093 
01094   } else if (cmp_nocase_uh(string, "normal") == 0) {
01095     return QL_normal;
01096 
01097   } else if (cmp_nocase_uh(string, "best") == 0) {
01098     return QL_best;
01099 
01100   } else {
01101     return QL_unspecified;
01102   }
01103 }
01104 
01105 ////////////////////////////////////////////////////////////////////
01106 //     Function: EggTexture::as_transform
01107 //       Access: Public, Virtual
01108 //  Description: Returns this object cross-cast to an EggTransform
01109 //               pointer, if it inherits from EggTransform, or NULL if
01110 //               it does not.
01111 ////////////////////////////////////////////////////////////////////
01112 EggTransform *EggTexture::
01113 as_transform() {
01114   return this;
01115 }
01116 
01117 ////////////////////////////////////////////////////////////////////
01118 //     Function: EggTexture::egg_start_parse_body
01119 //       Access: Protected, Virtual
01120 //  Description: This function is called within parse_egg().  It
01121 //               should call the appropriate function on the lexer to
01122 //               initialize the parser into the state associated with
01123 //               this object.  If the object cannot be parsed into
01124 //               directly, it should return false.
01125 ////////////////////////////////////////////////////////////////////
01126 bool EggTexture::
01127 egg_start_parse_body() {
01128   egg_start_texture_body();
01129   return true;
01130 }
01131 
01132 ////////////////////////////////////////////////////////////////////
01133 //     Function: EggTexture::r_min_multitexture_sort
01134 //       Access: Private
01135 //  Description: Ensures that our multitexture_sort is at least the
01136 //               indicated value.
01137 ////////////////////////////////////////////////////////////////////
01138 bool EggTexture::
01139 r_min_multitexture_sort(int sort, EggTexture::MultiTextures &cycle_detector) {
01140   if (_multitexture_sort >= sort) {
01141     // No problem.
01142     return true;
01143   }
01144 
01145   if (!cycle_detector.insert(this).second) {
01146     // Oops, we just hit a cycle!
01147     return false;
01148   }
01149 
01150   _multitexture_sort = sort;
01151 
01152   // Now we also have to increment all of the textures that we are
01153   // under.
01154   bool no_cycles = true;
01155 
01156   MultiTextures::iterator mti;
01157   for (mti = _under_textures.begin();
01158        mti != _under_textures.end();
01159        ++mti) {
01160     EggTexture *other = (*mti);
01161     if (!other->r_min_multitexture_sort(sort + 1, cycle_detector)) {
01162       // Oops, found a cycle!
01163       no_cycles = false;
01164     }
01165   }
01166 
01167   return no_cycles;
01168 }
01169 
01170 
01171 ////////////////////////////////////////////////////////////////////
01172 //     Function: TextureType output operator
01173 //  Description:
01174 ////////////////////////////////////////////////////////////////////
01175 ostream &operator << (ostream &out, EggTexture::TextureType texture_type) {
01176   switch (texture_type) {
01177   case EggTexture::TT_unspecified:
01178     return out << "unspecified";
01179 
01180   case EggTexture::TT_1d_texture:
01181     return out << "1d";
01182 
01183   case EggTexture::TT_2d_texture:
01184     return out << "2d";
01185 
01186   case EggTexture::TT_3d_texture:
01187     return out << "3d";
01188 
01189   case EggTexture::TT_cube_map:
01190     return out << "cube-map";
01191   }
01192 
01193   nassertr(false, out);
01194   return out << "(**invalid**)";
01195 }
01196 
01197 
01198 ////////////////////////////////////////////////////////////////////
01199 //     Function: Format output operator
01200 //  Description:
01201 ////////////////////////////////////////////////////////////////////
01202 ostream &operator << (ostream &out, EggTexture::Format format) {
01203   switch (format) {
01204   case EggTexture::F_unspecified:
01205     return out << "unspecified";
01206 
01207   case EggTexture::F_rgba:
01208     return out << "rgba";
01209   case EggTexture::F_rgbm:
01210     return out << "rgbm";
01211   case EggTexture::F_rgba12:
01212     return out << "rgba12";
01213   case EggTexture::F_rgba8:
01214     return out << "rgba8";
01215   case EggTexture::F_rgba4:
01216     return out << "rgba4";
01217 
01218   case EggTexture::F_rgb:
01219     return out << "rgb";
01220   case EggTexture::F_rgb12:
01221     return out << "rgb12";
01222   case EggTexture::F_rgb8:
01223     return out << "rgb8";
01224   case EggTexture::F_rgb5:
01225     return out << "rgb5";
01226   case EggTexture::F_rgba5:
01227     return out << "rgba5";
01228   case EggTexture::F_rgb332:
01229     return out << "rgb332";
01230 
01231   case EggTexture::F_red:
01232     return out << "red";
01233   case EggTexture::F_green:
01234     return out << "green";
01235   case EggTexture::F_blue:
01236     return out << "blue";
01237   case EggTexture::F_alpha:
01238     return out << "alpha";
01239   case EggTexture::F_luminance:
01240     return out << "luminance";
01241   case EggTexture::F_luminance_alpha:
01242     return out << "luminance_alpha";
01243   case EggTexture::F_luminance_alphamask:
01244     return out << "luminance_alphamask";
01245   }
01246 
01247   nassertr(false, out);
01248   return out << "(**invalid**)";
01249 }
01250 
01251 ////////////////////////////////////////////////////////////////////
01252 //     Function: CompressionMode output operator
01253 //  Description:
01254 ////////////////////////////////////////////////////////////////////
01255 ostream &operator << (ostream &out, EggTexture::CompressionMode mode) {
01256   switch (mode) {
01257   case EggTexture::CM_default:
01258     return out << "default";
01259   case EggTexture::CM_off:
01260     return out << "off";
01261   case EggTexture::CM_on:
01262     return out << "on";
01263   case EggTexture::CM_fxt1:
01264     return out << "fxt1";
01265   case EggTexture::CM_dxt1:
01266     return out << "dxt1";
01267   case EggTexture::CM_dxt2:
01268     return out << "dxt2";
01269   case EggTexture::CM_dxt3:
01270     return out << "dxt3";
01271   case EggTexture::CM_dxt4:
01272     return out << "dxt4";
01273   case EggTexture::CM_dxt5:
01274     return out << "dxt5";
01275   }
01276 
01277   nassertr(false, out);
01278   return out << "(**invalid**)";
01279 }
01280 
01281 ////////////////////////////////////////////////////////////////////
01282 //     Function: WrapMode output operator
01283 //  Description:
01284 ////////////////////////////////////////////////////////////////////
01285 ostream &operator << (ostream &out, EggTexture::WrapMode mode) {
01286   switch (mode) {
01287   case EggTexture::WM_unspecified:
01288     return out << "unspecified";
01289   case EggTexture::WM_repeat:
01290     return out << "repeat";
01291   case EggTexture::WM_clamp:
01292     return out << "clamp";
01293   case EggTexture::WM_mirror:
01294     return out << "mirror";
01295   case EggTexture::WM_mirror_once:
01296     return out << "mirror_once";
01297   case EggTexture::WM_border_color:
01298     return out << "border_color";
01299   }
01300 
01301   nassertr(false, out);
01302   return out << "(**invalid**)";
01303 }
01304 
01305 ////////////////////////////////////////////////////////////////////
01306 //     Function: FilterType output operator
01307 //  Description:
01308 ////////////////////////////////////////////////////////////////////
01309 ostream &operator << (ostream &out, EggTexture::FilterType type) {
01310   switch (type) {
01311   case EggTexture::FT_unspecified:
01312     return out << "unspecified";
01313 
01314   case EggTexture::FT_nearest:
01315     return out << "nearest";
01316   case EggTexture::FT_linear:
01317     return out << "linear";
01318 
01319   case EggTexture::FT_nearest_mipmap_nearest:
01320     return out << "nearest_mipmap_nearest";
01321   case EggTexture::FT_linear_mipmap_nearest:
01322     return out << "linear_mipmap_nearest";
01323   case EggTexture::FT_nearest_mipmap_linear:
01324     return out << "nearest_mipmap_linear";
01325   case EggTexture::FT_linear_mipmap_linear:
01326     return out << "linear_mipmap_linear";
01327   }
01328 
01329   nassertr(false, out);
01330   return out << "(**invalid**)";
01331 }
01332 
01333 ////////////////////////////////////////////////////////////////////
01334 //     Function: EnvType output operator
01335 //  Description:
01336 ////////////////////////////////////////////////////////////////////
01337 ostream &operator << (ostream &out, EggTexture::EnvType type) {
01338   switch (type) {
01339   case EggTexture::ET_unspecified:
01340     return out << "unspecified";
01341 
01342   case EggTexture::ET_modulate:
01343     return out << "modulate";
01344 
01345   case EggTexture::ET_decal:
01346     return out << "decal";
01347 
01348   case EggTexture::ET_blend:
01349     return out << "blend";
01350 
01351   case EggTexture::ET_replace:
01352     return out << "replace";
01353 
01354   case EggTexture::ET_add:
01355     return out << "add";
01356 
01357   case EggTexture::ET_blend_color_scale:
01358     return out << "blend_color_scale";
01359 
01360   case EggTexture::ET_modulate_glow:
01361     return out << "modulate_glow";
01362 
01363   case EggTexture::ET_modulate_gloss:
01364     return out << "modulate_gloss";
01365 
01366   case EggTexture::ET_normal:
01367     return out << "normal";
01368 
01369   case EggTexture::ET_normal_height:
01370     return out << "normal_height";
01371 
01372   case EggTexture::ET_glow:
01373     return out << "glow";
01374     
01375   case EggTexture::ET_gloss:
01376     return out << "gloss";
01377     
01378   case EggTexture::ET_height:
01379     return out << "height";
01380     
01381   case EggTexture::ET_selector:
01382     return out << "selector";
01383 
01384   case EggTexture::ET_normal_gloss:
01385     return out << "normal_gloss";
01386   }
01387 
01388   nassertr(false, out);
01389   return out << "(**invalid**)";
01390 }
01391 
01392 ostream &
01393 operator << (ostream &out, EggTexture::CombineMode cm) {
01394   switch (cm) {
01395   case EggTexture::CM_unspecified:
01396     return out << "unspecified";
01397 
01398   case EggTexture::CM_replace:
01399     return out << "replace";
01400 
01401   case EggTexture::CM_modulate:
01402     return out << "modulate";
01403 
01404   case EggTexture::CM_add:
01405     return out << "add";
01406 
01407   case EggTexture::CM_add_signed:
01408     return out << "add_signed";
01409 
01410   case EggTexture::CM_interpolate:
01411     return out << "interpolate";
01412 
01413   case EggTexture::CM_subtract:
01414     return out << "subtract";
01415 
01416   case EggTexture::CM_dot3_rgb:
01417     return out << "dot3_rgb";
01418 
01419   case EggTexture::CM_dot3_rgba:
01420     return out << "dot3_rgba";
01421   }
01422 
01423   return out << "**invalid CombineMode(" << (int)cm << ")**";
01424 }
01425 
01426 ostream &
01427 operator << (ostream &out, EggTexture::CombineChannel cm) {
01428   switch (cm) {
01429   case EggTexture::CC_rgb:
01430     return out << "rgb";
01431 
01432   case EggTexture::CC_alpha:
01433     return out << "alpha";
01434 
01435   case EggTexture::CC_num_channels:
01436     // This case is here just to prevent a compiler warning.  Fall out
01437     // of the switch and return the error message.
01438     break;
01439   }
01440 
01441   return out << "**invalid CombineChannel(" << (int)cm << ")**";
01442 }
01443 
01444 ostream &
01445 operator << (ostream &out, EggTexture::CombineSource cs) {
01446   switch (cs) {
01447   case EggTexture::CS_unspecified:
01448     return out << "unspecified";
01449 
01450   case EggTexture::CS_texture:
01451     return out << "texture";
01452 
01453   case EggTexture::CS_constant:
01454     return out << "constant";
01455 
01456   case EggTexture::CS_primary_color:
01457     return out << "primary_color";
01458 
01459   case EggTexture::CS_previous:
01460     return out << "previous";
01461 
01462   case EggTexture::CS_constant_color_scale:
01463     return out << "constant_color_scale";
01464 
01465   case EggTexture::CS_last_saved_result:
01466     return out << "last_saved_result";
01467   }
01468 
01469   return out << "**invalid CombineSource(" << (int)cs << ")**";
01470 }
01471 
01472 ostream &
01473 operator << (ostream &out, EggTexture::CombineOperand co) {
01474   switch (co) {
01475   case EggTexture::CO_unspecified:
01476     return out << "unspecified";
01477 
01478   case EggTexture::CO_src_color:
01479     return out << "src_color";
01480 
01481   case EggTexture::CO_one_minus_src_color:
01482     return out << "one_minus_src_color";
01483 
01484   case EggTexture::CO_src_alpha:
01485     return out << "src_alpha";
01486 
01487   case EggTexture::CO_one_minus_src_alpha:
01488     return out << "one_minus_src_alpha";
01489   }
01490 
01491   return out << "**invalid CombineOperand(" << (int)co << ")**";
01492 }
01493 
01494 ostream &
01495 operator << (ostream &out, EggTexture::TexGen tex_gen) {
01496   switch (tex_gen) {
01497   case EggTexture::TG_unspecified:
01498     return out << "unspecified";
01499 
01500   case EggTexture::TG_eye_sphere_map:
01501     return out << "eye_sphere_map";
01502 
01503   case EggTexture::TG_world_cube_map:
01504     return out << "world_cube_map";
01505 
01506   case EggTexture::TG_eye_cube_map:
01507     return out << "eye_cube_map";
01508 
01509   case EggTexture::TG_world_normal:
01510     return out << "world_normal";
01511 
01512   case EggTexture::TG_eye_normal:
01513     return out << "eye_normal";
01514 
01515   case EggTexture::TG_world_position:
01516     return out << "world_position";
01517 
01518   case EggTexture::TG_eye_position:
01519     return out << "eye_position";
01520 
01521   case EggTexture::TG_point_sprite:
01522     return out << "point_sprite";
01523   }
01524 
01525   return out << "**invalid TexGen(" << (int)tex_gen << ")**";
01526 }
01527 
01528 ostream &
01529 operator << (ostream &out, EggTexture::QualityLevel quality_level) {
01530   switch (quality_level) {
01531   case EggTexture::QL_unspecified:
01532     return out << "unspecified";
01533   case EggTexture::QL_default:
01534     return out << "default";
01535   case EggTexture::QL_fastest:
01536     return out << "fastest";
01537   case EggTexture::QL_normal:
01538     return out << "normal";
01539   case EggTexture::QL_best:
01540     return out << "best";
01541   }
01542 
01543   return out << "**invalid QualityLevel(" << (int)quality_level << ")**";
01544 }
 All Classes Functions Variables Enumerations