00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "ItemSorter.h"
00021
00022 #include "Item.h"
00023 #include "Shape.h"
00024 #include "ShapeFrame.h"
00025 #include "ShapeInfo.h"
00026 #include "MainShapeArchive.h"
00027 #include "RenderSurface.h"
00028 #include "Rect.h"
00029 #include "GameData.h"
00030
00031
00032 #include "WeaponOverlay.h"
00033 #include "MainActor.h"
00034 #include "getObject.h"
00035
00036
00037 using Pentagram::Rect;
00038
00039 #if 0
00040 template<class _T> class MyVector
00041 {
00042 public:
00043 typedef _T *iterator;
00044 typedef _T &reference;
00045
00046 private:
00047 iterator _begin;
00048 iterator _end;
00049 iterator _last;
00050
00051 public:
00052 MyVector()
00053 {
00054 _begin = 0;
00055 _end = 0;
00056 _last = 0;
00057 }
00058
00059 iterator push_back(reference _R)
00060 {
00061 if (!_begin)
00062 {
00063 _begin = new _T[1];
00064 _end = _last = _begin + 1;
00065 *_begin = _R;
00066 return _begin;
00067 }
00068
00069 if (_end == _last)
00070 {
00071 size_t _capacity = _last - _begin;
00072 iterator _new = new _T[_capacity*2];
00073 std::memcpy (_new, _begin, _capacity * sizeof(_T));
00074 _end = _new + (_end - _begin);
00075 delete [] _begin;
00076 _begin = _new;
00077 _last = _begin + (_capacity*2);
00078 }
00079 *_end = _R;
00080 _end++;
00081 return _end-1;
00082 }
00083
00084 void clear() { _end = _begin; }
00085
00086 iterator begin() { return _begin; }
00087 iterator end() { return _end; }
00088 private:
00089
00090
00091 };
00092
00093 #endif
00094
00095
00096
00097 struct SortItem
00098 {
00099 SortItem() : item_num(0), shape(0), order(-1), depends() { }
00100
00101 uint16 item_num;
00102
00103 Shape *shape;
00104 uint32 shape_num;
00105 uint32 frame;
00106 uint32 flags;
00107 uint32 ext_flags;
00108
00109 int sx, sx2;
00110 int sy, sy2;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 sint32 x, xleft;
00131 sint32 y, yfar;
00132 sint32 z, ztop;
00133
00134 sint32 sxleft;
00135 sint32 sxright;
00136
00137 sint32 sxtop;
00138 sint32 sytop;
00139
00140 sint32 sxbot;
00141 sint32 sybot;
00142
00143 bool f32x32 : 1;
00144 bool flat : 1;
00145 bool occl : 1;
00146 bool solid : 1;
00147 bool draw : 1;
00148 bool roof : 1;
00149 bool noisy : 1;
00150 bool anim : 1;
00151 bool trans : 1;
00152 bool fixed : 1;
00153 bool land : 1;
00154
00155 bool occluded : 1;
00156
00157 sint16 clipped;
00158
00159 sint32 order;
00160
00161 std::vector<SortItem *> depends;
00162
00163
00164
00165
00166
00167 inline bool overlap(const SortItem &si2) const;
00168
00169
00170 inline bool occludes(const SortItem &si2) const;
00171
00172
00173 inline bool operator<(const SortItem& si2) const;
00174
00175
00176 inline bool operator<<(const SortItem& si2) const;
00177
00178 };
00179
00180 typedef std::vector<SortItem *> SortItemVector;
00181
00182
00183
00184 inline bool SortItem::overlap(const SortItem &si2) const
00185 {
00186 const int point_top_diff[2] = { sxtop - si2.sxbot, sytop - si2.sybot };
00187 const int point_bot_diff[2] = { sxbot - si2.sxtop, sybot - si2.sytop };
00188
00189
00190
00191
00192
00193
00194 const sint32 dot_top_left = point_top_diff[0] + point_top_diff[1] * 2;
00195
00196
00197 const sint32 dot_top_right = -point_top_diff[0] + point_top_diff[1] * 2;
00198
00199
00200 const sint32 dot_bot_left = point_bot_diff[0] - point_bot_diff[1] * 2;
00201
00202
00203 const sint32 dot_bot_right = -point_bot_diff[0] - point_bot_diff[1] * 2;
00204
00205 const bool right_clear = sxright <= si2.sxleft;
00206 const bool left_clear = sxleft >= si2.sxright;
00207 const bool top_left_clear = dot_top_left >= 0;
00208 const bool top_right_clear = dot_top_right >= 0;
00209 const bool bot_left_clear = dot_bot_left >= 0;
00210 const bool bot_right_clear = dot_bot_right >= 0;
00211
00212 const bool clear = right_clear | left_clear |
00213 bot_right_clear | bot_left_clear |
00214 top_right_clear | top_left_clear;
00215
00216 return !clear;
00217 }
00218
00219
00220 inline bool SortItem::occludes(const SortItem &si2) const
00221 {
00222 const int point_top_diff[2] = { sxtop - si2.sxtop, sytop - si2.sytop };
00223 const int point_bot_diff[2] = { sxbot - si2.sxbot, sybot - si2.sybot };
00224
00225
00226
00227
00228
00229
00230 const sint32 dot_top_left = point_top_diff[0] + point_top_diff[1] * 2;
00231
00232
00233 const sint32 dot_top_right = -point_top_diff[0] + point_top_diff[1] * 2;
00234
00235
00236 const sint32 dot_bot_left = point_bot_diff[0] - point_bot_diff[1] * 2;
00237
00238
00239 const sint32 dot_bot_right = -point_bot_diff[0] - point_bot_diff[1] * 2;
00240
00241
00242 const bool right_res = sxright >= si2.sxright;
00243 const bool left_res = sxleft <= si2.sxleft;
00244 const bool top_left_res = dot_top_left <= 0;
00245 const bool top_right_res = dot_top_right <= 0;
00246 const bool bot_left_res = dot_bot_left <= 0;
00247 const bool bot_right_res = dot_bot_right <= 0;
00248
00249 const bool occluded = right_res & left_res &
00250 bot_right_res & bot_left_res &
00251 top_right_res & top_left_res;
00252
00253 return occluded;
00254 }
00255
00256 inline bool SortItem::operator<(const SortItem& si2) const
00257 {
00258 const SortItem& si1 = *this;
00259
00260
00261 if (si1.flat && si2.flat)
00262 {
00263
00264 if (si1.ztop != si2.ztop) return si1.ztop < si2.ztop;
00265
00266
00267
00268
00269 if (si1.anim != si2.anim) return si1.anim < si2.anim;
00270
00271
00272 if (si1.trans != si2.trans) return si1.trans < si2.trans;
00273
00274
00275 if (si1.draw != si2.draw) return si1.draw > si2.draw;
00276
00277
00278 if (si1.solid != si2.solid) return si1.solid > si2.solid;
00279
00280
00281 if (si1.occl != si2.occl) return si1.occl > si2.occl;
00282
00283
00284 if (si1.f32x32 != si2.f32x32) return si1.f32x32 > si2.f32x32;
00285 }
00286
00287 else {
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if (si1.ztop <= si2.z) return true;
00304 else if (si1.z >= si2.ztop) return false;
00305
00306
00307
00308 }
00309
00310
00311
00312
00313
00314
00315 if (si1.x <= si2.xleft) return true;
00316 else if (si1.xleft >= si2.x) return false;
00317
00318
00319 if (si1.y <= si2.yfar) return true;
00320 else if (si1.yfar >= si2.y) return false;
00321
00322
00323
00324
00325 if (si1.ztop < si2.ztop) return true;
00326 else if (si1.ztop > si2.ztop) return false;
00327
00328
00329 if ((si1.ztop+si1.z)/2 <= si2.z) return true;
00330 else if (si1.z >= (si2.ztop+si2.z)/2) return false;
00331
00332
00333 if ((si1.x+si1.xleft)/2 <= si2.xleft) return true;
00334 else if (si1.xleft >= (si2.x+si2.xleft)/2) return false;
00335
00336
00337 if ((si1.y+si1.yfar)/2 <= si2.yfar) return true;
00338 else if (si1.yfar >= (si2.y+si2.yfar)/2) return false;
00339
00340
00341 if (si1.x + si1.y != si1.x + si2.y) return (si1.x + si1.y < si2.x + si2.y);
00342
00343
00344 if (si1.xleft + si1.yfar != si1.xleft + si2.yfar) return (si1.xleft + si1.yfar < si2.xleft + si2.yfar);
00345
00346
00347 if (si1.x != si2.x) return si1.x < si2.x;
00348
00349
00350 if (si1.y != si2.y) return si1.y < si2.y;
00351
00352
00353 if (si1.shape_num != si2.shape_num) return si1.shape_num < si2.shape_num;
00354
00355
00356 return si1.frame < si2.frame;
00357 }
00358
00359 #define COMPARISON_RETURN(val,op,tab) \
00360 pout << tab"if (si1."#val" != si2."#val") -> (" \
00361 << si1.val << " != " << si2.val << ") -> " \
00362 << (si1.val != si2.val) << std::endl; \
00363 pout << tab"{" << std::endl; \
00364 if (si1.val != si2.val) \
00365 { \
00366 pout << tab"\treturn si1."#val" "#op" si2."#val"; -> (" \
00367 << si1.val << " "#op" " << si2.val << ") -> "\
00368 << (si1.val op si2.val) << std::endl; \
00369 return si1.val op si2.val; \
00370 } \
00371 pout << tab"}" << std::endl;
00372
00373 #define COMPARISON_RETURN_EX(val1,op,val2,tab) \
00374 pout << tab"if ("#val1" != "#val2") -> (" \
00375 << val1 << " != " << val2 << ") -> " \
00376 << (val1 != val2) << std::endl; \
00377 pout << tab"{" << std::endl; \
00378 if (val1 != val2) \
00379 { \
00380 pout << tab"\treturn "#val1" "#op" "#val2"; -> (" \
00381 << val1 << " "#op" " << val2 << ") -> " \
00382 << (val1 op val2) << std::endl; \
00383 return val1 op val2; \
00384 } \
00385 pout << tab"}" << std::endl;
00386
00387 #define COMPARISON_RETURN_TF(val1,op,val2,tf,tab) \
00388 pout << tab "if ("#val1" "#op" "#val2") -> (" \
00389 << val1 << " "#op" " << val2 << ") -> " \
00390 << (val1 op val2) << std::endl; \
00391 pout << tab"{" << std::endl; \
00392 if (val1 op val2) \
00393 { \
00394 pout << tab"\treturn " << tf << std::endl; \
00395 return tf; \
00396 } \
00397 pout << tab"}" << std::endl;
00398
00399 inline bool SortItem::operator<<(const SortItem& si2) const
00400 {
00401 const SortItem& si1 = *this;
00402
00403 if (si2.overlap(si1)) pout << "Overlaping" << std::endl;
00404 else
00405 {
00406 pout << "Not Overlaping" << std::endl;
00407 return false;
00408 }
00409
00410
00411 pout << "if (si1.flat && si2.flat) -> if ("
00412 << si1.flat << " && " << si2.flat << ") -> "
00413 << (si1.flat && si2.flat) << std::endl;
00414 pout << "{" << std::endl;
00415
00416 if (si1.flat && si2.flat)
00417 {
00418
00419
00420 COMPARISON_RETURN(ztop,<,"\t");
00421
00422
00423
00424
00425
00426 COMPARISON_RETURN(anim,<,"\t");
00427
00428
00429
00430 COMPARISON_RETURN(trans,<,"\t");
00431
00432
00433
00434 COMPARISON_RETURN(draw,>,"\t");
00435
00436
00437
00438 COMPARISON_RETURN(solid,>,"\t");
00439
00440
00441
00442 COMPARISON_RETURN(occl,>,"\t");
00443
00444
00445
00446 COMPARISON_RETURN(f32x32,>,"\t");
00447 }
00448
00449 else {
00450 pout << "}" << std::endl;
00451 pout << "else" << std::endl;
00452 pout << "{" << std::endl;
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 COMPARISON_RETURN_TF(si1.ztop,<=,si2.z,true,"\t");
00473 COMPARISON_RETURN_TF(si1.z,>=,si2.ztop,false,"\t");
00474
00475
00476
00477 }
00478 pout << "}" << std::endl;
00479
00480
00481
00482
00483
00484
00485
00486
00487 COMPARISON_RETURN_TF(si1.x,<=,si2.xleft,true,"\t");
00488 COMPARISON_RETURN_TF(si1.xleft,>=,si2.x,false,"\t");
00489
00490
00491
00492
00493 COMPARISON_RETURN_TF(si1.y,<=,si2.yfar,true,"\t");
00494 COMPARISON_RETURN_TF(si1.yfar,>=,si2.y,false,"\t");
00495
00496
00497 COMPARISON_RETURN_TF(si1.ztop,<,si2.z,true,"");
00498 COMPARISON_RETURN_TF(si1.ztop,>,si2.ztop,false,"");
00499
00500
00501
00502
00503 COMPARISON_RETURN_TF((si1.ztop+si1.z)/2,<=,si2.z,true,"");
00504 COMPARISON_RETURN_TF(si1.z,>=,(si2.ztop+si2.z)/2,false,"");
00505
00506
00507
00508
00509 COMPARISON_RETURN_TF((si1.x+si1.xleft)/2,<=,si2.xleft,true,"");
00510 COMPARISON_RETURN_TF(si1.xleft,>=,(si2.x+si2.xleft)/2,false,"");
00511
00512
00513
00514
00515 COMPARISON_RETURN_TF((si1.y+si1.yfar)/2,<=,si2.yfar,true,"");
00516 COMPARISON_RETURN_TF(si1.yfar,>=,(si2.y+si2.yfar)/2,false,"");
00517
00518
00519
00520 COMPARISON_RETURN_EX(si1.x + si1.y,<,si1.x + si2.y,"");
00521
00522
00523
00524 COMPARISON_RETURN_EX(si1.xleft + si1.yfar,<,si1.xleft + si2.yfar,"");
00525
00526
00527
00528 COMPARISON_RETURN(x,<,"");
00529
00530
00531
00532 COMPARISON_RETURN(y,<,"");
00533
00534
00535
00536 COMPARISON_RETURN(shape_num,<,"");
00537
00538
00539
00540 COMPARISON_RETURN(frame,<,"");
00541 return 0;
00542 }
00543
00544
00545
00546
00547
00548 ItemSorter::ItemSorter(int Max_Items) :
00549 shapes(0), surf(0), max_items(Max_Items), num_items(0), num_extra(0), sort_limit(0)
00550 {
00551 if (max_items <= 0) max_items = Max_Items = 2048;
00552 items = new SortItem [max_items];
00553 }
00554
00555 ItemSorter::~ItemSorter()
00556 {
00557 delete [] items;
00558 }
00559
00560 void ItemSorter::BeginDisplayList(RenderSurface *rs,
00561 sint32 camx, sint32 camy, sint32 camz)
00562 {
00563
00564 if (!shapes) shapes = GameData::get_instance()->getMainShapes();
00565
00566
00567 if (num_extra)
00568 {
00569 delete [] items;
00570 max_items += num_extra*2;
00571 items = new SortItem [max_items];
00572 }
00573
00574 surf = rs;
00575 num_items = 0;
00576 order_counter = 0;
00577 num_extra = 0;
00578
00579
00580 cam_sx = (camx - camy)/4;
00581
00582 cam_sy = (camx + camy)/8 - camz;
00583 }
00584
00585 void ItemSorter::AddItem(sint32 x, sint32 y, sint32 z, uint32 shape_num, uint32 frame_num, uint32 flags, uint32 ext_flags, uint16 item_num)
00586 {
00587
00588
00589
00590
00591
00592 if (num_items >= max_items)
00593 {
00594 num_extra++;
00595 return;
00596 }
00597
00598 SortItem *si = items+num_items;
00599
00600 si->item_num = item_num;
00601 si->shape = shapes->getShape(shape_num);
00602 si->shape_num = shape_num;
00603 si->frame = frame_num;
00604 ShapeFrame *frame = si->shape->getFrame(si->frame);
00605 if (!frame) {
00606 perr << "Invalid shape: " << si->shape_num << "," << si->frame
00607 << std::endl;
00608 return;
00609 }
00610
00611 ShapeInfo *info = shapes->getShapeInfo(shape_num);
00612
00613
00614
00615
00616
00617 sint32 xd, yd, zd;
00618 si->flags = flags;
00619 si->ext_flags = ext_flags;
00620
00621
00622 if (si->flags & Item::FLG_FLIPPED)
00623 {
00624 xd = info->y * 32;
00625 yd = info->x * 32;
00626 }
00627 else
00628 {
00629 xd = info->x * 32;
00630 yd = info->y * 32;
00631 }
00632
00633 zd = info->z * 8;
00634
00635
00636 si->x = x; si->y = y; si->z = z;
00637 si->xleft = si->x - xd;
00638 si->yfar = si->y - yd;
00639 si->ztop = si->z + zd;
00640
00641
00642 si->sxleft = (si->xleft - si->y)/4 - cam_sx;
00643
00644 si->sxright= (si->x - si->yfar)/4 - cam_sx;
00645
00646
00647 si->sxtop = (si->xleft - si->yfar)/4 - cam_sx;
00648
00649 si->sytop = (si->xleft + si->yfar)/8 - si->ztop - cam_sy;
00650
00651
00652 si->sxbot = (si->x - si->y)/4 - cam_sx;
00653
00654 si->sybot = (si->x + si->y)/8 - si->z - cam_sy;
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 si->sx = si->sxbot - frame->xoff;
00666 si->sy = si->sybot - frame->yoff;
00667 si->sx2 = si->sx + frame->width;
00668 si->sy2 = si->sy + frame->height;
00669
00670
00671 si->clipped = surf->CheckClipped(Rect (si->sx,si->sy, frame->width, frame->height));
00672 if (si->clipped < 0) return;
00673
00674
00675 si->f32x32 = xd==128 && yd==128;
00676 si->flat = zd == 0;
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 {
00691 si->draw = info->is_draw();
00692 si->solid = info->is_solid();
00693 si->occl = info->is_occl() && !(si->ext_flags & Item::FLG_INVISIBLE);
00694 si->roof = info->is_roof();
00695 si->noisy = info->is_noisy();
00696 si->anim = info->animtype != 0;
00697 si->trans = info->is_translucent();
00698 si->fixed = info->is_fixed();
00699 si->land = info->is_land();
00700 }
00701
00702 si->occluded = false;
00703 si->order = -1;
00704
00705
00706
00707
00708
00709 si->depends.erase(si->depends.begin(), si->depends.end());
00710
00711
00712
00713
00714 for (SortItem * si2 = items; si2 != si; ++si2)
00715 {
00716
00717 if (si2->occluded || !si->overlap(*si2)) continue;
00718
00719
00720 if (*si < *si2)
00721 {
00722
00723 if (si2->occl && si2->occludes(*si))
00724 {
00725
00726 si->occluded = true;
00727 break;
00728 }
00729
00730
00731 si2->depends.push_back(si);
00732 }
00733 else
00734 {
00735
00736 if (si->occl && si->occludes(*si2)) si2->occluded = true;
00737
00738 else si->depends.push_back(si2);
00739 }
00740 }
00741
00742
00743 num_items ++;
00744 }
00745
00746 void ItemSorter::AddItem(Item *add)
00747 {
00748 #if 0
00749
00750 sint32 x, y, z;
00751 add->getLerped(x, y, z);
00752 AddItem(x,y,z,add->getShape(), add->getFrame(), add->getFlags(), add->getObjId());
00753
00754 #else
00755
00756
00757
00758
00759
00760
00761 if (num_items >= max_items)
00762 {
00763 num_extra++;
00764 return;
00765 }
00766
00767 SortItem *si = items+num_items;
00768
00769 si->item_num = add->getObjId();
00770 si->shape = add->getShapeObject();
00771 si->shape_num = add->getShape();
00772 si->frame = add->getFrame();
00773 ShapeFrame *frame = si->shape->getFrame(si->frame);
00774 if (!frame) {
00775 perr << "Invalid shape: " << si->shape_num << "," << si->frame
00776 << std::endl;
00777 return;
00778 }
00779
00780 ShapeInfo *info = add->getShapeInfo();
00781
00782
00783
00784
00785
00786 sint32 xd, yd, zd;
00787 si->flags = add->getFlags();
00788 si->ext_flags = add->getExtFlags();
00789
00790
00791 if (si->flags & Item::FLG_FLIPPED)
00792 {
00793 xd = info->y * 32;
00794 yd = info->x * 32;
00795 }
00796 else
00797 {
00798 xd = info->x * 32;
00799 yd = info->y * 32;
00800 }
00801
00802 zd = info->z * 8;
00803
00804
00805 add->getLerped(si->x, si->y, si->z);
00806 si->xleft = si->x - xd;
00807 si->yfar = si->y - yd;
00808 si->ztop = si->z + zd;
00809
00810
00811 si->sxleft = (si->xleft - si->y)/4 - cam_sx;
00812
00813 si->sxright= (si->x - si->yfar)/4 - cam_sx;
00814
00815
00816 si->sxtop = (si->xleft - si->yfar)/4 - cam_sx;
00817
00818 si->sytop = (si->xleft + si->yfar)/8 - si->ztop - cam_sy;
00819
00820
00821 si->sxbot = (si->x - si->y)/4 - cam_sx;
00822
00823 si->sybot = (si->x + si->y)/8 - si->z - cam_sy;
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 si->sx = si->sxbot - frame->xoff;
00835 si->sy = si->sybot - frame->yoff;
00836 si->sx2 = si->sx + frame->width;
00837 si->sy2 = si->sy + frame->height;
00838
00839
00840 si->clipped = surf->CheckClipped(Rect (si->sx,si->sy, frame->width, frame->height));
00841 if (si->clipped < 0) return;
00842
00843
00844 si->f32x32 = xd==128 && yd==128;
00845 si->flat = zd == 0;
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 {
00860 si->draw = info->is_draw();
00861 si->solid = info->is_solid();
00862 si->occl = info->is_occl() && !(si->flags & Item::FLG_INVISIBLE);
00863 si->roof = info->is_roof();
00864 si->noisy = info->is_noisy();
00865 si->anim = info->animtype != 0;
00866 si->trans = info->is_translucent();
00867 si->fixed = info->is_fixed();
00868 si->land = info->is_land();
00869 }
00870
00871 si->occluded = false;
00872 si->order = -1;
00873
00874
00875
00876
00877
00878 si->depends.erase(si->depends.begin(), si->depends.end());
00879
00880
00881
00882
00883 for (SortItem * si2 = items; si2 != si; ++si2)
00884 {
00885
00886 if (si2->occluded || !si->overlap(*si2)) continue;
00887
00888
00889 if (*si < *si2)
00890 {
00891
00892 if (si2->occl && si2->occludes(*si))
00893 {
00894
00895 si->occluded = true;
00896 break;
00897 }
00898
00899
00900 si2->depends.push_back(si);
00901 }
00902 else
00903 {
00904
00905 if (si->occl && si->occludes(*si2)) si2->occluded = true;
00906
00907 else si->depends.push_back(si2);
00908 }
00909 }
00910
00911
00912 num_items ++;
00913 #endif
00914 }
00915
00916 SortItem *prev = 0;
00917
00918 void ItemSorter::PaintDisplayList(bool item_highlight)
00919 {
00920 prev = 0;
00921 SortItem *it = items;
00922 SortItem *end = items + num_items;
00923 order_counter = 0;
00924 while (it != end)
00925 {
00926 if (it->order == -1) if (PaintSortItem(it)) return;
00927 ++it;
00928 }
00929
00930
00931 if (item_highlight)
00932 {
00933 it = items;
00934 while (it != end)
00935 {
00936 if (!(it->flags & (Item::FLG_DISPOSABLE|Item::FLG_FAST_ONLY)) && !it->fixed )
00937 {
00938 surf->PaintHighlightInvis(it->shape,
00939 it->frame,
00940 it->sxbot,
00941 it->sybot,
00942 it->trans,
00943 (it->flags&Item::FLG_FLIPPED)!=0, 0x1f00ffff);
00944 }
00945
00946 ++it;
00947 }
00948
00949 }
00950 }
00951
00952 bool ItemSorter::PaintSortItem(SortItem *si)
00953 {
00954
00955 if (si->occluded) return false;
00956
00957
00958 si->order = -2;
00959
00960
00961 SortItemVector::iterator it = si->depends.begin();
00962 SortItemVector::iterator end = si->depends.end();
00963 while (it != end)
00964 {
00965
00966
00967
00968 if ((*it)->order == -1) if (PaintSortItem((*it))) return true;
00969
00970 ++it;
00971 }
00972
00973
00974 si->order = order_counter;
00975 order_counter++;
00976
00977
00978
00979
00980
00981 if (si->ext_flags & Item::EXT_HIGHLIGHT && (si->ext_flags & Item::EXT_TRANSPARENT || si->ext_flags & Item::EXT_TRANSPARENT))
00982 surf->PaintHighlightInvis(si->shape, si->frame, si->sxbot, si->sybot, si->trans, (si->flags&Item::FLG_FLIPPED)!=0, 0x7F00007F);
00983 if (si->ext_flags & Item::EXT_HIGHLIGHT)
00984 surf->PaintHighlight(si->shape, si->frame, si->sxbot, si->sybot, si->trans, (si->flags&Item::FLG_FLIPPED)!=0, 0x7F00007F);
00985 else if (si->ext_flags & Item::EXT_TRANSPARENT)
00986 surf->PaintInvisible(si->shape, si->frame, si->sxbot, si->sybot, si->trans, (si->flags&Item::FLG_FLIPPED)!=0);
00987 else if (si->flags & Item::FLG_FLIPPED)
00988 surf->PaintMirrored(si->shape, si->frame, si->sxbot, si->sybot, si->trans);
00989 else if (si->trans)
00990 surf->PaintTranslucent(si->shape, si->frame, si->sxbot, si->sybot);
00991 else if (!si->clipped)
00992 surf->PaintNoClip(si->shape, si->frame, si->sxbot, si->sybot);
00993 else
00994 surf->Paint(si->shape, si->frame, si->sxbot, si->sybot);
00995
00996
00997
00998
00999
01000 if (si->shape_num == 1 && si->item_num == 1) {
01001 MainActor* av = getMainActor();
01002 const WeaponOverlayFrame* wo_frame = 0;
01003 uint32 wo_shapenum;
01004 av->getWeaponOverlay(wo_frame, wo_shapenum);
01005 if (wo_frame) {
01006 Shape* wo_shape = GameData::get_instance()->getMainShapes()->getShape(wo_shapenum);
01007 surf->Paint(wo_shape, wo_frame->frame,
01008 si->sxbot + wo_frame->xoff,
01009 si->sybot + wo_frame->yoff);
01010 }
01011 }
01012
01013 if (sort_limit) {
01014 if (order_counter == sort_limit) {
01015 static uint32 previt = 0;
01016 int x1 = si->xleft;
01017 int y1 = si->yfar;
01018 int z2 = si->ztop;
01019 if (!previt || previt != si->item_num)
01020 {
01021 previt = si->item_num;
01022 pout << si->shape_num << ":" << si->frame << " (" << x1 << "," << y1 << "," << si->z << ") (" << si->x << "," << si->y << "," << z2 << ")" << std::endl;
01023
01024 if (prev) *prev << *si;
01025 }
01026 return true;
01027 }
01028 prev = si;
01029 }
01030
01031 return false;
01032 }
01033
01034 bool ItemSorter::NullPaintSortItem(SortItem *si)
01035 {
01036
01037 if (si->occluded) return false;
01038
01039
01040 si->order = -2;
01041
01042
01043 SortItemVector::iterator it = si->depends.begin();
01044 SortItemVector::iterator end = si->depends.end();
01045 while (it != end)
01046 {
01047
01048
01049
01050
01051 if ((*it)->order == -1) if (NullPaintSortItem((*it))) return true;
01052
01053 ++it;
01054 }
01055
01056
01057 si->order = order_counter;
01058 order_counter++;
01059
01060 return false;
01061 }
01062
01063 uint16 ItemSorter::Trace(sint32 x, sint32 y, HitFace* face, bool item_highlight)
01064 {
01065 SortItem *it;
01066 SortItem *end;
01067 SortItem *selected;
01068
01069 if (!order_counter)
01070 {
01071 it = items;
01072 end = items + num_items;
01073 order_counter = 0;
01074 while (it != end)
01075 {
01076 if (it->order == -1) if (NullPaintSortItem(it)) break;
01077
01078 ++it;
01079 }
01080 }
01081
01082
01083 selected = 0;
01084
01085 if (item_highlight)
01086 {
01087 it = items + num_items;
01088 selected = 0;
01089 end = items;
01090
01091 while (it-- != end)
01092 {
01093 if (!(it->flags & (Item::FLG_DISPOSABLE|Item::FLG_FAST_ONLY)) && !it->fixed )
01094 {
01095
01096 if (!it->item_num) continue;
01097
01098
01099 if (x < it->sx || x >= it->sx2 || y < it->sy || y >= it->sy2) continue;
01100
01101
01102 ShapeFrame *frame = it->shape->getFrame(it->frame);
01103 assert(frame);
01104
01105
01106 if (it->flags & Item::FLG_FLIPPED)
01107 {
01108 if (!frame->hasPoint(it->sxbot-x, y-it->sybot)) continue;
01109 }
01110 else
01111 {
01112 if (!frame->hasPoint(x-it->sxbot, y-it->sybot)) continue;
01113 }
01114
01115
01116 selected = it;
01117 }
01118 }
01119
01120 }
01121
01122
01123
01124
01125 it = items;
01126 end = items + num_items;
01127
01128 if (!selected) for (;it != end;++it)
01129 {
01130 if (!it->item_num) continue;
01131
01132
01133 if (x < it->sx || x >= it->sx2 || y < it->sy || y >= it->sy2) continue;
01134
01135
01136 ShapeFrame *frame = it->shape->getFrame(it->frame);
01137 assert(frame);
01138
01139
01140 if (it->flags & Item::FLG_FLIPPED)
01141 {
01142 if (!frame->hasPoint(it->sxbot-x, y-it->sybot)) continue;
01143 }
01144 else
01145 {
01146 if (!frame->hasPoint(x-it->sxbot, y-it->sybot)) continue;
01147 }
01148
01149
01150 if (!selected || (it->order > selected->order)) selected = it;
01151 }
01152
01153 if (selected) {
01154
01155 if (face) {
01156
01157 if (selected->ztop == selected->z) {
01158 *face = Z_FACE;
01159 } else {
01160
01161
01162
01163 sint32 RNTx = selected->sxbot;
01164 sint32 RNTy = selected->sybot - selected->ztop + selected->z;
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180 if (2 * (y - RNTy) <= (x - RNTx) &&
01181 2 * (y - RNTy) < (RNTx - x))
01182 *face = Z_FACE;
01183 else if (x > RNTx)
01184 *face = X_FACE;
01185 else
01186 *face = Y_FACE;
01187 }
01188 }
01189
01190 return selected->item_num;
01191 }
01192
01193 return 0;
01194 }
01195
01196
01197