00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "texturePlacement.h"
00020 #include "textureReference.h"
00021 #include "textureImage.h"
00022 #include "paletteGroup.h"
00023 #include "paletteImage.h"
00024 #include "palettizer.h"
00025 #include "eggFile.h"
00026 #include "destTextureImage.h"
00027
00028 #include "indent.h"
00029 #include "datagram.h"
00030 #include "datagramIterator.h"
00031 #include "bamReader.h"
00032 #include "bamWriter.h"
00033 #include "pnmImage.h"
00034
00035 TypeHandle TexturePlacement::_type_handle;
00036
00037
00038
00039
00040
00041
00042
00043 TexturePlacement::
00044 TexturePlacement() {
00045 _texture = (TextureImage *)NULL;
00046 _group = (PaletteGroup *)NULL;
00047 _image = (PaletteImage *)NULL;
00048 _dest = (DestTextureImage *)NULL;
00049 _has_uvs = false;
00050 _size_known = false;
00051 _is_filled = true;
00052 _omit_reason = OR_none;
00053 }
00054
00055
00056
00057
00058
00059
00060 TexturePlacement::
00061 TexturePlacement(TextureImage *texture, PaletteGroup *group) :
00062 _texture(texture),
00063 _group(group)
00064 {
00065 _omit_reason = OR_working;
00066
00067 if (!texture->is_size_known()) {
00068
00069
00070 _omit_reason = OR_unknown;
00071 }
00072
00073 _image = (PaletteImage *)NULL;
00074 _dest = (DestTextureImage *)NULL;
00075 _has_uvs = false;
00076 _size_known = false;
00077 _is_filled = false;
00078 }
00079
00080
00081
00082
00083
00084
00085 TexturePlacement::
00086 ~TexturePlacement() {
00087
00088
00089 References::iterator ri;
00090 References copy_references = _references;
00091 for (ri = copy_references.begin(); ri != copy_references.end(); ++ri) {
00092 TextureReference *reference = (*ri);
00093 nassertv(reference->get_placement() == this);
00094 reference->clear_placement();
00095 }
00096
00097
00098 _group->unplace(this);
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 const string &TexturePlacement::
00108 get_name() const {
00109 return _texture->get_name();
00110 }
00111
00112
00113
00114
00115
00116
00117 TextureImage *TexturePlacement::
00118 get_texture() const {
00119 return _texture;
00120 }
00121
00122
00123
00124
00125
00126
00127 const TextureProperties &TexturePlacement::
00128 get_properties() const {
00129 return _texture->get_properties();
00130 }
00131
00132
00133
00134
00135
00136
00137 PaletteGroup *TexturePlacement::
00138 get_group() const {
00139 return _group;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 void TexturePlacement::
00149 add_egg(TextureReference *reference) {
00150 reference->mark_egg_stale();
00151
00152
00153
00154
00155
00156
00157
00158 _references.insert(reference);
00159 }
00160
00161
00162
00163
00164
00165
00166
00167 void TexturePlacement::
00168 remove_egg(TextureReference *reference) {
00169 reference->mark_egg_stale();
00170
00171
00172
00173
00174 _references.erase(reference);
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 void TexturePlacement::
00185 mark_eggs_stale() {
00186 References::iterator ri;
00187 for (ri = _references.begin(); ri != _references.end(); ++ri) {
00188 TextureReference *reference = (*ri);
00189
00190 reference->mark_egg_stale();
00191 }
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 void TexturePlacement::
00201 set_dest(DestTextureImage *dest) {
00202 _dest = dest;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 DestTextureImage *TexturePlacement::
00212 get_dest() const {
00213 return _dest;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 bool TexturePlacement::
00230 determine_size() {
00231 if (!_texture->is_size_known()) {
00232
00233 force_replace();
00234 _omit_reason = OR_unknown;
00235 return false;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 _has_uvs = false;
00253 _position._wrap_u = EggTexture::WM_clamp;
00254 _position._wrap_v = EggTexture::WM_clamp;
00255
00256 TexCoordd max_uv, min_uv;
00257
00258 References::iterator ri;
00259 for (ri = _references.begin(); ri != _references.end(); ++ri) {
00260 TextureReference *reference = (*ri);
00261 if (reference->has_uvs()) {
00262 const TexCoordd &n = reference->get_min_uv();
00263 const TexCoordd &x = reference->get_max_uv();
00264
00265 if (_has_uvs) {
00266 min_uv.set(min(min_uv[0], n[0]), min(min_uv[1], n[1]));
00267 max_uv.set(max(max_uv[0], x[0]), max(max_uv[1], x[1]));
00268 } else {
00269 min_uv = n;
00270 max_uv = x;
00271 _has_uvs = true;
00272 }
00273 }
00274
00275
00276
00277 if (reference->get_wrap_u() == EggTexture::WM_repeat) {
00278 _position._wrap_u = EggTexture::WM_repeat;
00279 }
00280 if (reference->get_wrap_v() == EggTexture::WM_repeat) {
00281 _position._wrap_v = EggTexture::WM_repeat;
00282 }
00283 }
00284
00285 nassertr(_has_uvs, false);
00286 TexCoordd rounded_min_uv = min_uv;
00287 TexCoordd rounded_max_uv = max_uv;
00288
00289
00290
00291
00292 if (pal->_round_uvs) {
00293 rounded_max_uv[0] =
00294 ceil((rounded_max_uv[0] - pal->_round_fuzz) / pal->_round_unit) *
00295 pal->_round_unit;
00296 rounded_max_uv[1] =
00297 ceil((rounded_max_uv[1] - pal->_round_fuzz) / pal->_round_unit) *
00298 pal->_round_unit;
00299
00300 rounded_min_uv[0] =
00301 floor((rounded_min_uv[0] + pal->_round_fuzz) / pal->_round_unit) *
00302 pal->_round_unit;
00303 rounded_min_uv[1] =
00304 floor((rounded_min_uv[1] + pal->_round_fuzz) / pal->_round_unit) *
00305 pal->_round_unit;
00306 }
00307
00308
00309
00310 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
00311
00312
00313 if (_texture->get_omit()) {
00314
00315 force_replace();
00316 _omit_reason = OR_omitted;
00317
00318 } else if (get_uv_area() > _texture->get_coverage_threshold()) {
00319
00320 force_replace();
00321 _omit_reason = OR_coverage;
00322
00323 } else if ((_position._x_size > pal->_pal_x_size ||
00324 _position._y_size > pal->_pal_y_size) ||
00325 (_position._x_size == pal->_pal_x_size &&
00326 _position._y_size == pal->_pal_y_size)) {
00327
00328
00329
00330
00331 force_replace();
00332 _omit_reason = OR_size;
00333
00334 } else if (_omit_reason == OR_omitted ||
00335 _omit_reason == OR_size ||
00336 _omit_reason == OR_coverage ||
00337 _omit_reason == OR_unknown) {
00338
00339
00340
00341 force_replace();
00342 mark_eggs_stale();
00343 _omit_reason = OR_working;
00344
00345 } else if (is_placed()) {
00346
00347
00348
00349 if (_position._x_size != _placed._x_size ||
00350 _position._y_size != _placed._y_size ||
00351 _position._min_uv[0] < _placed._min_uv[0] ||
00352 _position._min_uv[1] < _placed._min_uv[1] ||
00353 _position._max_uv[0] > _placed._max_uv[0] ||
00354 _position._max_uv[1] > _placed._max_uv[1]) {
00355
00356
00357
00358
00359
00360
00361
00362 if (pal->_round_uvs) {
00363 compute_size_from_uvs(min_uv, max_uv);
00364 if (_position._x_size <= _placed._x_size &&
00365 _position._y_size <= _placed._y_size &&
00366 _position._min_uv[0] >= _placed._min_uv[0] &&
00367 _position._min_uv[1] >= _placed._min_uv[1] &&
00368 _position._max_uv[0] <= _placed._max_uv[0] &&
00369 _position._max_uv[1] <= _placed._max_uv[1]) {
00370
00371 } else {
00372
00373 compute_size_from_uvs(rounded_min_uv, rounded_max_uv);
00374 force_replace();
00375 }
00376 } else {
00377 force_replace();
00378 }
00379 }
00380
00381 if (_position._wrap_u != _placed._wrap_u ||
00382 _position._wrap_v != _placed._wrap_v) {
00383
00384
00385 _is_filled = false;
00386 _placed._wrap_u = _position._wrap_u;
00387 _placed._wrap_v = _position._wrap_v;
00388 }
00389 }
00390
00391 return true;
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 bool TexturePlacement::
00405 is_size_known() const {
00406 return _size_known;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 OmitReason TexturePlacement::
00416 get_omit_reason() const {
00417 return _omit_reason;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 int TexturePlacement::
00429 get_x_size() const {
00430 nassertr(_size_known, 0);
00431 return _position._x_size;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 int TexturePlacement::
00443 get_y_size() const {
00444 nassertr(_size_known, 0);
00445 return _position._y_size;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 double TexturePlacement::
00457 get_uv_area() const {
00458 if (!_has_uvs) {
00459 return 0.0;
00460 }
00461
00462 TexCoordd range = _position._max_uv - _position._min_uv;
00463 return range[0] * range[1];
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 bool TexturePlacement::
00475 is_placed() const {
00476 return _image != (PaletteImage *)NULL;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 PaletteImage *TexturePlacement::
00486 get_image() const {
00487 nassertr(is_placed(), (PaletteImage *)NULL);
00488 return _image;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 PalettePage *TexturePlacement::
00498 get_page() const {
00499 nassertr(is_placed(), (PalettePage *)NULL);
00500 return _image->get_page();
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510 int TexturePlacement::
00511 get_placed_x() const {
00512 nassertr(is_placed(), 0);
00513 return _placed._x;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523 int TexturePlacement::
00524 get_placed_y() const {
00525 nassertr(is_placed(), 0);
00526 return _placed._y;
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536 int TexturePlacement::
00537 get_placed_x_size() const {
00538 nassertr(is_placed(), 0);
00539 return _placed._x_size;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549 int TexturePlacement::
00550 get_placed_y_size() const {
00551 nassertr(is_placed(), 0);
00552 return _placed._y_size;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562 double TexturePlacement::
00563 get_placed_uv_area() const {
00564 nassertr(is_placed(), 0);
00565 TexCoordd range = _placed._max_uv - _placed._min_uv;
00566 return range[0] * range[1];
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 void TexturePlacement::
00578 place_at(PaletteImage *image, int x, int y) {
00579 nassertv(!is_placed());
00580 nassertv(_size_known);
00581
00582 _image = image;
00583 _is_filled = false;
00584 _position._x = x;
00585 _position._y = y;
00586 _placed = _position;
00587 _omit_reason = OR_none;
00588 }
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 void TexturePlacement::
00599 force_replace() {
00600 if (_image != (PaletteImage *)NULL) {
00601 _image->unplace(this);
00602 _image = (PaletteImage *)NULL;
00603 }
00604 if (_omit_reason == OR_none) {
00605 mark_eggs_stale();
00606 }
00607 _omit_reason = OR_working;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 void TexturePlacement::
00621 omit_solitary() {
00622 nassertv(is_placed());
00623 if (_omit_reason != OR_solitary) {
00624 mark_eggs_stale();
00625 _omit_reason = OR_solitary;
00626 }
00627 }
00628
00629
00630
00631
00632
00633
00634
00635 void TexturePlacement::
00636 not_solitary() {
00637 nassertv(is_placed());
00638 if (_omit_reason != OR_none) {
00639 mark_eggs_stale();
00640 _omit_reason = OR_none;
00641 }
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 bool TexturePlacement::
00653 intersects(int x, int y, int x_size, int y_size) {
00654 nassertr(is_placed(), false);
00655
00656 int hright = x + x_size;
00657 int hbot = y + y_size;
00658
00659 int mright = _placed._x + _placed._x_size;
00660 int mbot = _placed._y + _placed._y_size;
00661
00662 return !(x >= mright || hright <= _placed._x ||
00663 y >= mbot || hbot <= _placed._y);
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673 void TexturePlacement::
00674 compute_tex_matrix(LMatrix3d &transform) {
00675 nassertv(is_placed());
00676
00677 LMatrix3d source_uvs = LMatrix3d::ident_mat();
00678
00679 TexCoordd range = _placed._max_uv - _placed._min_uv;
00680 if (range[0] != 0.0 && range[1] != 0.0) {
00681 source_uvs =
00682 LMatrix3d::translate_mat(-_placed._min_uv) *
00683 LMatrix3d::scale_mat(1.0 / range[0], 1.0 / range[1]);
00684 }
00685
00686 int top = _placed._y + _placed._margin;
00687 int left = _placed._x + _placed._margin;
00688 int x_size = _placed._x_size - _placed._margin * 2;
00689 int y_size = _placed._y_size - _placed._margin * 2;
00690
00691 int bottom = top + y_size;
00692 int pal_x_size = _image->get_x_size();
00693 int pal_y_size = _image->get_y_size();
00694
00695 LVecBase2d t((double)left / (double)pal_x_size,
00696 (double)(pal_y_size - bottom) / (double)pal_y_size);
00697 LVecBase2d s((double)x_size / (double)pal_x_size,
00698 (double)y_size / (double)pal_y_size);
00699
00700 LMatrix3d dest_uvs
00701 (s[0], 0.0, 0.0,
00702 0.0, s[1], 0.0,
00703 t[0], t[1], 1.0);
00704
00705 transform = source_uvs * dest_uvs;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714 void TexturePlacement::
00715 write_placed(ostream &out, int indent_level) {
00716 indent(out, indent_level)
00717 << get_texture()->get_name();
00718
00719 if (is_placed()) {
00720 out << " at "
00721 << get_placed_x() << " " << get_placed_y() << " to "
00722 << get_placed_x() + get_placed_x_size() << " "
00723 << get_placed_y() + get_placed_y_size() << " (coverage "
00724 << get_placed_uv_area() << ")";
00725
00726 if (_placed._wrap_u != EggTexture::WM_unspecified ||
00727 _placed._wrap_v != EggTexture::WM_unspecified) {
00728 if (_placed._wrap_u != _placed._wrap_v) {
00729 out << " (" << _placed._wrap_u << ", " << _placed._wrap_v << ")";
00730 } else {
00731 out << " " << _placed._wrap_u;
00732 }
00733 }
00734 out << "\n";
00735 } else {
00736 out << " not yet placed.\n";
00737 }
00738 };
00739
00740
00741
00742
00743
00744
00745
00746
00747 bool TexturePlacement::
00748 is_filled() const {
00749 return _is_filled;
00750 }
00751
00752
00753
00754
00755
00756
00757
00758 void TexturePlacement::
00759 mark_unfilled() {
00760 _is_filled = false;
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770 void TexturePlacement::
00771 fill_image(PNMImage &image) {
00772 nassertv(is_placed());
00773
00774 _is_filled = true;
00775
00776
00777
00778
00779
00780
00781
00782 LMatrix3d transform;
00783 compute_tex_matrix(transform);
00784 TexCoordd ul = TexCoordd(0.0, 1.0) * transform;
00785 TexCoordd lr = TexCoordd(1.0, 0.0) * transform;
00786
00787
00788 int pal_x_size = _image->get_x_size();
00789 int pal_y_size = _image->get_y_size();
00790
00791 int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
00792 int left = (int)floor(ul[0] * pal_x_size + 0.5);
00793 int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
00794 int right = (int)floor(lr[0] * pal_x_size + 0.5);
00795
00796
00797
00798
00799 int x_size = right - left;
00800 int y_size = bottom - top;
00801 nassertv(x_size >= 0 && y_size >= 0);
00802
00803
00804
00805 const PNMImage &source_full = _texture->read_source_image();
00806 if (!source_full.is_valid()) {
00807 flag_error_image(image);
00808 return;
00809 }
00810
00811 PNMImage source(x_size, y_size, source_full.get_num_channels(),
00812 source_full.get_maxval());
00813 source.quick_filter_from(source_full);
00814
00815 bool alpha = image.has_alpha();
00816 bool source_alpha = source.has_alpha();
00817
00818
00819
00820
00821
00822
00823
00824 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
00825 int sy = y - top;
00826
00827 if (_placed._wrap_v == EggTexture::WM_clamp) {
00828
00829 sy = max(min(sy, y_size - 1), 0);
00830
00831 } else {
00832
00833 sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
00834 }
00835
00836 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
00837 int sx = x - left;
00838
00839 if (_placed._wrap_u == EggTexture::WM_clamp) {
00840
00841 sx = max(min(sx, x_size - 1), 0);
00842
00843 } else {
00844
00845 sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
00846 }
00847
00848 image.set_xel(x, y, source.get_xel(sx, sy));
00849 if (alpha) {
00850 if (source_alpha) {
00851 image.set_alpha(x, y, source.get_alpha(sx, sy));
00852 } else {
00853 image.set_alpha(x, y, 1.0);
00854 }
00855 }
00856 }
00857 }
00858 }
00859
00860
00861
00862
00863
00864
00865
00866
00867 void TexturePlacement::
00868 flag_error_image(PNMImage &image) {
00869 nassertv(is_placed());
00870 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
00871 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
00872 image.set_xel_val(x, y, 1, 0, 0);
00873 }
00874 }
00875 if (image.has_alpha()) {
00876 for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
00877 for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
00878 image.set_alpha_val(x, y, 1);
00879 }
00880 }
00881 }
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 void TexturePlacement::
00893 compute_size_from_uvs(const TexCoordd &min_uv, const TexCoordd &max_uv) {
00894 _position._min_uv = min_uv;
00895 _position._max_uv = max_uv;
00896
00897 TexCoordd range = _position._max_uv - _position._min_uv;
00898
00899 _position._x_size = (int)floor(_texture->get_x_size() * range[0] + 0.5);
00900 _position._y_size = (int)floor(_texture->get_y_size() * range[1] + 0.5);
00901
00902
00903
00904 _position._x_size = max(_position._x_size, 4);
00905 _position._y_size = max(_position._y_size, 4);
00906
00907 _position._margin = _texture->get_margin();
00908
00909
00910
00911
00912
00913 if ((double)_position._margin / (double)_position._x_size > 0.10) {
00914 _position._x_size += _position._margin * 2;
00915 }
00916 if ((double)_position._margin / (double)_position._y_size > 0.10) {
00917 _position._y_size += _position._margin * 2;
00918 }
00919
00920 _size_known = true;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 void TexturePlacement::
00932 register_with_read_factory() {
00933 BamReader::get_factory()->
00934 register_factory(get_class_type(), make_TexturePlacement);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944 void TexturePlacement::
00945 write_datagram(BamWriter *writer, Datagram &datagram) {
00946 TypedWritable::write_datagram(writer, datagram);
00947 writer->write_pointer(datagram, _texture);
00948 writer->write_pointer(datagram, _group);
00949 writer->write_pointer(datagram, _image);
00950 writer->write_pointer(datagram, _dest);
00951
00952 datagram.add_bool(_has_uvs);
00953 datagram.add_bool(_size_known);
00954 _position.write_datagram(writer, datagram);
00955
00956 datagram.add_bool(_is_filled);
00957 _placed.write_datagram(writer, datagram);
00958 datagram.add_int32((int)_omit_reason);
00959
00960 datagram.add_int32(_references.size());
00961 References::const_iterator ri;
00962 for (ri = _references.begin(); ri != _references.end(); ++ri) {
00963 writer->write_pointer(datagram, (*ri));
00964 }
00965
00966 }
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 int TexturePlacement::
00978 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00979 int index = TypedWritable::complete_pointers(p_list, manager);
00980
00981 if (p_list[index] != (TypedWritable *)NULL) {
00982 DCAST_INTO_R(_texture, p_list[index], index);
00983 }
00984 index++;
00985
00986 if (p_list[index] != (TypedWritable *)NULL) {
00987 DCAST_INTO_R(_group, p_list[index], index);
00988 }
00989 index++;
00990
00991 if (p_list[index] != (TypedWritable *)NULL) {
00992 DCAST_INTO_R(_image, p_list[index], index);
00993 }
00994 index++;
00995
00996 if (p_list[index] != (TypedWritable *)NULL) {
00997 DCAST_INTO_R(_dest, p_list[index], index);
00998 }
00999 index++;
01000
01001 int i;
01002 for (i = 0; i < _num_references; i++) {
01003 TextureReference *reference;
01004 DCAST_INTO_R(reference, p_list[index], index);
01005 _references.insert(reference);
01006 index++;
01007 }
01008
01009 return index;
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 TypedWritable* TexturePlacement::
01021 make_TexturePlacement(const FactoryParams ¶ms) {
01022 TexturePlacement *me = new TexturePlacement;
01023 DatagramIterator scan;
01024 BamReader *manager;
01025
01026 parse_params(params, scan, manager);
01027 me->fillin(scan, manager);
01028 return me;
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038 void TexturePlacement::
01039 fillin(DatagramIterator &scan, BamReader *manager) {
01040 TypedWritable::fillin(scan, manager);
01041
01042 manager->read_pointer(scan);
01043 manager->read_pointer(scan);
01044 manager->read_pointer(scan);
01045 manager->read_pointer(scan);
01046
01047 _has_uvs = scan.get_bool();
01048 _size_known = scan.get_bool();
01049 _position.fillin(scan, manager);
01050
01051 _is_filled = scan.get_bool();
01052 _placed.fillin(scan, manager);
01053 _omit_reason = (OmitReason)scan.get_int32();
01054
01055 _num_references = scan.get_int32();
01056 manager->read_pointers(scan, _num_references);
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 bool SortPlacementBySize::
01068 operator ()(TexturePlacement *a, TexturePlacement *b) const {
01069 if (a->get_y_size() < b->get_y_size()) {
01070 return false;
01071
01072 } else if (b->get_y_size() < a->get_y_size()) {
01073 return true;
01074
01075 } else if (a->get_x_size() < b->get_x_size()) {
01076 return false;
01077
01078 } else if (b->get_x_size() < a->get_x_size()) {
01079 return true;
01080 }
01081 return false;
01082 }