Panda3D
 All Classes Functions Variables Enumerations
eggTexture.cxx
1 // Filename: eggTexture.cxx
2 // Created by: drose (18Jan99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggTexture.h"
16 #include "eggMiscFuncs.h"
17 #include "lexerDefs.h"
18 
19 #include "indent.h"
20 #include "string_utils.h"
21 
22 TypeHandle EggTexture::_type_handle;
23 
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: EggTexture::Constructor
27 // Access: Published
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 EggTexture::
31 EggTexture(const string &tref_name, const Filename &filename)
32  : EggFilenameNode(tref_name, filename)
33 {
34  _texture_type = TT_unspecified;
35  _format = F_unspecified;
36  _compression_mode = CM_default;
37  _wrap_mode = WM_unspecified;
38  _wrap_u = WM_unspecified;
39  _wrap_v = WM_unspecified;
40  _wrap_w = WM_unspecified;
41  _minfilter = FT_unspecified;
42  _magfilter = FT_unspecified;
43  _anisotropic_degree = 0;
44  _env_type = ET_unspecified;
45  _saved_result = false;
46  _multiview = false;
47  _num_views = 0;
48  _tex_gen = TG_unspecified;
49  _quality_level = QL_unspecified;
50  _priority = 0;
51  _color.set(0.0f, 0.0f, 0.0f, 1.0f);
52  _border_color.set(0.0f, 0.0f, 0.0f, 1.0f);
53  _flags = 0;
54  _alpha_file_channel = 0;
55  _read_mipmaps = false;
56  _multitexture_sort = 0;
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: EggTexture::Copy constructor
61 // Access: Published
62 // Description:
63 ////////////////////////////////////////////////////////////////////
64 EggTexture::
65 EggTexture(const EggTexture &copy) {
66  (*this) = copy;
67 }
68 
69 ////////////////////////////////////////////////////////////////////
70 // Function: EggTexture::Copy assignment operator
71 // Access: Published
72 // Description:
73 ////////////////////////////////////////////////////////////////////
74 EggTexture &EggTexture::
75 operator = (const EggTexture &copy) {
77 
78  EggFilenameNode::operator = (copy);
79  EggRenderMode::operator = (copy);
80  EggTransform::operator = (copy);
81 
82  _texture_type = copy._texture_type;
83  _format = copy._format;
84  _compression_mode = copy._compression_mode;
85  _wrap_mode = copy._wrap_mode;
86  _wrap_u = copy._wrap_u;
87  _wrap_v = copy._wrap_v;
88  _wrap_w = copy._wrap_w;
89  _minfilter = copy._minfilter;
90  _magfilter = copy._magfilter;
91  _anisotropic_degree = copy._anisotropic_degree;
92  _env_type = copy._env_type;
93  _saved_result = copy._saved_result;
94  _multiview = copy._multiview;
95  _num_views = copy._num_views;
96  _tex_gen = copy._tex_gen;
97  _quality_level = copy._quality_level;
98  _stage_name = copy._stage_name;
99  _priority = copy._priority;
100  _color = copy._color;
101  _border_color = copy._border_color;
102  _uv_name = copy._uv_name;
103  _rgb_scale = 1;
104  _alpha_scale = 1;
105  _flags = copy._flags;
106  _alpha_filename = copy._alpha_filename;
107  _alpha_fullpath = copy._alpha_fullpath;
108  _alpha_file_channel = copy._alpha_file_channel;
109  _read_mipmaps = copy._read_mipmaps;
110  _multitexture_sort = 0;
111  _combiner[0] = copy._combiner[0];
112  _combiner[1] = copy._combiner[1];
113 
114  return *this;
115 }
116 
117 ////////////////////////////////////////////////////////////////////
118 // Function: EggTexture::Destructor
119 // Access: Published, Virtual
120 // Description:
121 ////////////////////////////////////////////////////////////////////
122 EggTexture::
123 ~EggTexture() {
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: EggTexture::write
129 // Access: Public, Virtual
130 // Description: Writes the texture definition to the indicated output
131 // stream in Egg format.
132 ////////////////////////////////////////////////////////////////////
133 void EggTexture::
134 write(ostream &out, int indent_level) const {
135  write_header(out, indent_level, "<Texture>");
136  enquote_string(out, get_filename(), indent_level + 2) << "\n";
137 
138  if (has_alpha_filename()) {
139  indent(out, indent_level + 2)
140  << "<Scalar> alpha-file { ";
141  enquote_string(out, get_alpha_filename());
142  out << " }\n";
143  }
144 
145  if (has_alpha_file_channel()) {
146  indent(out, indent_level + 2)
147  << "<Scalar> alpha-file-channel { "
148  << get_alpha_file_channel() << " }\n";
149  }
150 
151  if (get_read_mipmaps()) {
152  indent(out, indent_level + 2)
153  << "<Scalar> read-mipmaps { 1 }\n";
154  }
155 
156  if (get_texture_type() != TT_unspecified) {
157  indent(out, indent_level + 2)
158  << "<Scalar> type { " << get_texture_type() << " }\n";
159  }
160 
161  if (get_format() != F_unspecified) {
162  indent(out, indent_level + 2)
163  << "<Scalar> format { " << get_format() << " }\n";
164  }
165 
166  if (get_compression_mode() != CM_default) {
167  indent(out, indent_level + 2)
168  << "<Scalar> compression { " << get_compression_mode() << " }\n";
169  }
170 
171  if (get_wrap_mode() != WM_unspecified) {
172  indent(out, indent_level + 2)
173  << "<Scalar> wrap { " << get_wrap_mode() << " }\n";
174  }
175 
176  if (get_wrap_u() != WM_unspecified) {
177  indent(out, indent_level + 2)
178  << "<Scalar> wrapu { " << get_wrap_u() << " }\n";
179  }
180 
181  if (get_wrap_v() != WM_unspecified) {
182  indent(out, indent_level + 2)
183  << "<Scalar> wrapv { " << get_wrap_v() << " }\n";
184  }
185 
186  if (get_wrap_w() != WM_unspecified) {
187  indent(out, indent_level + 2)
188  << "<Scalar> wrapw { " << get_wrap_w() << " }\n";
189  }
190 
191  if (get_minfilter() != FT_unspecified) {
192  indent(out, indent_level + 2)
193  << "<Scalar> minfilter { " << get_minfilter() << " }\n";
194  }
195 
196  if (get_magfilter() != FT_unspecified) {
197  indent(out, indent_level + 2)
198  << "<Scalar> magfilter { " << get_magfilter() << " }\n";
199  }
200 
201  if (has_anisotropic_degree()) {
202  indent(out, indent_level + 2)
203  << "<Scalar> anisotropic-degree { " << get_anisotropic_degree() << " }\n";
204  }
205 
206  if (get_env_type() != ET_unspecified) {
207  indent(out, indent_level + 2)
208  << "<Scalar> envtype { " << get_env_type() << " }\n";
209  }
210 
211  for (int ci = 0; ci < (int)CC_num_channels; ci++) {
212  CombineChannel channel = (CombineChannel)ci;
213  if (get_combine_mode(channel) != CM_unspecified) {
214  indent(out, indent_level + 2)
215  << "<Scalar> combine-" << channel
216  << " { " << get_combine_mode(channel) << " }\n";
217  }
218  for (int i = 0; i < (int)CI_num_indices; i++) {
219  if (get_combine_source(channel, i) != CS_unspecified) {
220  indent(out, indent_level + 2)
221  << "<Scalar> combine-" << channel << "-source" << i
222  << " { " << get_combine_source(channel, i) << " }\n";
223  }
224  if (get_combine_operand(channel, i) != CO_unspecified) {
225  indent(out, indent_level + 2)
226  << "<Scalar> combine-" << channel << "-operand" << i
227  << " { " << get_combine_operand(channel, i) << " }\n";
228  }
229  }
230  }
231 
232  if (get_saved_result()) {
233  indent(out, indent_level + 2)
234  << "<Scalar> saved-result { 1 }\n";
235  }
236 
237  if (get_tex_gen() != TG_unspecified) {
238  indent(out, indent_level + 2)
239  << "<Scalar> tex-gen { " << get_tex_gen() << " }\n";
240  }
241 
242  if (get_quality_level() != QL_unspecified) {
243  indent(out, indent_level + 2)
244  << "<Scalar> quality-level { " << get_quality_level() << " }\n";
245  }
246 
247  if (has_stage_name()) {
248  indent(out, indent_level + 2)
249  << "<Scalar> stage-name { " << get_stage_name() << " }\n";
250  }
251 
252  if (has_priority()) {
253  indent(out, indent_level + 2)
254  << "<Scalar> priority { " << get_priority() << " }\n";
255  }
256 
257  if (has_color()) {
258  indent(out, indent_level + 2)
259  << "<Scalar> blendr { " << _color[0] << " }\n";
260  indent(out, indent_level + 2)
261  << "<Scalar> blendg { " << _color[1] << " }\n";
262  indent(out, indent_level + 2)
263  << "<Scalar> blendb { " << _color[2] << " }\n";
264  indent(out, indent_level + 2)
265  << "<Scalar> blenda { " << _color[3] << " }\n";
266  }
267 
268  if (has_border_color()) {
269  indent(out, indent_level + 2)
270  << "<Scalar> borderr { " << _border_color[0] << " }\n";
271  indent(out, indent_level + 2)
272  << "<Scalar> borderg { " << _border_color[1] << " }\n";
273  indent(out, indent_level + 2)
274  << "<Scalar> borderb { " << _border_color[2] << " }\n";
275  indent(out, indent_level + 2)
276  << "<Scalar> bordera { " << _border_color[3] << " }\n";
277  }
278 
279  if (has_uv_name()) {
280  indent(out, indent_level + 2)
281  << "<Scalar> uv-name { " << get_uv_name() << " }\n";
282  }
283 
284  if (has_rgb_scale()) {
285  indent(out, indent_level + 2)
286  << "<Scalar> rgb-scale { " << get_rgb_scale() << " }\n";
287  }
288 
289  if (has_alpha_scale()) {
290  indent(out, indent_level + 2)
291  << "<Scalar> alpha-scale { " << get_alpha_scale() << " }\n";
292  }
293 
294  if (get_multiview()) {
295  indent(out, indent_level + 2)
296  << "<Scalar> multiview { 1 }\n";
297  }
298 
299  if (has_num_views()) {
300  indent(out, indent_level + 2)
301  << "<Scalar> num-views { " << get_num_views() << " }\n";
302  }
303 
304  EggRenderMode::write(out, indent_level + 2);
305 
306  if (has_transform()) {
307  EggTransform::write(out, indent_level + 2, "<Transform>");
308  }
309 
310  indent(out, indent_level) << "}\n";
311 }
312 
313 ////////////////////////////////////////////////////////////////////
314 // Function: EggTexture::is_equivalent_to
315 // Access: Published
316 // Description: Returns true if the two textures are equivalent in
317 // all relevant properties (according to eq), false
318 // otherwise.
319 //
320 // The Equivalence parameter, eq, should be set to the
321 // bitwise OR of the following properties, according to
322 // what you consider relevant:
323 //
324 // EggTexture::E_basename:
325 // The basename part of the texture filename, without
326 // the directory prefix *or* the filename extension.
327 //
328 // EggTexture::E_extension:
329 // The extension part of the texture filename.
330 //
331 // EggTexture::E_dirname:
332 // The directory prefix of the texture filename.
333 //
334 // EggTexture::E_complete_filename:
335 // The union of the above three; that is, the complete
336 // filename, with directory, basename, and extension.
337 //
338 // EggTexture::E_transform:
339 // The texture matrix.
340 //
341 // EggTexture::E_attributes:
342 // All remaining texture attributes (mode, mipmap,
343 // etc.) except TRef name.
344 //
345 // EggTexture::E_tref_name:
346 // The TRef name.
347 ////////////////////////////////////////////////////////////////////
348 bool EggTexture::
349 is_equivalent_to(const EggTexture &other, int eq) const {
350  if ((eq & E_complete_filename) == E_complete_filename) {
351  //cout << "compared by filename" << endl;
352  if (get_filename() != other.get_filename()) {
353  return false;
354  }
355  } else {
356  //cout << "compared by not complete filename" << endl;
357  const Filename &a = get_filename();
358  const Filename &b = other.get_filename();
359 
360  if (eq & E_basename) {
362  return false;
363  }
364  }
365  if (eq & E_extension) {
366  if (a.get_extension() != b.get_extension()) {
367  return false;
368  }
369  }
370  if (eq & E_dirname) {
371  if (a.get_dirname() != b.get_dirname()) {
372  return false;
373  }
374  }
375  }
376 
377  if (eq & E_transform) {
378  //cout << "compared by transform" << endl;
379  if (transform_is_identity() != other.transform_is_identity()) {
380  return false;
381  }
382 
383  if (has_transform() && other.has_transform()) {
384  if (!get_transform3d().almost_equal(other.get_transform3d(), 0.0001)) {
385  return false;
386  }
387  }
388  }
389 
390  if (eq & E_attributes) {
391  //cout << "compared by attributes" << endl;
392  if (_texture_type != other._texture_type ||
393  _format != other._format ||
394  _compression_mode != other._compression_mode ||
395  _wrap_mode != other._wrap_mode ||
396  _wrap_u != other._wrap_u ||
397  _wrap_v != other._wrap_v ||
398  _wrap_w != other._wrap_w ||
399  _minfilter != other._minfilter ||
400  _magfilter != other._magfilter ||
401  _env_type != other._env_type) {
402  return false;
403  }
404  if (EggRenderMode::operator != (other)) {
405  return false;
406  }
407  }
408 
409  if (eq & E_tref_name) {
410  //cout << "compared by tref_name" << endl;
411  if (get_name() != other.get_name()) {
412  return false;
413  }
414  }
415 
416  return true;
417 }
418 
419 ////////////////////////////////////////////////////////////////////
420 // Function: EggTexture::sorts_less_than
421 // Access: Published
422 // Description: An ordering operator to compare two textures for
423 // sorting order. This imposes an arbitrary ordering
424 // useful to identify unique textures, according to the
425 // indicated Equivalence factor. See
426 // is_equivalent_to().
427 ////////////////////////////////////////////////////////////////////
428 bool EggTexture::
429 sorts_less_than(const EggTexture &other, int eq) const {
430  if ((eq & E_complete_filename) == E_complete_filename) {
431  if (get_filename() != other.get_filename()) {
432  return get_filename() < other.get_filename();
433  }
434  } else {
435  const Filename &a = get_filename();
436  const Filename &b = other.get_filename();
437 
438  if (eq & E_basename) {
441  }
442  }
443  if (eq & E_extension) {
444  if (a.get_extension() != b.get_extension()) {
445  return a.get_extension() < b.get_extension();
446  }
447  }
448  if (eq & E_dirname) {
449  if (a.get_dirname() != b.get_dirname()) {
450  return a.get_dirname() < b.get_dirname();
451  }
452  }
453  }
454 
455  if (eq & E_transform) {
456  bool is_identity = transform_is_identity();
457  bool other_is_identity = other.transform_is_identity();
458  if (is_identity != other_is_identity) {
459  return (int)is_identity < (int)other_is_identity;
460  }
461 
462  if (has_transform() && other.has_transform()) {
463  int compare = get_transform3d().compare_to(other.get_transform3d());
464  if (compare != 0) {
465  return compare < 0;
466  }
467  }
468  }
469 
470  if (eq & E_attributes) {
471  if (_texture_type != other._texture_type) {
472  return (int)_texture_type < (int)other._texture_type;
473  }
474  if (_format != other._format) {
475  return (int)_format < (int)other._format;
476  }
477  if (_compression_mode != other._compression_mode) {
478  return (int)_compression_mode < (int)other._compression_mode;
479  }
480  if (_wrap_mode != other._wrap_mode) {
481  return (int)_wrap_mode < (int)other._wrap_mode;
482  }
483  if (_wrap_u != other._wrap_u) {
484  return (int)_wrap_u < (int)other._wrap_u;
485  }
486  if (_wrap_v != other._wrap_v) {
487  return (int)_wrap_v < (int)other._wrap_v;
488  }
489  if (_wrap_w != other._wrap_w) {
490  return (int)_wrap_w < (int)other._wrap_w;
491  }
492  if (_minfilter != other._minfilter) {
493  return (int)_minfilter < (int)other._minfilter;
494  }
495  if (_magfilter != other._magfilter) {
496  return (int)_magfilter < (int)other._magfilter;
497  }
498  if (_anisotropic_degree != other._anisotropic_degree) {
499  return _anisotropic_degree < other._anisotropic_degree;
500  }
501  if (_env_type != other._env_type) {
502  return (int)_env_type < (int)other._env_type;
503  }
504  if (EggRenderMode::operator != (other)) {
505  return EggRenderMode::operator < (other);
506  }
507  }
508 
509  if (eq & E_tref_name) {
510  if (get_name() != other.get_name()) {
511  return get_name() < other.get_name();
512  }
513  }
514 
515  return false;
516 }
517 
518 ////////////////////////////////////////////////////////////////////
519 // Function: EggTexture::has_alpha_channel
520 // Access: Published
521 // Description: Given the number of color components (channels) in
522 // the image file as actually read from the disk, return
523 // true if this texture seems to have an alpha channel
524 // or not. This depends on the EggTexture's format as
525 // well as the number of channels.
526 ////////////////////////////////////////////////////////////////////
527 bool EggTexture::
528 has_alpha_channel(int num_components) const {
529  switch (_format) {
530  case F_red:
531  case F_green:
532  case F_blue:
533  case F_luminance:
534  case F_rgb:
535  case F_rgb12:
536  case F_rgb8:
537  case F_rgb5:
538  case F_rgb332:
539  // These formats never use alpha, regardless of the number of
540  // components we have.
541  return false;
542 
543  case F_alpha:
544  // This format always uses alpha.
545  return true;
546 
547  case F_luminance_alpha:
548  case F_luminance_alphamask:
549  case F_rgba:
550  case F_rgbm:
551  case F_rgba12:
552  case F_rgba8:
553  case F_rgba4:
554  case F_rgba5:
555  case F_unspecified:
556  // These formats use alpha if the image had alpha.
557  return (num_components == 2 || num_components == 4);
558  }
559 
560  return false;
561 }
562 
563 ////////////////////////////////////////////////////////////////////
564 // Function: EggTexture::affects_polygon_alpha
565 // Access: Published
566 // Description: Returns true if this texture's environment type or
567 // combine mode allows the texture to have an effect on
568 // the polygon's alpha values, false otherwise.
569 ////////////////////////////////////////////////////////////////////
570 bool EggTexture::
572  switch (_env_type) {
573  case ET_modulate:
574  case ET_replace:
575  return true;
576 
577  case ET_decal:
578  case ET_blend:
579  case ET_add:
580  case ET_blend_color_scale:
581  case ET_modulate_glow:
582  case ET_modulate_gloss:
583  case ET_normal:
584  case ET_normal_height:
585  case ET_glow:
586  case ET_gloss:
587  case ET_height:
588  case ET_normal_gloss:
589  return false;
590 
591  case ET_selector:
592  return true;
593 
594  case ET_unspecified:
595  break;
596  }
597 
598  switch (_combiner[CC_alpha]._mode) {
599  case CM_replace:
600  case CM_modulate:
601  case CM_add_signed:
602  case CM_subtract:
603  return true;
604 
605  case CM_interpolate:
606  case CM_add:
607  case CM_dot3_rgb:
608  case CM_dot3_rgba:
609  return false;
610 
611  case CM_unspecified:
612  break;
613  }
614 
615  // A completely unspecified texture environment implies "modulate",
616  // which does affect alpha.
617  return true;
618 }
619 
620 
621 ////////////////////////////////////////////////////////////////////
622 // Function: EggTexture::clear_multitexture
623 // Access: Published
624 // Description: Resets the multitexture flags set by
625 // multitexture_over(). After this call,
626 // get_multitexture() will return false, and
627 // get_multitexture_sort() will return 0.
628 ////////////////////////////////////////////////////////////////////
629 void EggTexture::
631  _multitexture_sort = 0;
632 
633  // Now empty out the _over_textures and _under_textures sets. This
634  // requires a bit of care so we don't end up in mutual recursion or
635  // iterating through self-modifying structures. To avoid this, we
636  // empty the sets first, and then walk through their original
637  // contents.
638  MultiTextures orig_over_textures, orig_under_textures;
639  orig_over_textures.swap(_over_textures);
640  orig_under_textures.swap(_under_textures);
641 
642  MultiTextures::iterator mti;
643  for (mti = orig_over_textures.begin();
644  mti != orig_over_textures.end();
645  ++mti) {
646  EggTexture *other = (*mti);
647  other->_under_textures.erase(this);
648  }
649  for (mti = orig_under_textures.begin();
650  mti != orig_under_textures.end();
651  ++mti) {
652  EggTexture *other = (*mti);
653  other->_over_textures.erase(this);
654  }
655 }
656 
657 ////////////////////////////////////////////////////////////////////
658 // Function: EggTexture::multitexture_over
659 // Access: Published
660 // Description: Indicates that this texture should be layered on top
661 // of the other texture. This will guarantee that
662 // this->get_multitexture_sort() >
663 // other->get_multitexture_sort(), at least until
664 // clear_multitexture() is called on either one.
665 //
666 // The return value is true if successful, or false if
667 // there is a failure because the other texture was
668 // already layered on top of this one (or there is a
669 // three- or more-way cycle).
670 ////////////////////////////////////////////////////////////////////
671 bool EggTexture::
673  if (get_multitexture_sort() <= other->get_multitexture_sort()) {
674  MultiTextures cycle_detector;
675  if (!r_min_multitexture_sort(other->get_multitexture_sort() + 1,
676  cycle_detector)) {
677  // Found a cycle right off the bat!
678  return false;
679  }
680  }
681 
682  if (_over_textures.insert(other).second) {
683  bool inserted_under = other->_under_textures.insert(this).second;
684  nassertr(inserted_under, false);
685  }
686  nassertr(get_multitexture_sort() > other->get_multitexture_sort(), false);
687 
688  return true;
689 }
690 
691 ////////////////////////////////////////////////////////////////////
692 // Function: EggTexture::string_texture_type
693 // Access: Published, Static
694 // Description: Returns the Texture_ype value associated with the given
695 // string representation, or TT_unspecified if the string
696 // does not match any known TextureType value.
697 ////////////////////////////////////////////////////////////////////
698 EggTexture::TextureType EggTexture::
699 string_texture_type(const string &string) {
700  if (cmp_nocase_uh(string, "1d") == 0 ||
701  cmp_nocase_uh(string, "1dtexture") == 0 ||
702  cmp_nocase_uh(string, "1d_texture") == 0) {
703  return TT_1d_texture;
704 
705  } else if (cmp_nocase_uh(string, "2d") == 0 ||
706  cmp_nocase_uh(string, "2dtexture") == 0 ||
707  cmp_nocase_uh(string, "2d_texture") == 0) {
708  return TT_2d_texture;
709 
710  } else if (cmp_nocase_uh(string, "3d") == 0 ||
711  cmp_nocase_uh(string, "3dtexture") == 0 ||
712  cmp_nocase_uh(string, "3d_texture") == 0) {
713  return TT_3d_texture;
714 
715  } else if (cmp_nocase_uh(string, "cube") == 0 ||
716  cmp_nocase_uh(string, "cubemap") == 0 ||
717  cmp_nocase_uh(string, "cube_map") == 0) {
718  return TT_cube_map;
719 
720  } else {
721  return TT_unspecified;
722  }
723 }
724 
725 ////////////////////////////////////////////////////////////////////
726 // Function: EggTexture::string_format
727 // Access: Published, Static
728 // Description: Returns the Format value associated with the given
729 // string representation, or F_unspecified if the string
730 // does not match any known Format value.
731 ////////////////////////////////////////////////////////////////////
732 EggTexture::Format EggTexture::
733 string_format(const string &string) {
734  if (cmp_nocase_uh(string, "rgba") == 0) {
735  return F_rgba;
736  } else if (cmp_nocase_uh(string, "rgbm") == 0) {
737  return F_rgbm;
738  } else if (cmp_nocase_uh(string, "rgba12") == 0) {
739  return F_rgba12;
740  } else if (cmp_nocase_uh(string, "rgba8") == 0) {
741  return F_rgba8;
742  } else if (cmp_nocase_uh(string, "rgba4") == 0) {
743  return F_rgba4;
744 
745  } else if (cmp_nocase_uh(string, "rgb") == 0) {
746  return F_rgb;
747  } else if (cmp_nocase_uh(string, "rgb12") == 0) {
748  return F_rgb12;
749  } else if (cmp_nocase_uh(string, "rgb8") == 0) {
750  return F_rgb8;
751  } else if (cmp_nocase_uh(string, "rgb5") == 0) {
752  return F_rgb5;
753  } else if (cmp_nocase_uh(string, "rgba5") == 0) {
754  return F_rgba5;
755  } else if (cmp_nocase_uh(string, "rgb332") == 0) {
756  return F_rgb332;
757  } else if (cmp_nocase_uh(string, "red") == 0) {
758  return F_red;
759  } else if (cmp_nocase_uh(string, "green") == 0) {
760  return F_green;
761  } else if (cmp_nocase_uh(string, "blue") == 0) {
762  return F_blue;
763  } else if (cmp_nocase_uh(string, "alpha") == 0) {
764  return F_alpha;
765  } else if (cmp_nocase_uh(string, "luminance") == 0) {
766  return F_luminance;
767  } else if (cmp_nocase_uh(string, "luminance_alpha") == 0) {
768  return F_luminance_alpha;
769  } else if (cmp_nocase_uh(string, "luminance_alphamask") == 0) {
770  return F_luminance_alphamask;
771  } else {
772  return F_unspecified;
773  }
774 }
775 
776 ////////////////////////////////////////////////////////////////////
777 // Function: EggTexture::string_compression_mode
778 // Access: Published, Static
779 // Description: Returns the CompressionMode value associated with the given
780 // string representation, or CM_default if the string
781 // does not match any known CompressionMode value.
782 ////////////////////////////////////////////////////////////////////
783 EggTexture::CompressionMode EggTexture::
784 string_compression_mode(const string &string) {
785  if (cmp_nocase_uh(string, "off") == 0) {
786  return CM_off;
787  } else if (cmp_nocase_uh(string, "on") == 0) {
788  return CM_on;
789  } else if (cmp_nocase_uh(string, "fxt1") == 0) {
790  return CM_fxt1;
791  } else if (cmp_nocase_uh(string, "dxt1") == 0) {
792  return CM_dxt1;
793  } else if (cmp_nocase_uh(string, "dxt2") == 0) {
794  return CM_dxt2;
795  } else if (cmp_nocase_uh(string, "dxt3") == 0) {
796  return CM_dxt3;
797  } else if (cmp_nocase_uh(string, "dxt4") == 0) {
798  return CM_dxt4;
799  } else if (cmp_nocase_uh(string, "dxt5") == 0) {
800  return CM_dxt5;
801  } else {
802  return CM_default;
803  }
804 }
805 
806 ////////////////////////////////////////////////////////////////////
807 // Function: EggTexture::string_wrap_mode
808 // Access: Published, Static
809 // Description: Returns the WrapMode value associated with the given
810 // string representation, or WM_unspecified if the string
811 // does not match any known WrapMode value.
812 ////////////////////////////////////////////////////////////////////
813 EggTexture::WrapMode EggTexture::
814 string_wrap_mode(const string &string) {
815  if (cmp_nocase_uh(string, "repeat") == 0) {
816  return WM_repeat;
817  } else if (cmp_nocase_uh(string, "clamp") == 0) {
818  return WM_clamp;
819  } else if (cmp_nocase_uh(string, "mirror") == 0) {
820  return WM_mirror;
821  } else if (cmp_nocase_uh(string, "mirror_once") == 0) {
822  return WM_mirror_once;
823  } else if (cmp_nocase_uh(string, "border_color") == 0) {
824  return WM_border_color;
825  } else {
826  return WM_unspecified;
827  }
828 }
829 
830 ////////////////////////////////////////////////////////////////////
831 // Function: EggTexture::string_filter_type
832 // Access: Published, Static
833 // Description: Returns the FilterType value associated with the given
834 // string representation, or FT_unspecified if the string
835 // does not match any known FilterType value.
836 ////////////////////////////////////////////////////////////////////
837 EggTexture::FilterType EggTexture::
838 string_filter_type(const string &string) {
839  // Old egg filter types.
840  if (cmp_nocase_uh(string, "point") == 0) {
841  return FT_nearest;
842  } else if (cmp_nocase_uh(string, "linear") == 0) {
843  return FT_linear;
844  } else if (cmp_nocase_uh(string, "bilinear") == 0) {
845  return FT_linear;
846  } else if (cmp_nocase_uh(string, "trilinear") == 0) {
847  return FT_linear_mipmap_linear;
848  } else if (cmp_nocase_uh(string, "mipmap") == 0) {
849  return FT_linear_mipmap_linear;
850  } else if (cmp_nocase_uh(string, "mipmap_point") == 0) {
851  return FT_nearest_mipmap_nearest;
852  } else if (cmp_nocase_uh(string, "mipmap_linear") == 0) {
853  return FT_nearest_mipmap_linear;
854  } else if (cmp_nocase_uh(string, "mipmap_bilinear") == 0) {
855  return FT_linear_mipmap_nearest;
856  } else if (cmp_nocase_uh(string, "mipmap_trilinear") == 0) {
857  return FT_linear_mipmap_linear;
858 
859  // Current egg filter types, that match those in Texture.
860  } else if (cmp_nocase_uh(string, "nearest") == 0) {
861  return FT_nearest;
862  } else if (cmp_nocase_uh(string, "linear") == 0) {
863  return FT_linear;
864  } else if (cmp_nocase_uh(string, "nearest_mipmap_nearest") == 0) {
865  return FT_nearest_mipmap_nearest;
866  } else if (cmp_nocase_uh(string, "linear_mipmap_nearest") == 0) {
867  return FT_linear_mipmap_nearest;
868  } else if (cmp_nocase_uh(string, "nearest_mipmap_linear") == 0) {
869  return FT_nearest_mipmap_linear;
870  } else if (cmp_nocase_uh(string, "linear_mipmap_linear") == 0) {
871  return FT_linear_mipmap_linear;
872 
873  } else {
874  return FT_unspecified;
875  }
876 }
877 
878 ////////////////////////////////////////////////////////////////////
879 // Function: EggTexture::string_env_type
880 // Access: Published, Static
881 // Description: Returns the EnvType value associated with the given
882 // string representation, or ET_unspecified if the string
883 // does not match any known EnvType value.
884 ////////////////////////////////////////////////////////////////////
885 EggTexture::EnvType EggTexture::
886 string_env_type(const string &string) {
887  if (cmp_nocase_uh(string, "modulate") == 0) {
888  return ET_modulate;
889 
890  } else if (cmp_nocase_uh(string, "decal") == 0) {
891  return ET_decal;
892 
893  } else if (cmp_nocase_uh(string, "blend") == 0) {
894  return ET_blend;
895 
896  } else if (cmp_nocase_uh(string, "replace") == 0) {
897  return ET_replace;
898 
899  } else if (cmp_nocase_uh(string, "add") == 0) {
900  return ET_add;
901 
902  } else if (cmp_nocase_uh(string, "blend_color_scale") == 0) {
903  return ET_blend_color_scale;
904 
905  } else if (cmp_nocase_uh(string, "modulate_glow") == 0) {
906  return ET_modulate_glow;
907 
908  } else if (cmp_nocase_uh(string, "modulate_gloss") == 0) {
909  return ET_modulate_gloss;
910 
911  } else if (cmp_nocase_uh(string, "normal") == 0) {
912  return ET_normal;
913 
914  } else if (cmp_nocase_uh(string, "normal_height") == 0) {
915  return ET_normal_height;
916 
917  } else if (cmp_nocase_uh(string, "glow") == 0) {
918  return ET_glow;
919 
920  } else if (cmp_nocase_uh(string, "gloss") == 0) {
921  return ET_gloss;
922 
923  } else if (cmp_nocase_uh(string, "height") == 0) {
924  return ET_height;
925 
926  } else if (cmp_nocase_uh(string, "selector") == 0) {
927  return ET_selector;
928 
929  } else if (cmp_nocase_uh(string, "normal_gloss") == 0) {
930  return ET_normal_gloss;
931 
932  } else {
933  return ET_unspecified;
934  }
935 }
936 
937 ////////////////////////////////////////////////////////////////////
938 // Function: EggTexture::string_combine_mode
939 // Access: Published, Static
940 // Description: Returns the CombineMode value associated with the given
941 // string representation, or CM_unspecified if the string
942 // does not match any known CombineMode value.
943 ////////////////////////////////////////////////////////////////////
944 EggTexture::CombineMode EggTexture::
945 string_combine_mode(const string &string) {
946  if (cmp_nocase_uh(string, "replace") == 0) {
947  return CM_replace;
948 
949  } else if (cmp_nocase_uh(string, "modulate") == 0) {
950  return CM_modulate;
951 
952  } else if (cmp_nocase_uh(string, "add") == 0) {
953  return CM_add;
954 
955  } else if (cmp_nocase_uh(string, "add_signed") == 0) {
956  return CM_add_signed;
957 
958  } else if (cmp_nocase_uh(string, "interpolate") == 0) {
959  return CM_interpolate;
960 
961  } else if (cmp_nocase_uh(string, "subtract") == 0) {
962  return CM_subtract;
963 
964  } else if (cmp_nocase_uh(string, "dot3_rgb") == 0) {
965  return CM_dot3_rgb;
966 
967  } else if (cmp_nocase_uh(string, "dot3_rgba") == 0) {
968  return CM_dot3_rgba;
969 
970  } else {
971  return CM_unspecified;
972  }
973 }
974 
975 ////////////////////////////////////////////////////////////////////
976 // Function: EggTexture::string_combine_source
977 // Access: Published, Static
978 // Description: Returns the CombineSource value associated with the given
979 // string representation, or CS_unspecified if the string
980 // does not match any known CombineSource value.
981 ////////////////////////////////////////////////////////////////////
982 EggTexture::CombineSource EggTexture::
983 string_combine_source(const string &string) {
984  if (cmp_nocase_uh(string, "texture") == 0) {
985  return CS_texture;
986 
987  } else if (cmp_nocase_uh(string, "constant") == 0) {
988  return CS_constant;
989 
990  } else if (cmp_nocase_uh(string, "primary_color") == 0) {
991  return CS_primary_color;
992 
993  } else if (cmp_nocase_uh(string, "previous") == 0) {
994  return CS_previous;
995 
996  } else if (cmp_nocase_uh(string, "constant_color_scale") == 0) {
997  return CS_constant_color_scale;
998 
999  } else if (cmp_nocase_uh(string, "last_saved_result") == 0) {
1000  return CS_last_saved_result;
1001 
1002  } else {
1003  return CS_unspecified;
1004  }
1005 }
1006 
1007 ////////////////////////////////////////////////////////////////////
1008 // Function: EggTexture::string_combine_operand
1009 // Access: Published, Static
1010 // Description: Returns the CombineOperand value associated with the given
1011 // string representation, or CO_unspecified if the string
1012 // does not match any known CombineOperand value.
1013 ////////////////////////////////////////////////////////////////////
1014 EggTexture::CombineOperand EggTexture::
1015 string_combine_operand(const string &string) {
1016  if (cmp_nocase_uh(string, "src_color") == 0) {
1017  return CO_src_color;
1018 
1019  } else if (cmp_nocase_uh(string, "one_minus_src_color") == 0) {
1020  return CO_one_minus_src_color;
1021 
1022  } else if (cmp_nocase_uh(string, "src_alpha") == 0) {
1023  return CO_src_alpha;
1024 
1025  } else if (cmp_nocase_uh(string, "one_minus_src_alpha") == 0) {
1026  return CO_one_minus_src_alpha;
1027 
1028  } else {
1029  return CO_unspecified;
1030  }
1031 }
1032 
1033 ////////////////////////////////////////////////////////////////////
1034 // Function: EggTexture::string_tex_gen
1035 // Access: Published, Static
1036 // Description: Returns the TexGen value associated with the given
1037 // string representation, or ET_unspecified if the string
1038 // does not match any known TexGen value.
1039 ////////////////////////////////////////////////////////////////////
1040 EggTexture::TexGen EggTexture::
1041 string_tex_gen(const string &string) {
1042  if (cmp_nocase_uh(string, "unspecified") == 0) {
1043  return TG_unspecified;
1044 
1045  } else if (cmp_nocase_uh(string, "sphere_map") == 0 ||
1046  cmp_nocase_uh(string, "eye_sphere_map") == 0) {
1047  return TG_eye_sphere_map;
1048 
1049  } else if (cmp_nocase_uh(string, "world_cube_map") == 0) {
1050  return TG_world_cube_map;
1051 
1052  } else if (cmp_nocase_uh(string, "cube_map") == 0 ||
1053  cmp_nocase_uh(string, "eye_cube_map") == 0) {
1054  return TG_eye_cube_map;
1055 
1056  } else if (cmp_nocase_uh(string, "world_normal") == 0) {
1057  return TG_world_normal;
1058 
1059  } else if (cmp_nocase_uh(string, "eye_normal") == 0) {
1060  return TG_eye_normal;
1061 
1062  } else if (cmp_nocase_uh(string, "world_position") == 0) {
1063  return TG_world_position;
1064 
1065  } else if (cmp_nocase_uh(string, "eye_position") == 0) {
1066  return TG_eye_position;
1067 
1068  } else if (cmp_nocase_uh(string, "point_sprite") == 0) {
1069  return TG_point_sprite;
1070 
1071  } else {
1072  return TG_unspecified;
1073  }
1074 }
1075 
1076 ////////////////////////////////////////////////////////////////////
1077 // Function: EggTexture::string_quality_level
1078 // Access: Published, Static
1079 // Description: Returns the TexGen value associated with the given
1080 // string representation, or ET_unspecified if the string
1081 // does not match any known TexGen value.
1082 ////////////////////////////////////////////////////////////////////
1083 EggTexture::QualityLevel EggTexture::
1084 string_quality_level(const string &string) {
1085  if (cmp_nocase_uh(string, "unspecified") == 0) {
1086  return QL_unspecified;
1087 
1088  } else if (cmp_nocase_uh(string, "default") == 0) {
1089  return QL_default;
1090 
1091  } else if (cmp_nocase_uh(string, "fastest") == 0) {
1092  return QL_fastest;
1093 
1094  } else if (cmp_nocase_uh(string, "normal") == 0) {
1095  return QL_normal;
1096 
1097  } else if (cmp_nocase_uh(string, "best") == 0) {
1098  return QL_best;
1099 
1100  } else {
1101  return QL_unspecified;
1102  }
1103 }
1104 
1105 ////////////////////////////////////////////////////////////////////
1106 // Function: EggTexture::as_transform
1107 // Access: Public, Virtual
1108 // Description: Returns this object cross-cast to an EggTransform
1109 // pointer, if it inherits from EggTransform, or NULL if
1110 // it does not.
1111 ////////////////////////////////////////////////////////////////////
1114  return this;
1115 }
1116 
1117 ////////////////////////////////////////////////////////////////////
1118 // Function: EggTexture::egg_start_parse_body
1119 // Access: Protected, Virtual
1120 // Description: This function is called within parse_egg(). It
1121 // should call the appropriate function on the lexer to
1122 // initialize the parser into the state associated with
1123 // this object. If the object cannot be parsed into
1124 // directly, it should return false.
1125 ////////////////////////////////////////////////////////////////////
1126 bool EggTexture::
1127 egg_start_parse_body() {
1128  egg_start_texture_body();
1129  return true;
1130 }
1131 
1132 ////////////////////////////////////////////////////////////////////
1133 // Function: EggTexture::r_min_multitexture_sort
1134 // Access: Private
1135 // Description: Ensures that our multitexture_sort is at least the
1136 // indicated value.
1137 ////////////////////////////////////////////////////////////////////
1138 bool EggTexture::
1139 r_min_multitexture_sort(int sort, EggTexture::MultiTextures &cycle_detector) {
1140  if (_multitexture_sort >= sort) {
1141  // No problem.
1142  return true;
1143  }
1144 
1145  if (!cycle_detector.insert(this).second) {
1146  // Oops, we just hit a cycle!
1147  return false;
1148  }
1149 
1150  _multitexture_sort = sort;
1151 
1152  // Now we also have to increment all of the textures that we are
1153  // under.
1154  bool no_cycles = true;
1155 
1156  MultiTextures::iterator mti;
1157  for (mti = _under_textures.begin();
1158  mti != _under_textures.end();
1159  ++mti) {
1160  EggTexture *other = (*mti);
1161  if (!other->r_min_multitexture_sort(sort + 1, cycle_detector)) {
1162  // Oops, found a cycle!
1163  no_cycles = false;
1164  }
1165  }
1166 
1167  return no_cycles;
1168 }
1169 
1170 
1171 ////////////////////////////////////////////////////////////////////
1172 // Function: TextureType output operator
1173 // Description:
1174 ////////////////////////////////////////////////////////////////////
1175 ostream &operator << (ostream &out, EggTexture::TextureType texture_type) {
1176  switch (texture_type) {
1177  case EggTexture::TT_unspecified:
1178  return out << "unspecified";
1179 
1180  case EggTexture::TT_1d_texture:
1181  return out << "1d";
1182 
1183  case EggTexture::TT_2d_texture:
1184  return out << "2d";
1185 
1186  case EggTexture::TT_3d_texture:
1187  return out << "3d";
1188 
1189  case EggTexture::TT_cube_map:
1190  return out << "cube-map";
1191  }
1192 
1193  nassertr(false, out);
1194  return out << "(**invalid**)";
1195 }
1196 
1197 
1198 ////////////////////////////////////////////////////////////////////
1199 // Function: Format output operator
1200 // Description:
1201 ////////////////////////////////////////////////////////////////////
1202 ostream &operator << (ostream &out, EggTexture::Format format) {
1203  switch (format) {
1204  case EggTexture::F_unspecified:
1205  return out << "unspecified";
1206 
1207  case EggTexture::F_rgba:
1208  return out << "rgba";
1209  case EggTexture::F_rgbm:
1210  return out << "rgbm";
1211  case EggTexture::F_rgba12:
1212  return out << "rgba12";
1213  case EggTexture::F_rgba8:
1214  return out << "rgba8";
1215  case EggTexture::F_rgba4:
1216  return out << "rgba4";
1217 
1218  case EggTexture::F_rgb:
1219  return out << "rgb";
1220  case EggTexture::F_rgb12:
1221  return out << "rgb12";
1222  case EggTexture::F_rgb8:
1223  return out << "rgb8";
1224  case EggTexture::F_rgb5:
1225  return out << "rgb5";
1226  case EggTexture::F_rgba5:
1227  return out << "rgba5";
1228  case EggTexture::F_rgb332:
1229  return out << "rgb332";
1230 
1231  case EggTexture::F_red:
1232  return out << "red";
1233  case EggTexture::F_green:
1234  return out << "green";
1235  case EggTexture::F_blue:
1236  return out << "blue";
1237  case EggTexture::F_alpha:
1238  return out << "alpha";
1239  case EggTexture::F_luminance:
1240  return out << "luminance";
1241  case EggTexture::F_luminance_alpha:
1242  return out << "luminance_alpha";
1243  case EggTexture::F_luminance_alphamask:
1244  return out << "luminance_alphamask";
1245  }
1246 
1247  nassertr(false, out);
1248  return out << "(**invalid**)";
1249 }
1250 
1251 ////////////////////////////////////////////////////////////////////
1252 // Function: CompressionMode output operator
1253 // Description:
1254 ////////////////////////////////////////////////////////////////////
1255 ostream &operator << (ostream &out, EggTexture::CompressionMode mode) {
1256  switch (mode) {
1257  case EggTexture::CM_default:
1258  return out << "default";
1259  case EggTexture::CM_off:
1260  return out << "off";
1261  case EggTexture::CM_on:
1262  return out << "on";
1263  case EggTexture::CM_fxt1:
1264  return out << "fxt1";
1265  case EggTexture::CM_dxt1:
1266  return out << "dxt1";
1267  case EggTexture::CM_dxt2:
1268  return out << "dxt2";
1269  case EggTexture::CM_dxt3:
1270  return out << "dxt3";
1271  case EggTexture::CM_dxt4:
1272  return out << "dxt4";
1273  case EggTexture::CM_dxt5:
1274  return out << "dxt5";
1275  }
1276 
1277  nassertr(false, out);
1278  return out << "(**invalid**)";
1279 }
1280 
1281 ////////////////////////////////////////////////////////////////////
1282 // Function: WrapMode output operator
1283 // Description:
1284 ////////////////////////////////////////////////////////////////////
1285 ostream &operator << (ostream &out, EggTexture::WrapMode mode) {
1286  switch (mode) {
1287  case EggTexture::WM_unspecified:
1288  return out << "unspecified";
1289  case EggTexture::WM_repeat:
1290  return out << "repeat";
1291  case EggTexture::WM_clamp:
1292  return out << "clamp";
1293  case EggTexture::WM_mirror:
1294  return out << "mirror";
1295  case EggTexture::WM_mirror_once:
1296  return out << "mirror_once";
1297  case EggTexture::WM_border_color:
1298  return out << "border_color";
1299  }
1300 
1301  nassertr(false, out);
1302  return out << "(**invalid**)";
1303 }
1304 
1305 ////////////////////////////////////////////////////////////////////
1306 // Function: FilterType output operator
1307 // Description:
1308 ////////////////////////////////////////////////////////////////////
1309 ostream &operator << (ostream &out, EggTexture::FilterType type) {
1310  switch (type) {
1311  case EggTexture::FT_unspecified:
1312  return out << "unspecified";
1313 
1314  case EggTexture::FT_nearest:
1315  return out << "nearest";
1316  case EggTexture::FT_linear:
1317  return out << "linear";
1318 
1319  case EggTexture::FT_nearest_mipmap_nearest:
1320  return out << "nearest_mipmap_nearest";
1321  case EggTexture::FT_linear_mipmap_nearest:
1322  return out << "linear_mipmap_nearest";
1323  case EggTexture::FT_nearest_mipmap_linear:
1324  return out << "nearest_mipmap_linear";
1325  case EggTexture::FT_linear_mipmap_linear:
1326  return out << "linear_mipmap_linear";
1327  }
1328 
1329  nassertr(false, out);
1330  return out << "(**invalid**)";
1331 }
1332 
1333 ////////////////////////////////////////////////////////////////////
1334 // Function: EnvType output operator
1335 // Description:
1336 ////////////////////////////////////////////////////////////////////
1337 ostream &operator << (ostream &out, EggTexture::EnvType type) {
1338  switch (type) {
1339  case EggTexture::ET_unspecified:
1340  return out << "unspecified";
1341 
1342  case EggTexture::ET_modulate:
1343  return out << "modulate";
1344 
1345  case EggTexture::ET_decal:
1346  return out << "decal";
1347 
1348  case EggTexture::ET_blend:
1349  return out << "blend";
1350 
1351  case EggTexture::ET_replace:
1352  return out << "replace";
1353 
1354  case EggTexture::ET_add:
1355  return out << "add";
1356 
1357  case EggTexture::ET_blend_color_scale:
1358  return out << "blend_color_scale";
1359 
1360  case EggTexture::ET_modulate_glow:
1361  return out << "modulate_glow";
1362 
1363  case EggTexture::ET_modulate_gloss:
1364  return out << "modulate_gloss";
1365 
1366  case EggTexture::ET_normal:
1367  return out << "normal";
1368 
1369  case EggTexture::ET_normal_height:
1370  return out << "normal_height";
1371 
1372  case EggTexture::ET_glow:
1373  return out << "glow";
1374 
1375  case EggTexture::ET_gloss:
1376  return out << "gloss";
1377 
1378  case EggTexture::ET_height:
1379  return out << "height";
1380 
1381  case EggTexture::ET_selector:
1382  return out << "selector";
1383 
1384  case EggTexture::ET_normal_gloss:
1385  return out << "normal_gloss";
1386  }
1387 
1388  nassertr(false, out);
1389  return out << "(**invalid**)";
1390 }
1391 
1392 ostream &
1393 operator << (ostream &out, EggTexture::CombineMode cm) {
1394  switch (cm) {
1395  case EggTexture::CM_unspecified:
1396  return out << "unspecified";
1397 
1398  case EggTexture::CM_replace:
1399  return out << "replace";
1400 
1401  case EggTexture::CM_modulate:
1402  return out << "modulate";
1403 
1404  case EggTexture::CM_add:
1405  return out << "add";
1406 
1407  case EggTexture::CM_add_signed:
1408  return out << "add_signed";
1409 
1410  case EggTexture::CM_interpolate:
1411  return out << "interpolate";
1412 
1413  case EggTexture::CM_subtract:
1414  return out << "subtract";
1415 
1416  case EggTexture::CM_dot3_rgb:
1417  return out << "dot3_rgb";
1418 
1419  case EggTexture::CM_dot3_rgba:
1420  return out << "dot3_rgba";
1421  }
1422 
1423  return out << "**invalid CombineMode(" << (int)cm << ")**";
1424 }
1425 
1426 ostream &
1427 operator << (ostream &out, EggTexture::CombineChannel cm) {
1428  switch (cm) {
1429  case EggTexture::CC_rgb:
1430  return out << "rgb";
1431 
1432  case EggTexture::CC_alpha:
1433  return out << "alpha";
1434 
1435  case EggTexture::CC_num_channels:
1436  // This case is here just to prevent a compiler warning. Fall out
1437  // of the switch and return the error message.
1438  break;
1439  }
1440 
1441  return out << "**invalid CombineChannel(" << (int)cm << ")**";
1442 }
1443 
1444 ostream &
1445 operator << (ostream &out, EggTexture::CombineSource cs) {
1446  switch (cs) {
1447  case EggTexture::CS_unspecified:
1448  return out << "unspecified";
1449 
1450  case EggTexture::CS_texture:
1451  return out << "texture";
1452 
1453  case EggTexture::CS_constant:
1454  return out << "constant";
1455 
1456  case EggTexture::CS_primary_color:
1457  return out << "primary_color";
1458 
1459  case EggTexture::CS_previous:
1460  return out << "previous";
1461 
1462  case EggTexture::CS_constant_color_scale:
1463  return out << "constant_color_scale";
1464 
1465  case EggTexture::CS_last_saved_result:
1466  return out << "last_saved_result";
1467  }
1468 
1469  return out << "**invalid CombineSource(" << (int)cs << ")**";
1470 }
1471 
1472 ostream &
1473 operator << (ostream &out, EggTexture::CombineOperand co) {
1474  switch (co) {
1475  case EggTexture::CO_unspecified:
1476  return out << "unspecified";
1477 
1478  case EggTexture::CO_src_color:
1479  return out << "src_color";
1480 
1481  case EggTexture::CO_one_minus_src_color:
1482  return out << "one_minus_src_color";
1483 
1484  case EggTexture::CO_src_alpha:
1485  return out << "src_alpha";
1486 
1487  case EggTexture::CO_one_minus_src_alpha:
1488  return out << "one_minus_src_alpha";
1489  }
1490 
1491  return out << "**invalid CombineOperand(" << (int)co << ")**";
1492 }
1493 
1494 ostream &
1495 operator << (ostream &out, EggTexture::TexGen tex_gen) {
1496  switch (tex_gen) {
1497  case EggTexture::TG_unspecified:
1498  return out << "unspecified";
1499 
1500  case EggTexture::TG_eye_sphere_map:
1501  return out << "eye_sphere_map";
1502 
1503  case EggTexture::TG_world_cube_map:
1504  return out << "world_cube_map";
1505 
1506  case EggTexture::TG_eye_cube_map:
1507  return out << "eye_cube_map";
1508 
1509  case EggTexture::TG_world_normal:
1510  return out << "world_normal";
1511 
1512  case EggTexture::TG_eye_normal:
1513  return out << "eye_normal";
1514 
1515  case EggTexture::TG_world_position:
1516  return out << "world_position";
1517 
1518  case EggTexture::TG_eye_position:
1519  return out << "eye_position";
1520 
1521  case EggTexture::TG_point_sprite:
1522  return out << "point_sprite";
1523  }
1524 
1525  return out << "**invalid TexGen(" << (int)tex_gen << ")**";
1526 }
1527 
1528 ostream &
1529 operator << (ostream &out, EggTexture::QualityLevel quality_level) {
1530  switch (quality_level) {
1531  case EggTexture::QL_unspecified:
1532  return out << "unspecified";
1533  case EggTexture::QL_default:
1534  return out << "default";
1535  case EggTexture::QL_fastest:
1536  return out << "fastest";
1537  case EggTexture::QL_normal:
1538  return out << "normal";
1539  case EggTexture::QL_best:
1540  return out << "best";
1541  }
1542 
1543  return out << "**invalid QualityLevel(" << (int)quality_level << ")**";
1544 }
bool affects_polygon_alpha() const
Returns true if this texture&#39;s environment type or combine mode allows the texture to have an effect ...
Definition: eggTexture.cxx:571
int get_multitexture_sort() const
Returns an integer that represents the depth to which this texture is layered on all other textures i...
Definition: eggTexture.I:1071
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
Definition: eggTransform.I:251
int get_anisotropic_degree() const
Returns the anisotropic filtering degree that has been specified for this texture, or 0 if nothing has been specified.
Definition: eggTexture.I:289
static WrapMode string_wrap_mode(const string &string)
Returns the WrapMode value associated with the given string representation, or WM_unspecified if the ...
Definition: eggTexture.cxx:814
void write_header(ostream &out, int indent_level, const char *egg_keyword) const
Writes the first line of the egg object, e.g.
bool multitexture_over(EggTexture *other)
Indicates that this texture should be layered on top of the other texture.
Definition: eggTexture.cxx:672
bool is_equivalent_to(const EggTexture &other, int eq) const
Returns true if the two textures are equivalent in all relevant properties (according to eq)...
Definition: eggTexture.cxx:349
This is an egg node that contains a filename.
bool get_multiview() const
Returns the current setting of the multiview flag.
Definition: eggTexture.I:974
void clear_multitexture()
Resets the multitexture flags set by multitexture_over().
Definition: eggTexture.cxx:630
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:33
bool has_stage_name() const
Returns true if a stage name has been explicitly specified for this texture, false otherwise...
Definition: eggTexture.I:498
bool has_priority() const
Returns true if a priority value for multitexture importance has been specified for the texture...
Definition: eggTexture.I:548
static EnvType string_env_type(const string &string)
Returns the EnvType value associated with the given string representation, or ET_unspecified if the s...
Definition: eggTexture.cxx:886
bool has_color() const
Returns true if a blend color has been specified for the texture.
Definition: eggTexture.I:593
static QualityLevel string_quality_level(const string &string)
Returns the TexGen value associated with the given string representation, or ET_unspecified if the st...
bool has_alpha_file_channel() const
Returns true if a particular channel has been specified for the alpha-file image, false otherwise...
Definition: eggTexture.I:931
virtual EggTransform * as_transform()
Returns this object cross-cast to an EggTransform pointer, if it inherits from EggTransform, or NULL if it does not.
int get_rgb_scale() const
Returns the rgb_scale value that has been specified for the texture, or 1 if no rgb_scale value has b...
Definition: eggTexture.I:756
string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:424
bool get_read_mipmaps() const
Returns the current setting of the read_mipmaps flag.
Definition: eggTexture.I:1056
int get_num_views() const
Returns the specified number of views specified for the 3-D multiview texture.
Definition: eggTexture.I:1023
static CompressionMode string_compression_mode(const string &string)
Returns the CompressionMode value associated with the given string representation, or CM_default if the string does not match any known CompressionMode value.
Definition: eggTexture.cxx:784
bool has_anisotropic_degree() const
Returns true if a value for the anisotropic filtering degree has been specified for this texture...
Definition: eggTexture.I:277
static Format string_format(const string &string)
Returns the Format value associated with the given string representation, or F_unspecified if the str...
Definition: eggTexture.cxx:733
static CombineOperand string_combine_operand(const string &string)
Returns the CombineOperand value associated with the given string representation, or CO_unspecified i...
WrapMode get_wrap_v() const
Returns the amount specified for V wrap.
Definition: eggTexture.I:153
void write(ostream &out, int indent_level) const
Writes the attributes to the indicated output stream in Egg format.
WrapMode get_wrap_u() const
Returns the amount specified for U wrap.
Definition: eggTexture.I:119
const string & get_uv_name() const
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
Definition: eggTexture.I:705
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Definition: lmatrix.cxx:2058
static FilterType string_filter_type(const string &string)
Returns the FilterType value associated with the given string representation, or FT_unspecified if th...
Definition: eggTexture.cxx:838
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
bool has_alpha_filename() const
Returns true if a separate file for the alpha component has been applied, false otherwise.
Definition: eggTexture.I:846
int get_alpha_file_channel() const
Returns the particular channel that has been specified for the alpha-file image, or 0 if no channel h...
Definition: eggTexture.I:944
bool sorts_less_than(const EggTexture &other, int eq) const
An ordering operator to compare two textures for sorting order.
Definition: eggTexture.cxx:429
static CombineMode string_combine_mode(const string &string)
Returns the CombineMode value associated with the given string representation, or CM_unspecified if t...
Definition: eggTexture.cxx:945
static TextureType string_texture_type(const string &string)
Returns the Texture_ype value associated with the given string representation, or TT_unspecified if t...
Definition: eggTexture.cxx:699
static TexGen string_tex_gen(const string &string)
Returns the TexGen value associated with the given string representation, or ET_unspecified if the st...
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
bool has_transform() const
Returns true if the transform is nonempty, false if it is empty (no transform components have been ad...
Definition: eggTransform.I:163
int get_alpha_scale() const
Returns the alpha_scale value that has been specified for the texture, or 1 if no alpha_scale value h...
Definition: eggTexture.I:806
void write(ostream &out, int indent_level, const string &label) const
Writes the transform to the indicated stream in Egg format.
int compare_to(const LMatrix4d &other) const
This flavor of compare_to uses a default threshold value based on the numeric type.
Definition: lmatrix.h:5832
bool has_alpha_channel(int num_components) const
Given the number of color components (channels) in the image file as actually read from the disk...
Definition: eggTexture.cxx:528
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:460
bool has_alpha_scale() const
Returns true if an alpha_scale has been specified for the texture, false otherwise.
Definition: eggTexture.I:794
virtual void write(ostream &out, int indent_level) const
Writes the texture definition to the indicated output stream in Egg format.
Definition: eggTexture.cxx:134
const Filename & get_alpha_filename() const
Returns the separate file assigned for the alpha channel.
Definition: eggTexture.I:858
bool has_border_color() const
Returns true if a border color has been specified for the texture.
Definition: eggTexture.I:637
WrapMode get_wrap_w() const
Returns the amount specified for W wrap.
Definition: eggTexture.I:187
bool has_uv_name() const
Returns true if a texcoord name has been explicitly specified for this texture, false otherwise...
Definition: eggTexture.I:693
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
static CombineSource string_combine_source(const string &string)
Returns the CombineSource value associated with the given string representation, or CS_unspecified if...
Definition: eggTexture.cxx:983
bool has_rgb_scale() const
Returns true if an rgb_scale has been specified for the texture, false otherwise. ...
Definition: eggTexture.I:744
bool has_num_views() const
Returns true if the number of views has been specified for the 3-D multiview texture, false otherwise.
Definition: eggTexture.I:1012
string get_extension() const
Returns the file extension.
Definition: filename.I:477
int get_priority() const
Returns the multitexture importance value that has been specified for the texture, or 0 if no priority value has been specified.
Definition: eggTexture.I:560
bool get_saved_result() const
Returns the current setting of the saved_result flag.
Definition: eggTexture.I:416
This represents the &lt;Transform&gt; entry of a group or texture node: a list of component transform opera...
Definition: eggTransform.h:33
const string & get_stage_name() const
Returns the stage name that has been specified for this texture, or the tref name if no texture stage...
Definition: eggTexture.I:510
bool transform_is_identity() const
Returns true if the described transform is identity, false otherwise.
Definition: eggTransform.I:262