struct HS_RECT_NAME { HS_RECT_TYPE fLeft, fTop, fRight, fBottom; HS_RECT_TYPE Width() const { return fRight - fLeft; } HS_RECT_TYPE Height() const { return fBottom - fTop; } hsBool IsEmpty() const { return fLeft >= fRight || fTop >= fBottom; } void SetEmpty() { fLeft = fTop = fRight = fBottom = 0; } HS_RECT_NAME* Set(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) { fLeft = left; fTop = top; fRight = right; fBottom = bottom; return this; } HS_RECT_NAME* Set(const HS_RECT_POINT* p1, const HS_RECT_POINT* p2) { if (p1->fX < p2->fX) { fLeft = p1->fX; fRight = p2->fX; } else { fLeft = p2->fX; fRight = p1->fX; } if (p1->fY < p2->fY) { fTop = p1->fY; fBottom = p2->fY; } else { fTop = p2->fY; fBottom = p1->fY; } return this; } HS_RECT_NAME* Set(UInt32 count, const HS_RECT_POINT pts[]) { if (count > 0) { fLeft = fRight = pts[0].fX; fTop = fBottom = pts[0].fY; (void)this->Union(count - 1, &pts[1]); } return this; } hsBool Contains(HS_RECT_TYPE x, HS_RECT_TYPE y) const { return x >= fLeft && x < fRight && y >= fTop && y < fBottom; } hsBool Contains(const HS_RECT_POINT* p) const { return this->Contains(p->fX, p->fY); } hsBool Contains(const HS_RECT_NAME* r) const { return fLeft <= r->fLeft && fTop <= r->fTop && fRight >= r->fRight && fBottom >= r->fBottom; } hsBool Contains(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) const { return fLeft <= left && fTop <= top && fRight >= right && fBottom >= bottom; } HS_RECT_NAME* Offset(HS_RECT_TYPE dx, HS_RECT_TYPE dy) { fLeft += dx; fTop += dy; fRight += dx; fBottom += dy; return this; } HS_RECT_NAME* MoveTo(HS_RECT_TYPE x, HS_RECT_TYPE y) { this->fRight += x - this->fLeft; this->fBottom += y - this->fTop; this->fLeft = x; this->fTop = y; return this; } HS_RECT_NAME* Inset(HS_RECT_TYPE dx, HS_RECT_TYPE dy) { fLeft += dx; fRight -= dx; fTop += dy; fBottom -= dy; return this; } HS_RECT_NAME* UnionX(HS_RECT_TYPE x) { if (x < fLeft) fLeft = x; else if (x > fRight) fRight = x; return this; } HS_RECT_NAME* UnionY(HS_RECT_TYPE y) { if (y < fTop) fTop = y; else if (y > fBottom) fBottom = y; return this; } HS_RECT_NAME* Union(const HS_RECT_NAME* r) { if (r->fLeft < fLeft) fLeft = r->fLeft; if (r->fTop < fTop) fTop = r->fTop; if (r->fRight > fRight) fRight = r->fRight; if (r->fBottom > fBottom) fBottom = r->fBottom; return this; } HS_RECT_NAME* Union(const HS_RECT_POINT* p) { if (p->fX < fLeft) fLeft = p->fX; if (p->fX > fRight) fRight = p->fX; if (p->fY < fTop) fTop = p->fY; if (p->fY> fBottom) fBottom = p->fY; return this; } HS_RECT_NAME* Union(UInt32 count, const HS_RECT_POINT p[]) { HS_RECT_TYPE left = this->fLeft; HS_RECT_TYPE top = this->fTop; HS_RECT_TYPE right = this->fRight; HS_RECT_TYPE bottom = this->fBottom; for (; count > 0; ++p, --count) { HS_RECT_TYPE value = p->fX; if (value < left) left = value; else if (value > right) right = value; value = p->fY; if (value < top) top = value; else if (value > bottom) bottom = value; } return this->Set(left, top, right, bottom); } #if 0 // Havok reeks friend int operator==(const HS_RECT_NAME& a, const HS_RECT_NAME& b) { return a.fLeft == b.fLeft && a.fTop == b.fTop && a.fRight == b.fRight && a.fBottom == b.fBottom; } friend int operator!=(const HS_RECT_NAME& a, const HS_RECT_NAME& b) { return !(a == b); } #else // Havok reeks int operator==(const HS_RECT_NAME& aa) const { return aa.fLeft == fLeft && aa.fTop == fTop && aa.fRight == fRight && aa.fBottom == fBottom; } int operator!=(const HS_RECT_NAME& aa) const { return !(aa == *this); } #endif // Havok reeks // Intersect Test friend int operator&&(const HS_RECT_NAME& a, const HS_RECT_NAME& b) { return a.fLeft < b.fRight && a.fRight > b.fLeft && a.fTop < b.fBottom && a.fBottom > b.fTop; } hsBool Intersect(const HS_RECT_NAME* r) { return this->Intersect(r->fLeft, r->fTop, r->fRight, r->fBottom); } hsBool Intersect(HS_RECT_TYPE left, HS_RECT_TYPE top, HS_RECT_TYPE right, HS_RECT_TYPE bottom) { if (left < fRight && top < fBottom && fLeft < right && fTop < bottom) { if (left > fLeft) fLeft = left; if (top > fTop) fTop = top; if (right < fRight) fRight = right; if (bottom < fBottom) fBottom = bottom; return true; } return false; } hsBool Intersect(const HS_RECT_NAME* a, const HS_RECT_NAME* b) { if (a->fLeft < b->fRight && a->fTop < b->fBottom && b->fLeft < a->fRight && b->fTop < a->fBottom) { *this = *b; if (a->fLeft > fLeft) fLeft = a->fLeft; if (a->fTop > fTop) fTop = a->fTop; if (a->fRight < fRight) fRight = a->fRight; if (a->fBottom < fBottom) fBottom = a->fBottom; return true; } return false; // "this" is not changed } HS_RECT_POINT* ToQuad(HS_RECT_POINT quad[4]) const { quad[0].fX = fLeft; quad[0].fY = fTop; quad[1].fX = fRight; quad[1].fY = fTop; quad[2].fX = fRight; quad[2].fY = fBottom; quad[3].fX = fLeft; quad[3].fY = fBottom; return quad; } hsBool CornerTest(const HS_RECT_NAME* area, HS_RECT_POINT* hitPt = nil, HS_RECT_POINT* oppositePt = nil) const { if (area->Contains(fLeft, fTop)) { if (hitPt) hitPt->Set(fLeft, fTop); if (oppositePt) oppositePt->Set(fRight, fBottom); return true; } if (area->Contains(fLeft, fBottom)) { if (hitPt) hitPt->Set(fLeft, fBottom); if (oppositePt) oppositePt->Set(fRight, fTop); return true; } if (area->Contains(fRight, fTop)) { if (hitPt) hitPt->Set(fRight, fTop); if (oppositePt) oppositePt->Set(fLeft, fBottom); return true; } if (area->Contains(fRight, fBottom)) { if (hitPt) hitPt->Set(fRight, fBottom); if (oppositePt) oppositePt->Set(fLeft, fTop); return true; } return false; } hsBool CornerTest(HS_RECT_POINT* pt, HS_RECT_TYPE tolerance, HS_RECT_POINT* hitPt = nil, HS_RECT_POINT* oppositePt = nil) const { HS_RECT_NAME area = { pt->fX - tolerance, pt->fY - tolerance, pt->fX + tolerance, pt->fY + tolerance }; return this->CornerTest(&area, hitPt, oppositePt); } #if !(HS_RECT_EXTEND) }; #endif #undef HS_RECT_NAME #undef HS_RECT_POINT #undef HS_RECT_TYPE #undef HS_RECT_EXTEND