00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggPalettize.h"
00016 #include "palettizer.h"
00017 #include "eggFile.h"
00018 #include "pal_string_utils.h"
00019 #include "filenameUnifier.h"
00020
00021 #include "dcast.h"
00022 #include "eggData.h"
00023 #include "bamFile.h"
00024 #include "pnotify.h"
00025 #include "notifyCategory.h"
00026 #include "notifySeverity.h"
00027 #include "pystub.h"
00028
00029 #include <stdio.h>
00030
00031
00032
00033
00034
00035
00036 EggPalettize::
00037 EggPalettize() : EggMultiFilter(true) {
00038 set_program_description
00039 ("egg-palettize attempts to pack several texture maps from various models "
00040 "together into one or more palette images, for improved rendering performance "
00041 "and ease of texture management. It can also resize textures and convert "
00042 "them to another image file format, whether or not they are actually "
00043 "placed on a palette, and can manage some "
00044 "simple texture properties, like mipmapping and rendering "
00045 "format.\n\n"
00046
00047 "egg-palettize reads a texture attributes file, usually named "
00048 "textures.txa, which contains instructions from the user about "
00049 "resizing particular textures. Type egg-palettize -H for an "
00050 "introduction to the syntax of this file.\n\n"
00051
00052 "The palettization information from previous runs is recorded in a file "
00053 "named textures.boo (assuming the attributes file is named "
00054 "textures.txa); a complete record of every egg file and every texture "
00055 "that has been referenced is kept here. This allows the program "
00056 "to intelligently manage the multiple egg files that may reference "
00057 "the textures in question.");
00058
00059
00060 clear_runlines();
00061 add_runline("[opts] file.egg [file.egg ...]");
00062
00063
00064
00065 remove_option("f");
00066 _force_complete = true;
00067
00068 add_option
00069 ("af", "filename", 0,
00070 "Read the indicated file as the .txa file. The default is textures.txa.",
00071 &EggPalettize::dispatch_filename, &_got_txa_filename, &_txa_filename);
00072
00073 add_option
00074 ("a", "filename", 0,
00075 "Deprecated option. This is the same as -af.",
00076 &EggPalettize::dispatch_filename, &_got_txa_filename, &_txa_filename);
00077
00078 add_option
00079 ("as", "script", 0,
00080 "Accept the script specified on the command line as the contents of the "
00081 ".txa file, instead of reading a file on disk. This implies -nodb and "
00082 "-opt.",
00083 &EggPalettize::dispatch_string, &_got_txa_script, &_txa_script);
00084
00085 add_option
00086 ("nodb", "", 0,
00087 "Don't read or record the state information to a .boo file. By default, "
00088 "the palettization information is recorded so it can be preserved "
00089 "between multiple invocations of egg-palettize. If you specify this "
00090 "parameter, all the egg files to be palettized together must be "
00091 "named at the same time. This also implies -opt, since there's no point "
00092 "in not making an optimal packing if you won't be preserving the "
00093 "state for future adjustments.",
00094 &EggPalettize::dispatch_none, &_nodb);
00095
00096 add_option
00097 ("tn", "pattern", 0,
00098 "Specify the name to generate for each palette image. The string should "
00099 "contain %g for the group name, %p for the page name, and %i for the "
00100 "index within the page. The extension is inferred from the image "
00101 "type. The default is '%g_palette_%p_%i'.",
00102 &EggPalettize::dispatch_string, &_got_generated_image_pattern,
00103 &_generated_image_pattern);
00104
00105 add_option
00106 ("pi", "", 0,
00107 "Do not process anything, but instead report the detailed palettization "
00108 "information written in the state file.",
00109 &EggPalettize::dispatch_none, &_report_pi);
00110
00111 add_option
00112 ("s", "", 0,
00113 "Do not process anything, but report statistics on palette "
00114 "and texture utilization from the state file.",
00115 &EggPalettize::dispatch_none, &_report_statistics);
00116
00117 add_option
00118 ("R", "", 0,
00119 "Remove the named egg files from the previously-generated state data "
00120 "file.",
00121 &EggPalettize::dispatch_none, &_remove_eggs);
00122
00123
00124
00125 add_option
00126 ("d", "dirname", 0,
00127 "The directory in which to write the palettized egg files. This is "
00128 "only necessary if more than one egg file is processed at the same "
00129 "time; if it is included, each egg file will be processed and written "
00130 "into the indicated directory.",
00131 &EggPalettize::dispatch_filename, &_got_output_dirname, &_output_dirname);
00132 add_option
00133 ("dm", "dirname", 0,
00134 "The directory in which to place all maps: generated palettes, "
00135 "as well as images which were not placed on palettes "
00136 "(but may have been resized). If this contains the string %g, "
00137 "this will be replaced with the 'dir' string associated with a "
00138 "palette group; see egg-palettize -H.",
00139 &EggPalettize::dispatch_string, &_got_map_dirname, &_map_dirname);
00140 add_option
00141 ("ds", "dirname", 0,
00142 "The directory to write palette shadow images to. These are working "
00143 "copies of the palette images, useful when the palette image type is "
00144 "a lossy-compression type like JPEG; you can avoid generational loss "
00145 "of quality on the palette images with each pass through the palettes "
00146 "by storing these extra shadow images in a lossless image type. This "
00147 "directory is only used if the :shadowtype keyword appears in the .txa "
00148 "file.",
00149 &EggPalettize::dispatch_filename, &_got_shadow_dirname, &_shadow_dirname);
00150 add_option
00151 ("dr", "dirname", 0,
00152 "The directory to make map filenames relative to when writing egg "
00153 "files. If specified, this should be an initial substring of -dm.",
00154 &EggPalettize::dispatch_filename, &_got_rel_dirname, &_rel_dirname);
00155 add_option
00156 ("g", "group", 0,
00157 "The default palette group that egg files will be assigned to if they "
00158 "are not explicitly assigned to any other group.",
00159 &EggPalettize::dispatch_string, &_got_default_groupname, &_default_groupname);
00160 add_option
00161 ("gdir", "name", 0,
00162 "The \"dir\" string to associate with the default palette group "
00163 "specified with -g, if no other dir name is given in the .txa file.",
00164 &EggPalettize::dispatch_string, &_got_default_groupdir, &_default_groupdir);
00165
00166 add_option
00167 ("all", "", 0,
00168 "Consider all the textures referenced in all egg files that have "
00169 "ever been palettized, not just the egg files that appear on "
00170 "the command line.",
00171 &EggPalettize::dispatch_none, &_all_textures);
00172 add_option
00173 ("egg", "", 0,
00174 "Regenerate all egg files that need modification, even those that "
00175 "aren't named on the command line.",
00176 &EggPalettize::dispatch_none, &_redo_eggs);
00177 add_option
00178 ("redo", "", 0,
00179 "Force a regeneration of each image from its original source(s). "
00180 "When used in conjunction with -egg, this also forces each egg file to "
00181 "be regenerated.",
00182 &EggPalettize::dispatch_none, &_redo_all);
00183 add_option
00184 ("opt", "", 0,
00185 "Force an optimal packing. By default, textures are added to "
00186 "existing palettes without disturbing them, which can lead to "
00187 "suboptimal packing. Including this switch forces the palettes "
00188 "to be rebuilt if necessary to optimize the packing, but this "
00189 "may invalidate other egg files which share this palette.",
00190 &EggPalettize::dispatch_none, &_optimal);
00191 add_option
00192 ("omitall", "", 0,
00193 "Re-enables the flag to omit all textures. This flag is normally on "
00194 "by default, causing nothing actually to be palettized, until the "
00195 "first time egg-palettize is run with the -opt flag, which turns off "
00196 "the omitall flag and thenceforth allows textures to be combined "
00197 "into palettes. Specifying this flag restores the original behavior "
00198 "of keeping every texture as a separate image (which is convenient for "
00199 "development).",
00200 &EggPalettize::dispatch_none, &_omitall);
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 add_option
00216 ("H", "", 0,
00217 "Describe the syntax of the attributes file.",
00218 &EggPalettize::dispatch_none, &_describe_input_file);
00219
00220 _txa_filename = "textures.txa";
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 bool EggPalettize::
00233 handle_args(ProgramBase::Args &args) {
00234 if (_describe_input_file) {
00235 describe_input_file();
00236 exit(1);
00237 }
00238
00239 if (_remove_eggs) {
00240
00241
00242 _remove_egg_list = args;
00243 return true;
00244 }
00245
00246
00247 return EggMultiFilter::handle_args(args);
00248 }
00249
00250
00251
00252
00253
00254
00255 void EggPalettize::
00256 describe_input_file() {
00257 nout <<
00258 "An attributes file consists mostly of lines describing desired sizes of "
00259 "texture maps. The format resembles, but is not identical to, that of "
00260 "the qtess input file. Examples:\n\n"
00261
00262 " texturename.rgb : 64 64\n"
00263 " texture-a.rgb texture-b.rgb : 32 16 margin 2\n"
00264 " *.rgb : 50% cont\n"
00265 " eyelids.rgb : 16 16 omit\n\n"
00266
00267 "In general, each line consists of one or more filenames (and can "
00268 "contain shell globbing characters like '*' or '?'), and a colon "
00269 "followed by a size request. For each texture appearing in an egg "
00270 "file, the input list is scanned from the beginning and the first "
00271 "line that matches the filename defines the size of the texture, as "
00272 "well as other properties associated with the texture.\n\n"
00273
00274 "A size request is most often a pair of numbers, giving a specific x y "
00275 "size of the texture. A third number may also be supplied, giving a "
00276 "specific number of channels to convert to (for instance, to force an "
00277 "image to a 64x64 grayscale image, set its size to 64 64 1). "
00278 "Alternatively, a percentage scaling may be specified, e.g. 30%. The "
00279 "requested size need not be a power of 2.\n\n"
00280
00281 "Other valid keywords that may be specified on the same line with the "
00282 "texture are:\n\n";
00283
00284 show_text(" omit", 10,
00285 "This indicates that the texture should not be placed on any "
00286 "palette image. It may still be resized, and it will in any "
00287 "case be copied into the install directory.\n\n");
00288
00289 show_text(" margin i", 10,
00290 "This specifies the number of pixels that should be written "
00291 "around the border of the texture when it is placed in a "
00292 "palette image; i is the integer number of pixels. The "
00293 "use of a margin helps cut down on color bleed "
00294 "from neighboring images. If the texture does "
00295 "not end up placed in a palette image, the "
00296 "margin is not used. If not specified, the default margin is "
00297 "used, which is specified by the :margin command (see below).\n\n");
00298
00299 show_text(" coverage f", 10,
00300 "This parameter specifies the maximum coverage to allow for this "
00301 "particular texture before rejecting it "
00302 "from the palette. If not specified, the default is "
00303 "specified by the :coverage command (see below).\n\n");
00304
00305 nout << " nearest\n"
00306 << " linear\n";
00307 show_text(" mipmap", 10,
00308 "One of these options may be used to force the texture to use "
00309 "a particular minfilter/magfilter sampling mode. If this is not "
00310 "specified, the sampling mode specified in the egg file is "
00311 "used. Textures that use different sampling modes cannot "
00312 "be placed together on the same palette images.\n\n");
00313
00314 show_text(" rgba", 10,
00315 "This specifies format 'rgba' should be in effect for this "
00316 "particular texture. Any valid egg texture format, such as "
00317 "rgba, rgba12, rgba8, rgb5, luminance, etc. may be specified. "
00318 "If nothing is specified, the format specified in the egg file "
00319 "is used. The format will automatically be downgraded to match "
00320 "the number of channels in the texture image; e.g. rgba will "
00321 "automatically be converted to rgb for a three-channel image. "
00322 "As with the filter modes above, textures that use different "
00323 "formats cannot be placed together on the same palette "
00324 "images.\n\n");
00325
00326 show_text(" force-rgba", 10,
00327 "This specifies a particular format, as above, that should be "
00328 "in effect for this texture, but it will not be downgraded to "
00329 "match the number of channels. As above, any valid egg texture "
00330 "format may be used, e.g. force-rgba12, force-rgb5, etc.\n\n");
00331
00332 show_text(" keep-format", 10,
00333 "This specifies that the image format requested by an egg file "
00334 "should be exactly preserved, without attempting to optimize "
00335 "it by, for instance, automatically downgrading.\n\n");
00336
00337 show_text(" generic", 10,
00338 "Specifies that any image format requested by an egg file "
00339 "that requests a particular bitdepth should be replaced by "
00340 "its generic equivalent, e.g. rgba8 should become rgba.\n\n");
00341
00342 show_text(" (alpha mode)", 10,
00343 "A particular alpha mode may be applied to a texture by naming "
00344 "the alpha mode. This may be any valid egg alpha mode, e.g. "
00345 "blend, binary, ms, or dual.\n\n");
00346
00347 show_text(" repeat_u, repeat_v, clamp_u, clamp_v", 10,
00348 "Explcitly specify whether the source texture should repeat or "
00349 "clamp in each direction. Although palette images are always "
00350 "clamped, this will affect the pixels that are painted into "
00351 "the palette image.\n\n");
00352
00353 show_text(" (image type)", 10,
00354 "A texture may be converted to a particular image type, for "
00355 "instance jpg or rgb, by naming the type. If present, this "
00356 "overrides the :imagetype command, described below. As with "
00357 ":imagetype, you may also specify two type names separated "
00358 "by a comma, to indicate that a different file should be written "
00359 "for the color and alpha components.\n\n");
00360
00361 show_text(" (group name)", 10,
00362 "A texture may also be assigned to a specific group by naming "
00363 "the group. The groups are defined using the :group command "
00364 "(see below). Normally, textures are not assigned directly "
00365 "to groups; instead, it is more useful to assign the egg files "
00366 "they are referenced in to groups; see below.\n\n");
00367
00368 show_text(" cont", 10,
00369 "Normally, a texture file (or egg file) scans the lines in the "
00370 "attributes file from the top, and stops on the first line that "
00371 "matches its name. If the keyword 'cont' is included on the "
00372 "line, however, the texture will apply the properties given "
00373 "on the line, and then continue scanning. This trick may be "
00374 "used to specify general parameters for all files while still "
00375 "allowing the texture to match a more specific line below.\n\n");
00376
00377 nout <<
00378 "The attributes file may also assign egg files to various "
00379 "named palette groups. The syntax is similar to the above:\n\n"
00380
00381 " car-blue.egg : main\n"
00382 " road.egg house.egg : main\n"
00383 " plane.egg : phase_2 main\n"
00384 " *.egg : phase_2\n\n"
00385
00386 "Any number of egg files may be named on one line, and the set of "
00387 "named egg files may be simultaneously assigned to one or more groups. "
00388 "Each group must have been previously defined using the :group command "
00389 "(see below). Each texture that is referenced by a given "
00390 "egg file will be palettized "
00391 "into at least one of the groups assigned to the egg file.\n\n"
00392
00393 "Finally, there are a number of special commands that may appear in the "
00394 "attributes file; some of these have been alluded to in the above "
00395 "comments. These commands typically specify global parameters or "
00396 "palettization options. The command names begin with a colon to "
00397 "distinguish them from other kinds of lines. Each command must "
00398 "appear on a line by itself. The commands are:\n\n";
00399
00400 show_text(" :palette xsize ysize", 10,
00401 "This specifies the size of the palette images to be "
00402 "created. The default is 512 by 512.\n\n");
00403
00404 show_text(" :margin msize", 10,
00405 "This specifies the amount of default margin to apply to all "
00406 "textures that are placed within a palette image. The margin "
00407 "is a number of additional pixels that are written around the "
00408 "texture image to help prevent color bleeding between "
00409 "neighboring images within the same palette. The default "
00410 "is 2.\n\n");
00411
00412 show_text(" :background r g b a", 10,
00413 "Specifies the background color of the generated palette "
00414 "images. Normally, this is black, and it doesn't matter much "
00415 "since the background color is, by definition, the color "
00416 "of the palette images where nothing is used.\n\n");
00417
00418 show_text(" :coverage area", 10,
00419 "The 'coverage' of a texture refers to the fraction of "
00420 "the area in the texture image that is actually used, according "
00421 "to the UV's that appear in the various egg files. If a texture's "
00422 "coverage is less than 1, only some of the texture image is used "
00423 "(and only this part will be written to the palette). If the "
00424 "coverage is greater than 1, the texture repeats that number of "
00425 "times. A repeating texture may still be palettized by writing "
00426 "the required number of copies into the palette image, according "
00427 "to the coverage area.\n\n"
00428
00429 "This command specifies the maximum coverage to allow for any "
00430 "texture before rejecting it from the palette. It may be any "
00431 "floating-point number greater than zero. Set this to 1 "
00432 "to avoid palettizing repeating textures altogether. This may "
00433 "also be overridden for a particular texture using the 'coverage' "
00434 "keyword on the texture line.\n\n");
00435
00436 show_text(" :powertwo flag", 10,
00437 "Specifies whether textures should be forced to a power of two "
00438 "size when they are not placed within a palette. Use 1 for true, "
00439 "to force textures to a power of two; or 0 to leave them exactly "
00440 "the size they are specified. The default is true.\n\n");
00441
00442 show_text(" :round fraction fuzz", 10,
00443 "When the coverage area is computed, it may optionally be "
00444 "rounded up to the next sizeable unit before placing the "
00445 "texture within the palette. This helps reduce constant "
00446 "repalettization caused by slight differences in coverage "
00447 "between egg files. For instance, say file a.egg references a "
00448 "texture with a coverage of 0.91, and then later file b.egg "
00449 "is discovered to reference the same texture with a coverage of "
00450 "0.92. If the texture was already palettized with the original "
00451 "coverage of 0.91, it must now be moved in the palette.\n\n"
00452
00453 "Rounding the coverage area up to some fixed unit reduces this "
00454 "problem. For instance, if you specified a value 0.5 for "
00455 "fraction in the above command, it would round both of these "
00456 "values up to the next half-unit, or 1.0.\n\n"
00457
00458 "The second number is a fuzz factor, and should be a small "
00459 "number; if the coverage area is just slightly larger than "
00460 "the last unit (within the fuzz factor), it is rounded down "
00461 "instead of up. This is intended to prevent UV coordinates "
00462 "that are just slightly out of the range [0, 1] (which happens "
00463 "fairly often) from forcing the palettization area all the "
00464 "way up to the next stop.\n\n"
00465
00466 "The default if this is unspecified is 0.1 0.01. That is, "
00467 "round up to the next tenth, unless within a hundredth of the "
00468 "last tenth. To disable rounding, specify ':round no'. "
00469 "Rounding is implicitly disabled when you run with the -opt "
00470 "command line option.\n\n");
00471
00472 show_text(" :remap (never | group | poly)", 10,
00473 "Sometimes two different parts of an egg file may reference "
00474 "different regions of a repeating texture. For instance, "
00475 "group A may reference UV coordinate values ranging from (0,5) "
00476 "to (1,6), for a coverage of 1.0, while group B references "
00477 "values ranging from (0,2) to (1,4), for a coverage of 2.0. "
00478 "The maximum coverage used is only 2.0, and thus the texture "
00479 "only needs to appear in the palette twice, but the total range "
00480 "of UV's is from (0,2) to (1,6), causing an apparent coverage "
00481 "of 4.0.\n\n"
00482
00483 "It's possible for egg-palettize to reduce this kind of mistake "
00484 "by remapping both groups of UV's so that they overlap. This "
00485 "parameter specifies how this operation should be done. If "
00486 "the option is 'never', remapping will not be performed; if "
00487 "'group', entire groups will be remapped as a unit, if 'poly', "
00488 "individual polygons within a group may be remapped. This last "
00489 "option provides the greatest minimization of UV coverage, "
00490 "but possibly at the expense of triangle strips in the resulting "
00491 "model (since some vertices can no longer be shared).\n\n"
00492
00493 "Sometimes, it may be necessary to be more restrictive on "
00494 "character geometry than on non-character geometry, because "
00495 "the cost of adding additional vertices on characters is "
00496 "greater. You can specify a different kind of remapping for "
00497 "characters only, by using the keyword 'char' on the same line, "
00498 "e.g. ':remap group char never'.\n\n"
00499
00500 "The default remap mode for all geometry, character or otherwise, "
00501 "if no remap mode is specified is 'poly'.\n\n");
00502
00503 show_text(" :imagetype type[,alpha_type]", 10,
00504 "This specifies the default type of image file that should be "
00505 "generated for each palette image and for each unplaced texture "
00506 "copied into the install directory. This may be overridden for "
00507 "a particular texture by specifying the image type on the "
00508 "texture line.\n\n"
00509
00510 "If two image type names separate by a comma are given, it means "
00511 "to generate a second file of the second type for the alpha "
00512 "channel, for images that require an alpha channel. This allows "
00513 "support for image file formats that do not support alpha "
00514 "(for instance, JPEG).\n\n");
00515
00516 show_text(" :shadowtype type[,alpha_type]", 10,
00517 "When generating palette images, egg-palettize sometimes has to "
00518 "read and write the same palette image repeatedly. If the "
00519 "palette image is stored in a lossy file format (like JPEG, see "
00520 ":imagetype), this can eventually lead to degradation of the "
00521 "palette images. As a workaround, egg-palettize can store "
00522 "its working copies of the palette images in lossless shadow "
00523 "images. Specify this to enable this feature; give it the "
00524 "name of a lossless image file format. The shadow images will "
00525 "be written to the directory specified by -ds on the command "
00526 "line.\n\n");
00527
00528 show_text(" :group groupname [dir dirname] [on group1 group2 ...] [includes group1 group2 ...]", 10,
00529 "This defines a palette group, a logical division of textures. "
00530 "Each texture is assigned to one or more palette groups before "
00531 "being placed in any palette image; the palette images are "
00532 "tied to the groups.\n\n"
00533
00534 "The optional parameter 'dir' specifies a directory name to "
00535 "associate with this group. This name is substituted in for "
00536 "the string '%g' when it appears in the map directory name "
00537 "specified on the command line with -dm; this may be used to "
00538 "install textures and palettes into different directories based "
00539 "on the groups they are assigned to.\n\n"
00540
00541 "Palette groups can also be hierarchically related. The "
00542 "keyword 'on' specifies any number of groups that this "
00543 "palette group depends on; if a texture has already been "
00544 "assigned to one of this group's dependent groups, it will "
00545 "not need to be assigned to this group. This also implicitly "
00546 "specifies a dir if one has not already been specified.\n\n"
00547
00548 "The keyword 'includes' names one or more groups that depend "
00549 "on this group.\n\n");
00550
00551 show_text(" :textureswap groupname texturename0 texturename1 [texturename2 ...]", 10,
00552 "This option builds a set of matching, interchangeable palette images. "
00553 "All palette images in the set share the same internal texture layout. "
00554 "The intention is to be able to swap palette images out at runtime, "
00555 "to replace entire sets of textures on a model in one operation. "
00556 "The textures named by this option indicate the texture images "
00557 "which are similar to each other, and which all should be assigned "
00558 "to the same placement on the different palette images: "
00559 "texturename0 will be assigned to palette image 0, "
00560 "texturename1 to the same position on palette image 1, "
00561 "texturename2 to the same position on palette image 2, and so on. "
00562 "To define a complete palette image, you must repeat this option "
00563 "several times to associate all of the similar texture images.\n\n");
00564
00565 nout <<
00566 "Comments may appear freely throughout the file, and are set off by a "
00567 "hash mark (#).\n\n";
00568 }
00569
00570
00571
00572
00573
00574
00575
00576 void EggPalettize::
00577 run() {
00578
00579
00580
00581
00582 Notify *notify = Notify::ptr();
00583 NotifyCategory *loader_cat = notify->get_category(":loader");
00584 if (loader_cat != (NotifyCategory *)NULL &&
00585 loader_cat->get_severity() == NS_info) {
00586 loader_cat->set_severity(NS_warning);
00587 }
00588
00589 Filename state_filename;
00590 BamFile state_file;
00591
00592 if (_got_txa_script) {
00593
00594
00595 _nodb = true;
00596
00597 } else {
00598
00599 if (!_txa_filename.exists() && !_got_txa_filename) {
00600
00601
00602
00603 Filename maybe = _txa_filename;
00604 maybe.set_dirname("src/maps");
00605 if (maybe.exists()) {
00606 _txa_filename = maybe;
00607 }
00608 }
00609
00610 if (!_txa_filename.exists()) {
00611 nout << FilenameUnifier::make_user_filename(_txa_filename)
00612 << " does not exist; cannot run.\n";
00613 exit(1);
00614 }
00615
00616 FilenameUnifier::set_txa_filename(_txa_filename);
00617
00618 state_filename = _txa_filename;
00619 state_filename.set_extension("boo");
00620 }
00621
00622 if (_nodb) {
00623
00624
00625 pal = new Palettizer;
00626
00627
00628 _optimal = true;
00629
00630 } else if (!state_filename.exists()) {
00631 nout << FilenameUnifier::make_user_filename(state_filename)
00632 << " does not exist; starting palettization from scratch.\n";
00633 pal = new Palettizer;
00634
00635
00636 pal->_omit_everything = true;
00637
00638 } else {
00639
00640
00641
00642 nout << "Reading " << FilenameUnifier::make_user_filename(state_filename)
00643 << "\n";
00644
00645 if (!state_file.open_read(state_filename)) {
00646 nout << FilenameUnifier::make_user_filename(state_filename)
00647 << " exists, but cannot be read. Perhaps you should "
00648 << "remove it so a new one can be created.\n";
00649 exit(1);
00650 }
00651
00652 TypedWritable *obj = state_file.read_object();
00653 if (obj == (TypedWritable *)NULL || !state_file.resolve()) {
00654 nout << FilenameUnifier::make_user_filename(state_filename)
00655 << " exists, but appears to be corrupt. Perhaps you "
00656 << "should remove it so a new one can be created.\n";
00657 exit(1);
00658 }
00659
00660 if (!obj->is_of_type(Palettizer::get_class_type())) {
00661 nout << FilenameUnifier::make_user_filename(state_filename)
00662 << " exists, but does not appear to be "
00663 << "an egg-palettize output file. Perhaps you "
00664 << "should remove it so a new one can be created.\n";
00665 exit(1);
00666 }
00667
00668 state_file.close();
00669
00670 pal = DCAST(Palettizer, obj);
00671
00672 if (pal->_read_pi_version > pal->_pi_version) {
00673 nout << FilenameUnifier::make_user_filename(state_filename)
00674 << " was written by a more recent version of egg-palettize "
00675 << "than this one. You will need to update your egg-palettize.\n";
00676 exit(1);
00677 }
00678
00679 if (pal->_read_pi_version < pal->_min_pi_version) {
00680 nout << FilenameUnifier::make_user_filename(state_filename)
00681 << " was written by an old version of egg-palettize.\n\n"
00682 << "You will need to make undo-pal (or simply remove the file "
00683 << FilenameUnifier::make_user_filename(state_filename)
00684 << " and try again).\n\n";
00685 exit(1);
00686 }
00687
00688 if (!pal->is_valid()) {
00689 nout << FilenameUnifier::make_user_filename(state_filename)
00690 << " could not be properly read. You will need to remove it.\n";
00691 exit(1);
00692 }
00693 }
00694
00695 pal->set_noabs(_noabs);
00696
00697 if (_report_pi) {
00698 pal->report_pi();
00699 exit(0);
00700 }
00701
00702 if (_report_statistics) {
00703 pal->report_statistics();
00704 exit(0);
00705 }
00706
00707 bool okflag = true;
00708
00709 if (_got_txa_script) {
00710 istringstream txa_script(_txa_script);
00711 pal->read_txa_file(txa_script, "command line");
00712
00713 } else {
00714 _txa_filename.set_text();
00715 ifstream txa_file;
00716 if (!_txa_filename.open_read(txa_file)) {
00717 nout << "Unable to open " << _txa_filename << "\n";
00718 exit(1);
00719 }
00720 pal->read_txa_file(txa_file, _txa_filename);
00721 }
00722
00723 if (_got_generated_image_pattern) {
00724 pal->_generated_image_pattern = _generated_image_pattern;
00725 }
00726
00727 if (_got_default_groupname) {
00728 pal->_default_groupname = _default_groupname;
00729 } else {
00730 pal->_default_groupname = _txa_filename.get_basename_wo_extension();
00731 }
00732
00733 if (_got_default_groupdir) {
00734 pal->_default_groupdir = _default_groupdir;
00735 }
00736
00737 if (_got_map_dirname) {
00738 pal->_map_dirname = _map_dirname;
00739 }
00740 if (_got_shadow_dirname) {
00741 pal->_shadow_dirname = _shadow_dirname;
00742 }
00743 if (_got_rel_dirname) {
00744 pal->_rel_dirname = _rel_dirname;
00745 FilenameUnifier::set_rel_dirname(_rel_dirname);
00746 }
00747
00748
00749
00750
00751
00752 pal->_omit_solitary = _optimal;
00753
00754 if (_omitall) {
00755 pal->_omit_everything = true;
00756 } else if (_optimal) {
00757 pal->_omit_everything = false;
00758 }
00759
00760 pal->all_params_set();
00761
00762
00763 Args::const_iterator ai;
00764 for (ai = _remove_egg_list.begin(); ai != _remove_egg_list.end(); ++ai) {
00765 Filename filename = (*ai);
00766 pal->remove_egg_file(filename.get_basename());
00767 }
00768
00769
00770 bool all_eggs_valid = true;
00771
00772 string egg_comment = get_exec_command();
00773 Eggs::const_iterator ei;
00774 for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
00775 EggData *egg_data = (*ei);
00776 Filename source_filename = egg_data->get_egg_filename();
00777 Filename dest_filename = get_output_filename(source_filename);
00778 string name = source_filename.get_basename();
00779
00780 EggFile *egg_file = pal->get_egg_file(name);
00781 if (!egg_file->from_command_line(egg_data, source_filename, dest_filename,
00782 egg_comment)) {
00783 all_eggs_valid = false;
00784
00785 } else {
00786 pal->add_command_line_egg(egg_file);
00787 }
00788 }
00789
00790 if (!all_eggs_valid) {
00791 nout << "Errors reading egg file(s).\n";
00792 exit(1);
00793 }
00794
00795 if (_optimal) {
00796
00797
00798 pal->reset_images();
00799 _all_textures = true;
00800
00801
00802
00803
00804
00805
00806 }
00807
00808 if (_all_textures) {
00809 pal->process_all(_redo_all, state_filename);
00810 } else {
00811 pal->process_command_line_eggs(_redo_all, state_filename);
00812 }
00813
00814 if (_optimal) {
00815
00816
00817 pal->optimal_resize();
00818 }
00819
00820 if (_redo_eggs) {
00821 if (!pal->read_stale_eggs(_redo_all)) {
00822 okflag = false;
00823 }
00824 }
00825
00826 if (okflag) {
00827 pal->generate_images(_redo_all);
00828
00829 if (_redo_eggs) {
00830
00831
00832 if (!pal->read_stale_eggs(false)) {
00833 okflag = false;
00834 }
00835 }
00836 }
00837
00838 if (okflag) {
00839 if (!pal->write_eggs()) {
00840 okflag = false;
00841 }
00842 }
00843
00844 if (!_nodb) {
00845
00846
00847
00848
00849 string dirname = state_filename.get_dirname();
00850 if (dirname.empty()) {
00851 dirname = ".";
00852 }
00853 Filename temp_filename = Filename::temporary(dirname, "pi");
00854
00855 if (!state_file.open_write(temp_filename) ||
00856 !state_file.write_object(pal)) {
00857 nout << "Unable to write palettization information to "
00858 << FilenameUnifier::make_user_filename(temp_filename)
00859 << "\n";
00860 exit(1);
00861 }
00862
00863 state_file.close();
00864 state_filename.unlink();
00865 if (!temp_filename.rename_to(state_filename)) {
00866 nout << "Unable to rename temporary file "
00867 << FilenameUnifier::make_user_filename(temp_filename) << " to "
00868 << FilenameUnifier::make_user_filename(state_filename) << "\n";
00869 exit(1);
00870 }
00871 }
00872
00873 if (!okflag) {
00874 exit(1);
00875 }
00876 }
00877
00878 int
00879 main(int argc, char *argv[]) {
00880
00881 pystub();
00882
00883 EggPalettize prog;
00884 prog.parse_command_line(argc, argv);
00885 prog.run();
00886 return 0;
00887 }
00888
00889