16 #include "pal_string_utils.h" 18 #include "palettizer.h" 19 #include "textureImage.h" 20 #include "sourceTextureImage.h" 21 #include "paletteGroup.h" 24 #include "pnmFileType.h" 39 _format = EggTexture::F_unspecified;
40 _force_format =
false;
41 _generic_format =
false;
43 _alpha_mode = EggRenderMode::AM_unspecified;
44 _wrap_u = EggTexture::WM_unspecified;
45 _wrap_v = EggTexture::WM_unspecified;
46 _quality_level = EggTexture::QL_unspecified;
49 _got_coverage_threshold =
false;
50 _coverage_threshold = 0.0;
64 size_t colon = line.find(
':');
65 if (colon == string::npos) {
66 nout <<
"Colon required.\n";
73 extract_words(line.substr(0, colon), words);
75 vector_string::iterator wi;
76 for (wi = words.begin(); wi != words.end(); ++wi) {
84 if (word.length() > 4 && word.substr(word.length() - 4) ==
".egg") {
87 _egg_patterns.push_back(pattern);
92 size_t dot = word.rfind(
'.');
93 if (dot != string::npos) {
94 word = word.substr(0, dot);
98 _texture_patterns.push_back(pattern);
102 if (_egg_patterns.empty() && _texture_patterns.empty()) {
103 nout <<
"No texture or egg filenames given.\n";
110 extract_words(line.substr(colon + 1), words);
113 while (wi != words.end()) {
114 const string &word = *wi;
115 nassertr(!word.empty(),
false);
117 if (isdigit(word[0])) {
119 if (_size_type != ST_none) {
120 nout <<
"Invalid repeated size request: " << word <<
"\n";
123 if (word[word.length() - 1] ==
'%') {
125 _size_type = ST_scale;
128 _scale = string_to_double(word, tail);
129 if (!(tail ==
"%")) {
138 while (wi != words.end() && isdigit((*wi)[0])) {
139 const string &word = *wi;
141 if (!string_to_int(word, num)) {
142 nout <<
"Invalid size: " << word <<
"\n";
145 numbers.push_back(num);
148 if (numbers.size() < 2) {
149 nout <<
"At least two size numbers must be given, or a percent sign used to indicate scaling.\n";
152 }
else if (numbers.size() == 2) {
153 _size_type = ST_explicit_2;
154 _x_size = numbers[0];
155 _y_size = numbers[1];
157 }
else if (numbers.size() == 3) {
158 _size_type = ST_explicit_3;
159 _x_size = numbers[0];
160 _y_size = numbers[1];
161 _num_channels = numbers[2];
164 nout <<
"Too many size numbers given.\n";
172 if (word ==
"omit") {
173 _keywords.push_back(KW_omit);
175 }
else if (word ==
"nearest") {
176 _keywords.push_back(KW_nearest);
178 }
else if (word ==
"linear") {
179 _keywords.push_back(KW_linear);
181 }
else if (word ==
"mipmap") {
182 _keywords.push_back(KW_mipmap);
184 }
else if (word ==
"cont") {
185 _keywords.push_back(KW_cont);
187 }
else if (word ==
"margin") {
189 if (wi == words.end()) {
190 nout <<
"Argument required for 'margin'.\n";
194 const string &arg = (*wi);
195 if (!string_to_int(arg, _margin)) {
196 nout <<
"Not an integer: " << arg <<
"\n";
200 nout <<
"Invalid margin: " << _margin <<
"\n";
205 }
else if (word ==
"aniso") {
207 if (wi == words.end()) {
208 nout <<
"Integer argument required for 'aniso'.\n";
212 const string &arg = (*wi);
213 if (!string_to_int(arg, _aniso_degree)) {
214 nout <<
"Not an integer: " << arg <<
"\n";
217 if ((_aniso_degree < 2) || (_aniso_degree > 16)) {
219 nout <<
"Invalid anistropic degree (range is 2-16): " << _aniso_degree <<
"\n";
223 _keywords.push_back(KW_anisotropic);
225 }
else if (word ==
"coverage") {
227 if (wi == words.end()) {
228 nout <<
"Argument required for 'coverage'.\n";
232 const string &arg = (*wi);
233 if (!string_to_double(arg, _coverage_threshold)) {
234 nout <<
"Not a number: " << arg <<
"\n";
237 if (_coverage_threshold <= 0.0) {
238 nout <<
"Invalid coverage threshold: " << _coverage_threshold <<
"\n";
241 _got_coverage_threshold =
true;
243 }
else if (word.substr(0, 6) ==
"force-") {
246 string format_name = word.substr(6);
248 if (format != EggTexture::F_unspecified) {
250 _force_format =
true;
252 nout <<
"Unknown image format: " << format_name <<
"\n";
256 }
else if (word ==
"generic") {
260 _generic_format =
true;
262 }
else if (word ==
"keep-format") {
270 _palette_groups.
insert(group);
277 if (format != EggTexture::F_unspecified) {
278 if (!_force_format) {
284 if (am != EggRenderMode::AM_unspecified) {
290 if (ql != EggTexture::QL_unspecified) {
293 }
else if (word.length() > 2 && word[word.length() - 2] ==
'_' &&
294 strchr(
"uv", word[word.length() - 1]) != NULL) {
296 string prefix = word.substr(0, word.length() - 2);
298 if (wm == EggTexture::WM_unspecified) {
301 switch (word[word.length() - 1]) {
313 if (!parse_image_type_request(word, _color_type, _alpha_type)) {
341 string name = egg_file->get_name();
343 bool matched_any =
false;
344 Patterns::const_iterator pi;
345 for (pi = _egg_patterns.begin();
346 pi != _egg_patterns.end() && !matched_any;
348 matched_any = (*pi).matches(name);
356 bool got_cont =
false;
357 Keywords::const_iterator ki;
358 for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) {
404 string name = texture->get_name();
406 bool matched_any =
false;
407 Patterns::const_iterator pi;
408 for (pi = _texture_patterns.begin();
409 pi != _texture_patterns.end() && !matched_any;
411 matched_any = (*pi).matches(name);
422 if (!request._got_size) {
423 switch (_size_type) {
429 request._got_size =
true;
430 request._x_size = max(1, (
int)(source->
get_x_size() * _scale / 100.0));
431 request._y_size = max(1, (
int)(source->
get_y_size() * _scale / 100.0));
436 request._got_num_channels =
true;
437 request._num_channels = _num_channels;
441 request._got_size =
true;
442 request._x_size = _x_size;
443 request._y_size = _y_size;
449 request._margin = _margin;
452 if (_got_coverage_threshold) {
453 request._coverage_threshold = _coverage_threshold;
457 request._properties._color_type = _color_type;
458 request._properties._alpha_type = _alpha_type;
461 if (_quality_level != EggTexture::QL_unspecified) {
462 request._properties._quality_level = _quality_level;
465 if (_format != EggTexture::F_unspecified) {
466 request._format = _format;
467 request._force_format = _force_format;
468 request._generic_format =
false;
471 if (_generic_format) {
472 request._generic_format =
true;
476 request._keep_format =
true;
479 if (_alpha_mode != EggRenderMode::AM_unspecified) {
480 request._alpha_mode = _alpha_mode;
483 if (_wrap_u != EggTexture::WM_unspecified) {
484 request._wrap_u = _wrap_u;
486 if (_wrap_v != EggTexture::WM_unspecified) {
487 request._wrap_v = _wrap_v;
490 bool got_cont =
false;
491 Keywords::const_iterator ki;
492 for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) {
495 request._omit =
true;
499 request._minfilter = EggTexture::FT_nearest;
500 request._magfilter = EggTexture::FT_nearest;
504 request._minfilter = EggTexture::FT_linear;
505 request._magfilter = EggTexture::FT_linear;
509 request._minfilter = EggTexture::FT_linear_mipmap_linear;
510 request._magfilter = EggTexture::FT_linear_mipmap_linear;
514 request._anisotropic_degree = _aniso_degree;
523 texture->_explicitly_assigned_groups.
make_union 524 (texture->_explicitly_assigned_groups, _palette_groups);
525 texture->_explicitly_assigned_groups.
remove_null();
535 texture->_is_surprise =
false;
546 output(ostream &out)
const {
547 Patterns::const_iterator pi;
548 for (pi = _texture_patterns.begin(); pi != _texture_patterns.end(); ++pi) {
551 for (pi = _egg_patterns.begin(); pi != _egg_patterns.end(); ++pi) {
556 switch (_size_type) {
561 out <<
" " << _scale <<
"%";
565 out <<
" " << _x_size <<
" " << _y_size;
569 out <<
" " << _x_size <<
" " << _y_size <<
" " << _num_channels;
574 out <<
" margin " << _margin;
577 if (_got_coverage_threshold) {
578 out <<
" coverage " << _coverage_threshold;
581 Keywords::const_iterator ki;
582 for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) {
605 out <<
" aniso " << _aniso_degree;
610 PaletteGroups::const_iterator gi;
611 for (gi = _palette_groups.
begin(); gi != _palette_groups.
end(); ++gi) {
612 out <<
" " << (*gi)->get_name();
615 if (_format != EggTexture::F_unspecified) {
616 out <<
" " << _format;
iterator end() const
Returns an iterator suitable for traversing the set.
static WrapMode string_wrap_mode(const string &string)
Returns the WrapMode value associated with the given string representation, or WM_unspecified if the ...
static AlphaMode string_alpha_mode(const string &string)
Returns the AlphaMode value associated with the given string representation, or AM_unspecified if the...
void remove_null()
Removes the special "null" group from the set.
PaletteGroup * test_palette_group(const string &name) const
Returns the PaletteGroup with the given name.
int get_y_size() const
Returns the size of the image file in pixels in the Y direction.
void clear_surprise()
Removes the 'surprise' flag; this file has been successfully matched against a line in the ...
iterator begin() const
Returns an iterator suitable for traversing the set.
This is the highest level of grouping for TextureImages.
This is the base class of a family of classes that represent particular image file types that PNMImag...
static QualityLevel string_quality_level(const string &string)
Returns the TexGen value associated with the given string representation, or ET_unspecified if the st...
void set_case_sensitive(bool case_sensitive)
Sets whether the match is case sensitive (true) or case insensitive (false).
SourceTextureImage * get_preferred_source()
Determines the preferred source image for examining size and reading pixels, etc. ...
static Format string_format(const string &string)
Returns the Format value associated with the given string representation, or F_unspecified if the str...
void match_txa_groups(const PaletteGroups &groups)
Adds the indicated set of groups, read from the .txa file, to the set of groups to which the egg file...
int get_x_size() const
Returns the size of the image file in pixels in the X direction.
bool match_texture(TextureImage *texture) const
Compares the patterns on the line to the indicated TextureImage.
bool get_size()
Determines the size of the SourceTextureImage, if it is not already known.
This is a texture image reference as it appears in an egg file: the source image of the texture...
bool match_egg(EggFile *egg_file) const
Compares the patterns on the line to the indicated EggFile.
void make_union(const PaletteGroups &a, const PaletteGroups &b)
Computes the union of PaletteGroups a and b, and stores the result in this object.
void insert(PaletteGroup *group)
Inserts a new group to the set, if it is not already there.
This represents a single source texture that is referenced by one or more egg files.
bool parse(const string &line)
Accepts a string that defines a line of the .txa file and parses it into its constinuent parts...
These are the things that a user might explicitly request to adjust on a texture via a line in the ...
This represents a single egg file known to the palettizer.
virtual string get_suggested_extension() const
Returns a suitable filename extension (without a leading dot) to suggest for files of this type...
This class can be used to test for string matches against standard Unix-shell filename globbing conve...