diff --git a/CMakeLists.txt b/CMakeLists.txt index 86c2a6090..9a05c096d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,16 @@ set(OC_CLONK_SOURCES src/C4GraphicsSystem.cpp src/C4GraphicsSystem.h src/c4group/C4Components.h + src/c4group/C4ComponentHost.cpp + src/c4group/C4ComponentHost.h src/c4group/C4Extra.cpp src/c4group/C4Extra.h src/c4group/C4Group.cpp src/c4group/C4Group.h src/c4group/C4GroupSet.cpp src/c4group/C4GroupSet.h + src/c4group/C4LangStringTable.cpp + src/c4group/C4LangStringTable.h src/c4group/C4Language.cpp src/c4group/C4Language.h src/c4group/C4Update.cpp @@ -217,12 +221,8 @@ set(OC_CLONK_SOURCES src/gui/C4UserMessages.h src/gui/C4Viewport.cpp src/gui/C4Viewport.h - src/lib/C4ComponentHost.cpp - src/lib/C4ComponentHost.h src/lib/C4InputValidation.cpp src/lib/C4InputValidation.h - src/lib/C4LangStringTable.cpp - src/lib/C4LangStringTable.h src/lib/C4LogBuf.cpp src/lib/C4LogBuf.h src/lib/C4Log.cpp @@ -231,6 +231,8 @@ set(OC_CLONK_SOURCES src/lib/C4NameList.h src/lib/C4Random.cpp src/lib/C4Random.h + src/lib/C4Rect.cpp + src/lib/C4Rect.h src/lib/C4RTF.cpp src/lib/C4RTF.H src/lib/C4Stat.cpp diff --git a/Makefile.am b/Makefile.am index 4f13078d8..df45ae279 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,8 @@ bin_PROGRAMS = clonk EXTRA_PROGRAMS = tstc4netio puncher c4group gunzip4c4group +noinst_LIBRARIES = lib.a + # Some defines and warning options if RECENT_GCC GCC_FLAGS = -pipe @@ -83,7 +85,56 @@ WARNING_FLAGS += -Winvalid-pch endif +lib_a_SOURCES = \ +src/lib/C4InputValidation.cpp \ +src/lib/C4InputValidation.h \ +src/lib/C4LogBuf.cpp \ +src/lib/C4LogBuf.h \ +src/lib/C4Random.cpp \ +src/lib/C4Random.h \ +src/lib/C4Rect.cpp \ +src/lib/C4Rect.h \ +src/lib/C4RTF.cpp \ +src/lib/C4RTF.H \ +src/lib/C4Stat.cpp \ +src/lib/C4Stat.h \ +src/lib/Fixed.cpp \ +src/lib/Fixed.h \ +src/lib/PathFinder.cpp \ +src/lib/PathFinder.h \ +src/lib/Standard.cpp \ +src/lib/Standard.h \ +src/lib/StdAdaptors.h \ +src/lib/StdBase64.cpp \ +src/lib/StdBase64.h \ +src/lib/StdBuf.cpp \ +src/lib/StdBuf.h \ +src/lib/StdColors.h \ +src/lib/StdCompiler.cpp \ +src/lib/StdCompiler.h \ +src/lib/StdMarkup.cpp \ +src/lib/StdMarkup.h \ +src/lib/StdResStr2.cpp \ +src/lib/StdResStr2.h \ +src/lib/StdResStr.h \ +src/lib/texture/C4Facet.cpp \ +src/lib/texture/C4FacetEx.cpp \ +src/lib/texture/C4FacetEx.h \ +src/lib/texture/C4Facet.h \ +src/lib/texture/C4Surface.cpp \ +src/lib/texture/C4SurfaceFile.cpp \ +src/lib/texture/C4SurfaceFile.h \ +src/lib/texture/C4Surface.h \ +src/lib/texture/StdPNG.cpp \ +src/lib/texture/StdPNG.h + clonk_SOURCES = \ +src/lib/C4Log.cpp \ +src/lib/C4Log.h \ +src/lib/C4NameList.cpp \ +src/lib/C4NameList.h \ +src/lib/texture/C4GraphicsResource.cpp \ +src/lib/texture/C4GraphicsResource.h \ src/C4Application.cpp \ src/C4Application.h \ src/C4FullScreen.cpp \ @@ -92,7 +143,11 @@ src/C4Game.cpp \ src/C4Game.h \ src/C4GraphicsSystem.cpp \ src/C4GraphicsSystem.h \ +src/c4group/C4LangStringTable.cpp \ +src/c4group/C4LangStringTable.h \ src/c4group/C4Components.h \ +src/c4group/C4ComponentHost.cpp \ +src/c4group/C4ComponentHost.h \ src/c4group/C4Extra.cpp \ src/c4group/C4Extra.h \ src/c4group/C4Group.cpp \ @@ -292,55 +347,6 @@ src/gui/C4UpperBoard.h \ src/gui/C4UserMessages.h \ src/gui/C4Viewport.cpp \ src/gui/C4Viewport.h \ -src/lib/C4ComponentHost.cpp \ -src/lib/C4ComponentHost.h \ -src/lib/C4InputValidation.cpp \ -src/lib/C4InputValidation.h \ -src/lib/C4LangStringTable.cpp \ -src/lib/C4LangStringTable.h \ -src/lib/C4LogBuf.cpp \ -src/lib/C4LogBuf.h \ -src/lib/C4Log.cpp \ -src/lib/C4Log.h \ -src/lib/C4NameList.cpp \ -src/lib/C4NameList.h \ -src/lib/C4Random.cpp \ -src/lib/C4Random.h \ -src/lib/C4RTF.cpp \ -src/lib/C4RTF.H \ -src/lib/C4Stat.cpp \ -src/lib/C4Stat.h \ -src/lib/Fixed.cpp \ -src/lib/Fixed.h \ -src/lib/PathFinder.cpp \ -src/lib/PathFinder.h \ -src/lib/Standard.cpp \ -src/lib/Standard.h \ -src/lib/StdAdaptors.h \ -src/lib/StdBase64.cpp \ -src/lib/StdBase64.h \ -src/lib/StdBuf.cpp \ -src/lib/StdBuf.h \ -src/lib/StdColors.h \ -src/lib/StdCompiler.cpp \ -src/lib/StdCompiler.h \ -src/lib/StdMarkup.cpp \ -src/lib/StdMarkup.h \ -src/lib/StdResStr2.cpp \ -src/lib/StdResStr2.h \ -src/lib/StdResStr.h \ -src/lib/texture/C4Facet.cpp \ -src/lib/texture/C4FacetEx.cpp \ -src/lib/texture/C4FacetEx.h \ -src/lib/texture/C4Facet.h \ -src/lib/texture/C4GraphicsResource.cpp \ -src/lib/texture/C4GraphicsResource.h \ -src/lib/texture/C4Surface.cpp \ -src/lib/texture/C4SurfaceFile.cpp \ -src/lib/texture/C4SurfaceFile.h \ -src/lib/texture/C4Surface.h \ -src/lib/texture/StdPNG.cpp \ -src/lib/texture/StdPNG.h \ src/network/C4Client.cpp \ src/network/C4Client.h \ src/network/C4GameControlNetwork.cpp \ @@ -483,6 +489,7 @@ clonk_SOURCES += src/platform/StdGtkWindow.cpp src/platform/StdGtkWindow.h endif clonk_LDADD = \ + lib.a \ $(LIBICONV) \ $(GTK_LIBS) \ $(FREETYPE_LIBS) \ diff --git a/src/lib/C4ComponentHost.cpp b/src/c4group/C4ComponentHost.cpp similarity index 100% rename from src/lib/C4ComponentHost.cpp rename to src/c4group/C4ComponentHost.cpp diff --git a/src/lib/C4ComponentHost.h b/src/c4group/C4ComponentHost.h similarity index 100% rename from src/lib/C4ComponentHost.h rename to src/c4group/C4ComponentHost.h diff --git a/src/lib/C4LangStringTable.cpp b/src/c4group/C4LangStringTable.cpp similarity index 99% rename from src/lib/C4LangStringTable.cpp rename to src/c4group/C4LangStringTable.cpp index ccbbbdf5d..127ece6b6 100644 --- a/src/lib/C4LangStringTable.cpp +++ b/src/c4group/C4LangStringTable.cpp @@ -21,6 +21,7 @@ #include "C4Include.h" #include "C4LangStringTable.h" +#include "C4InputValidation.h" struct C4StringTableEntry { diff --git a/src/lib/C4LangStringTable.h b/src/c4group/C4LangStringTable.h similarity index 100% rename from src/lib/C4LangStringTable.h rename to src/c4group/C4LangStringTable.h diff --git a/src/game/object/C4Shape.cpp b/src/game/object/C4Shape.cpp index 7ac7a7b44..269a4cca2 100644 --- a/src/game/object/C4Shape.cpp +++ b/src/game/object/C4Shape.cpp @@ -50,152 +50,6 @@ C4Shape::C4Shape() Default(); } -void C4Rect::Default() - { - x=y=Wdt=Hgt=0; - } - -void C4Rect::CompileFunc(StdCompiler *pComp) - { - pComp->Value(mkDefaultAdapt(x, 0)); pComp->Seperator(); - pComp->Value(mkDefaultAdapt(y, 0)); pComp->Seperator(); - pComp->Value(mkDefaultAdapt(Wdt, 0)); pComp->Seperator(); - pComp->Value(mkDefaultAdapt(Hgt, 0)); - } - -void C4TargetRect::Default() - { - C4Rect::Default(); - tx=ty=0; - } - -void C4TargetRect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY) - { - C4Rect::Set(iX,iY,iWdt,iHgt); - tx=iTX; ty=iTY; - } - -bool C4TargetRect::ClipBy(C4TargetRect &rClip) - { - int32_t d; - // clip left - if ((d = x - rClip.x) < 0) { Wdt += d; x = rClip.x; } else tx += d; - // clip top - if ((d = y - rClip.y) < 0) { Hgt += d; y = rClip.y; } else ty += d; - // clip right - if ((d = (x+Wdt - rClip.x-rClip.Wdt)) > 0) Wdt -= d; - // clip bottom - if ((d = (y+Hgt - rClip.y-rClip.Hgt)) > 0) Hgt -= d; - // check validity - if (Wdt <= 0 || Hgt <= 0) return false; - // add target pos - tx += rClip.tx; - ty += rClip.ty; - // done - return true; - } - -void C4TargetRect::Set(const C4TargetFacet &rSrc) - { - // copy members - x=rSrc.X; y=rSrc.Y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; tx=rSrc.TargetX; ty=rSrc.TargetY; - } - -void C4TargetRect::CompileFunc(StdCompiler *pComp) - { - C4Rect::CompileFunc(pComp); pComp->Seperator(); - pComp->Value(mkDefaultAdapt(tx,0)); pComp->Seperator(); - pComp->Value(mkDefaultAdapt(ty,0)); - } - -void C4Rect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt) - { - x=iX; y=iY; Wdt=iWdt; Hgt=iHgt; - } - -BOOL C4Rect::Overlap(C4Rect &rTarget) - { - if (x+Wdt<=rTarget.x) return FALSE; - if (x>=rTarget.x+rTarget.Wdt) return FALSE; - if (y+Hgt<=rTarget.y) return FALSE; - if (y>=rTarget.y+rTarget.Hgt) return FALSE; - return TRUE; - } - -void C4Rect::Intersect(const C4Rect &r2) - { - // Narrow bounds - if (r2.x > x) - if (r2.x + r2.Wdt < x + Wdt) - { x = r2.x; Wdt = r2.Wdt; } - else - { Wdt -= (r2.x - x); x = r2.x; } - else - if (r2.x + r2.Wdt < x + Wdt) - Wdt = r2.x + r2.Wdt - x; - if (r2.y > y) - if (r2.y + r2.Hgt < y + Hgt) - { y = r2.y; Hgt = r2.Hgt; } - else - { Hgt -= (r2.y - y); y = r2.y; } - else - if (r2.y + r2.Hgt < y + Hgt) - Hgt = r2.y + r2.Hgt - y; - // Degenerated? Will happen when the two rects don't overlap - if (Wdt < 0) Wdt = 0; - if (Hgt < 0) Hgt = 0; - } - -bool C4Rect::IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2) - { - // Easy cases first - if(Contains(iX, iY)) return true; - if(Contains(iX2, iY2)) return true; - if(iX < x && iX2 < x) return false; - if(iY < y && iY2 < y) return false; - if(iX >= x+Wdt && iX2 >= x+Wdt) return false; - if(iY >= y+Hgt && iY2 >= y+Hgt) return false; - // check some special cases - if (iX == iX2 || iY == iY2) return true; - // Check intersection left/right - int32_t iXI, iYI; - iXI = (iX < x ? x : x+Wdt); - iYI = iY + (iY2 - iY) * (iXI - iX) / (iX2 - iX); - if(iYI >= y && iYI < y+Hgt) return true; - // Check intersection up/down - iYI = (iY < y ? y : y+Hgt); - iXI = iX + (iX2 - iX) * (iYI - iY) / (iY2 - iY); - return iXI >= x && iXI < x+Wdt; - } - -void C4Rect::Add(const C4Rect &r2) - { - // Null? Don't do anything - if (!r2.Wdt || !r2.Hgt) return; - if (!Wdt || !Hgt) - { - *this = r2; - return; - } - // Expand bounds - if (r2.x < x) - if (r2.x + r2.Wdt > x + Wdt) - { x = r2.x; Wdt = r2.Wdt; } - else - { Wdt += (x - r2.x); x = r2.x; } - else - if (r2.x + r2.Wdt > x + Wdt) - Wdt = r2.x + r2.Wdt - x; - if (r2.y < y) - if (r2.y + r2.Hgt > y + Hgt) - { y = r2.y; Hgt = r2.Hgt; } - else - { Hgt += (y - r2.y); y = r2.y; } - else - if (r2.y + r2.Hgt > y + Hgt) - Hgt = r2.y + r2.Hgt - y; - } - void C4Shape::Clear() { ZeroMem(this, sizeof (C4Shape)); @@ -679,95 +533,3 @@ void C4Shape::CompileFunc(StdCompiler *pComp, bool fRuntime) pComp->Value(mkNamingAdapt( iAttachVtx, "AttachVtx", 0 )); } } - - - -// ---- C4RectList ---- - - -void C4RectList::ClipByRect(const C4Rect &rClip) - { - // split up all rectangles - for (int32_t i = 0; i < GetCount(); ++i) - { - C4Rect *pTarget = &Get(i); - // any overlap? - if (rClip.x+rClip.Wdt <= pTarget->x) continue; - if (rClip.y+rClip.Hgt <= pTarget->y) continue; - if (rClip.x >= pTarget->x+pTarget->Wdt) continue; - if (rClip.y >= pTarget->y+pTarget->Hgt) continue; - // okay; split up rectangle - // first split will just reduce the target rectangle size - // if more splits are done, additional rectangles need to be added - int32_t iSplitCount = 0, iOver; C4Rect rcThis(*pTarget); - // clipped by right side - if ((iOver=rcThis.x+rcThis.Wdt-rClip.x-rClip.Wdt)>0) - { - pTarget->x += pTarget->Wdt - iOver; pTarget->Wdt = iOver; rcThis.Wdt -= iOver; - ++iSplitCount; - } - // clipped by obttom side - if ((iOver=rcThis.y+rcThis.Hgt-rClip.y-rClip.Hgt)>0) - { - if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } - pTarget->y += pTarget->Hgt - iOver; pTarget->Hgt = iOver; rcThis.Hgt -= iOver; - ++iSplitCount; - } - // clipped by left side - if ((iOver=rClip.x-rcThis.x)>0) - { - if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } - pTarget->Wdt = iOver; rcThis.Wdt -= iOver; rcThis.x = rClip.x; - ++iSplitCount; - } - // clipped by top side - if ((iOver=rClip.y-rcThis.y)>0) - { - if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } else ++iSplitCount; - pTarget->Hgt = iOver; /* rcThis.Hgt -= iOver; rcThis.y = rClip.y; not needed, since rcThis is no longer used */ - } - // nothing split? This means this rectnagle is completely contained - if (!iSplitCount) - { - // make it vanish - RemoveIndexedRect(i); --i; - } - } - // concat rectangles if possible - bool fDone = false; - while (!fDone) - { - fDone=true; - for (int32_t i = 0, cnt=GetCount(); i < cnt && fDone; ++i) - { - C4Rect &rc1 = Get(i); - for (int32_t j = i+1; j < cnt; ++j) - { - C4Rect &rc2 = Get(j); - if (rc1.y == rc2.y && rc1.Hgt == rc2.Hgt) - { - if (rc1.x + rc1.Wdt == rc2.x) - { - rc1.Wdt += rc2.Wdt; RemoveIndexedRect(j); fDone=false; break; - } - else if (rc2.x + rc2.Wdt == rc1.x) - { - rc2.Wdt += rc1.Wdt; RemoveIndexedRect(i); fDone=false; break; - } - } - else if (rc1.x == rc2.x && rc1.Wdt == rc2.Wdt) - { - if (rc1.y + rc1.Hgt == rc2.y) - { - rc1.Hgt += rc2.Hgt; RemoveIndexedRect(j); fDone=false; break; - } - else if (rc2.y + rc2.Hgt == rc1.y) - { - rc2.Hgt += rc1.Hgt; RemoveIndexedRect(i); fDone=false; break; - } - } - } - } - } - } - diff --git a/src/game/object/C4Shape.h b/src/game/object/C4Shape.h index 08e495660..caa9e5525 100644 --- a/src/game/object/C4Shape.h +++ b/src/game/object/C4Shape.h @@ -26,71 +26,10 @@ #include "C4FacetEx.h" #include "C4Constants.h" +#include "C4Rect.h" #define C4D_VertexCpyPos (C4D_MaxVertex/2) -class C4Rect - { - public: - int32_t x,y,Wdt,Hgt; - public: - void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt); - void Default(); - BOOL Overlap(C4Rect &rTarget); - void Intersect(const C4Rect &r2); - void Add(const C4Rect &r2); - bool operator ==(const C4Rect &r2) { return !((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); } - bool operator !=(const C4Rect &r2) { return 0 != ((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); } - - bool Contains(int32_t iX, int32_t iY) - { return iX>=x && iX=y && iY=x && iX+iWdt=y && iY+iHgt(rcfOuter.left); y=static_cast(rcfOuter.top); - Wdt=static_cast(ceilf(rcfOuter.right)-floorf(rcfOuter.left)); - Hgt=static_cast(ceilf(rcfOuter.bottom)-floorf(rcfOuter.top)); } - - void CompileFunc(StdCompiler *pComp); - }; - -class C4TargetRect: public C4Rect - { - public: - int32_t tx,ty; - public: - C4TargetRect(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY) - : C4Rect(iX, iY, iWdt, iHgt), tx(iTX), ty(iTY) { } - C4TargetRect() { } // default ctor; doesn't initialize - void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY); - void Default(); - bool ClipBy(C4TargetRect &rClip); // clip this rectangle by the given one (adding target positions) - return false if they don't overlap - - void Set(const C4TargetFacet &rSrc); // copy contents from facet - - void CompileFunc(StdCompiler *pComp); - }; - -const C4Rect Rect0(0,0,0,0); -const C4TargetRect TargetRect0(0,0,0,0,0,0); - // a functional class to provide density for coordinates class C4DensityProvider { @@ -145,22 +84,4 @@ class C4Shape: public C4Rect void CompileFunc(StdCompiler *pComp, bool fRuntime); }; - -// a bunch of rectangles -// rects NOT including pos+size-point -class C4RectList : public std::vector - { - public: - void AddRect(const C4Rect &rNewRect) - { push_back(rNewRect); } - void RemoveIndexedRect(int32_t idx) - { if (idxValue(mkDefaultAdapt(x, 0)); pComp->Seperator(); + pComp->Value(mkDefaultAdapt(y, 0)); pComp->Seperator(); + pComp->Value(mkDefaultAdapt(Wdt, 0)); pComp->Seperator(); + pComp->Value(mkDefaultAdapt(Hgt, 0)); + } + +void C4TargetRect::Default() + { + C4Rect::Default(); + tx=ty=0; + } + +void C4TargetRect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY) + { + C4Rect::Set(iX,iY,iWdt,iHgt); + tx=iTX; ty=iTY; + } + +bool C4TargetRect::ClipBy(C4TargetRect &rClip) + { + int32_t d; + // clip left + if ((d = x - rClip.x) < 0) { Wdt += d; x = rClip.x; } else tx += d; + // clip top + if ((d = y - rClip.y) < 0) { Hgt += d; y = rClip.y; } else ty += d; + // clip right + if ((d = (x+Wdt - rClip.x-rClip.Wdt)) > 0) Wdt -= d; + // clip bottom + if ((d = (y+Hgt - rClip.y-rClip.Hgt)) > 0) Hgt -= d; + // check validity + if (Wdt <= 0 || Hgt <= 0) return false; + // add target pos + tx += rClip.tx; + ty += rClip.ty; + // done + return true; + } + +void C4TargetRect::Set(const C4TargetFacet &rSrc) + { + // copy members + x=rSrc.X; y=rSrc.Y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; tx=rSrc.TargetX; ty=rSrc.TargetY; + } + +void C4TargetRect::CompileFunc(StdCompiler *pComp) + { + C4Rect::CompileFunc(pComp); pComp->Seperator(); + pComp->Value(mkDefaultAdapt(tx,0)); pComp->Seperator(); + pComp->Value(mkDefaultAdapt(ty,0)); + } + +void C4Rect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt) + { + x=iX; y=iY; Wdt=iWdt; Hgt=iHgt; + } + +BOOL C4Rect::Overlap(C4Rect &rTarget) + { + if (x+Wdt<=rTarget.x) return FALSE; + if (x>=rTarget.x+rTarget.Wdt) return FALSE; + if (y+Hgt<=rTarget.y) return FALSE; + if (y>=rTarget.y+rTarget.Hgt) return FALSE; + return TRUE; + } + +void C4Rect::Intersect(const C4Rect &r2) + { + // Narrow bounds + if (r2.x > x) + if (r2.x + r2.Wdt < x + Wdt) + { x = r2.x; Wdt = r2.Wdt; } + else + { Wdt -= (r2.x - x); x = r2.x; } + else + if (r2.x + r2.Wdt < x + Wdt) + Wdt = r2.x + r2.Wdt - x; + if (r2.y > y) + if (r2.y + r2.Hgt < y + Hgt) + { y = r2.y; Hgt = r2.Hgt; } + else + { Hgt -= (r2.y - y); y = r2.y; } + else + if (r2.y + r2.Hgt < y + Hgt) + Hgt = r2.y + r2.Hgt - y; + // Degenerated? Will happen when the two rects don't overlap + if (Wdt < 0) Wdt = 0; + if (Hgt < 0) Hgt = 0; + } + +bool C4Rect::IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2) + { + // Easy cases first + if(Contains(iX, iY)) return true; + if(Contains(iX2, iY2)) return true; + if(iX < x && iX2 < x) return false; + if(iY < y && iY2 < y) return false; + if(iX >= x+Wdt && iX2 >= x+Wdt) return false; + if(iY >= y+Hgt && iY2 >= y+Hgt) return false; + // check some special cases + if (iX == iX2 || iY == iY2) return true; + // Check intersection left/right + int32_t iXI, iYI; + iXI = (iX < x ? x : x+Wdt); + iYI = iY + (iY2 - iY) * (iXI - iX) / (iX2 - iX); + if(iYI >= y && iYI < y+Hgt) return true; + // Check intersection up/down + iYI = (iY < y ? y : y+Hgt); + iXI = iX + (iX2 - iX) * (iYI - iY) / (iY2 - iY); + return iXI >= x && iXI < x+Wdt; + } + +void C4Rect::Add(const C4Rect &r2) + { + // Null? Don't do anything + if (!r2.Wdt || !r2.Hgt) return; + if (!Wdt || !Hgt) + { + *this = r2; + return; + } + // Expand bounds + if (r2.x < x) + if (r2.x + r2.Wdt > x + Wdt) + { x = r2.x; Wdt = r2.Wdt; } + else + { Wdt += (x - r2.x); x = r2.x; } + else + if (r2.x + r2.Wdt > x + Wdt) + Wdt = r2.x + r2.Wdt - x; + if (r2.y < y) + if (r2.y + r2.Hgt > y + Hgt) + { y = r2.y; Hgt = r2.Hgt; } + else + { Hgt += (y - r2.y); y = r2.y; } + else + if (r2.y + r2.Hgt > y + Hgt) + Hgt = r2.y + r2.Hgt - y; + } + +// ---- C4RectList ---- + + +void C4RectList::ClipByRect(const C4Rect &rClip) + { + // split up all rectangles + for (int32_t i = 0; i < GetCount(); ++i) + { + C4Rect *pTarget = &Get(i); + // any overlap? + if (rClip.x+rClip.Wdt <= pTarget->x) continue; + if (rClip.y+rClip.Hgt <= pTarget->y) continue; + if (rClip.x >= pTarget->x+pTarget->Wdt) continue; + if (rClip.y >= pTarget->y+pTarget->Hgt) continue; + // okay; split up rectangle + // first split will just reduce the target rectangle size + // if more splits are done, additional rectangles need to be added + int32_t iSplitCount = 0, iOver; C4Rect rcThis(*pTarget); + // clipped by right side + if ((iOver=rcThis.x+rcThis.Wdt-rClip.x-rClip.Wdt)>0) + { + pTarget->x += pTarget->Wdt - iOver; pTarget->Wdt = iOver; rcThis.Wdt -= iOver; + ++iSplitCount; + } + // clipped by obttom side + if ((iOver=rcThis.y+rcThis.Hgt-rClip.y-rClip.Hgt)>0) + { + if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } + pTarget->y += pTarget->Hgt - iOver; pTarget->Hgt = iOver; rcThis.Hgt -= iOver; + ++iSplitCount; + } + // clipped by left side + if ((iOver=rClip.x-rcThis.x)>0) + { + if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } + pTarget->Wdt = iOver; rcThis.Wdt -= iOver; rcThis.x = rClip.x; + ++iSplitCount; + } + // clipped by top side + if ((iOver=rClip.y-rcThis.y)>0) + { + if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } else ++iSplitCount; + pTarget->Hgt = iOver; /* rcThis.Hgt -= iOver; rcThis.y = rClip.y; not needed, since rcThis is no longer used */ + } + // nothing split? This means this rectnagle is completely contained + if (!iSplitCount) + { + // make it vanish + RemoveIndexedRect(i); --i; + } + } + // concat rectangles if possible + bool fDone = false; + while (!fDone) + { + fDone=true; + for (int32_t i = 0, cnt=GetCount(); i < cnt && fDone; ++i) + { + C4Rect &rc1 = Get(i); + for (int32_t j = i+1; j < cnt; ++j) + { + C4Rect &rc2 = Get(j); + if (rc1.y == rc2.y && rc1.Hgt == rc2.Hgt) + { + if (rc1.x + rc1.Wdt == rc2.x) + { + rc1.Wdt += rc2.Wdt; RemoveIndexedRect(j); fDone=false; break; + } + else if (rc2.x + rc2.Wdt == rc1.x) + { + rc2.Wdt += rc1.Wdt; RemoveIndexedRect(i); fDone=false; break; + } + } + else if (rc1.x == rc2.x && rc1.Wdt == rc2.Wdt) + { + if (rc1.y + rc1.Hgt == rc2.y) + { + rc1.Hgt += rc2.Hgt; RemoveIndexedRect(j); fDone=false; break; + } + else if (rc2.y + rc2.Hgt == rc1.y) + { + rc2.Hgt += rc1.Hgt; RemoveIndexedRect(i); fDone=false; break; + } + } + } + } + } + } + diff --git a/src/lib/C4Rect.h b/src/lib/C4Rect.h new file mode 100644 index 000000000..590e46321 --- /dev/null +++ b/src/lib/C4Rect.h @@ -0,0 +1,108 @@ +/* + * OpenClonk, http://www.openclonk.org + * + * Copyright (c) 1998-2000, 2007 Matthes Bender + * Copyright (c) 2001, 2003-2006 Sven Eberhardt + * Copyright (c) 2005-2006 Peter Wortmann + * Copyright (c) 2006, 2009 Günther Brammer + * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de + * + * Portions might be copyrighted by other authors who have contributed + * to OpenClonk. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * See isc_license.txt for full license and disclaimer. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +/* Basic classes for rectangles and vertex outlines */ + +#ifndef INC_C4Rect +#define INC_C4Rect + +#define C4D_VertexCpyPos (C4D_MaxVertex/2) + +class C4Rect + { + public: + int32_t x,y,Wdt,Hgt; + public: + void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt); + void Default(); + BOOL Overlap(C4Rect &rTarget); + void Intersect(const C4Rect &r2); + void Add(const C4Rect &r2); + bool operator ==(const C4Rect &r2) { return !((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); } + bool operator !=(const C4Rect &r2) { return 0 != ((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); } + + bool Contains(int32_t iX, int32_t iY) + { return iX>=x && iX=y && iY=x && iX+iWdt=y && iY+iHgt(rcfOuter.left); y=static_cast(rcfOuter.top); + Wdt=static_cast(ceilf(rcfOuter.right)-floorf(rcfOuter.left)); + Hgt=static_cast(ceilf(rcfOuter.bottom)-floorf(rcfOuter.top)); } + + void CompileFunc(StdCompiler *pComp); + }; + +class C4TargetRect: public C4Rect + { + public: + int32_t tx,ty; + public: + C4TargetRect(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY) + : C4Rect(iX, iY, iWdt, iHgt), tx(iTX), ty(iTY) { } + C4TargetRect() { } // default ctor; doesn't initialize + void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY); + void Default(); + bool ClipBy(C4TargetRect &rClip); // clip this rectangle by the given one (adding target positions) - return false if they don't overlap + + void Set(const C4TargetFacet &rSrc); // copy contents from facet + + void CompileFunc(StdCompiler *pComp); + }; + +const C4Rect Rect0(0,0,0,0); +const C4TargetRect TargetRect0(0,0,0,0,0,0); + +// a bunch of rectangles +// rects NOT including pos+size-point +class C4RectList : public std::vector + { + public: + void AddRect(const C4Rect &rNewRect) + { push_back(rNewRect); } + void RemoveIndexedRect(int32_t idx) + { if (idx -#include +#include #include #endif