diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index 19226b944..b7fe77a0d 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -1081,3 +1081,23 @@ VideoBuffer Graphics::DumpFrame() std::copy(vid, vid+(WINDOWW*WINDOWH), newBuffer.Buffer); return newBuffer; } + +void Graphics::SetClipRect(int &x, int &y, int &w, int &h) +{ + int newX = x; + int newY = y; + int newW = w; + int newH = h; + if (newX < 0) newX = 0; + if (newY < 0) newY = 0; + if (newW > WINDOWW - newX) newW = WINDOWW - newX; + if (newH > WINDOWH - newY) newH = WINDOWH - newY; + x = clipx1; + y = clipy1; + w = clipx2 - clipx1; + h = clipy2 - clipy1; + clipx1 = newX; + clipy1 = newY; + clipx2 = newX + newW; + clipy2 = newY + newH; +} diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index e2cb393c7..5771693c1 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -70,6 +70,11 @@ public: class Graphics { + int clipx1 = 0; + int clipy1 = 0; + int clipx2 = WINDOWW; + int clipy2 = WINDOWH; + public: pixel *vid; int sdl_scale; @@ -122,13 +127,14 @@ public: void clearrect(int x, int y, int width, int height); void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2); - void draw_image(pixel *img, int x, int y, int w, int h, int a); - void draw_image(const VideoBuffer & vidBuf, int x, int y, int a); - void draw_image(VideoBuffer * vidBuf, int x, int y, int a); + void draw_image(const pixel *img, int x, int y, int w, int h, int a); + void draw_image(const VideoBuffer * vidBuf, int x, int y, int a); void draw_rgba_image(const unsigned char *data, int x, int y, float alpha); Graphics(); ~Graphics(); + + void SetClipRect(int &x, int &y, int &w, int &h); }; #endif diff --git a/src/graphics/RasterDrawMethods.inl b/src/graphics/RasterDrawMethods.inl index 4d7b0be40..40889d991 100644 --- a/src/graphics/RasterDrawMethods.inl +++ b/src/graphics/RasterDrawMethods.inl @@ -104,7 +104,11 @@ int PIXELMETHODS_CLASS::addchar(int x, int y, String::value_type c, int r, int g TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y) { int c; - if (x<0 || y<0 || x>=XRES || y>=YRES) +#ifdef DO_CLIPCHECK + if (x=clipx2 || y>=clipy2) +#else + if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) +#endif return; c = vid[y*(VIDXRES)+x]; c = PIXB(c) + 3*PIXG(c) + 2*PIXR(c); @@ -117,7 +121,11 @@ TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y) void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a) { pixel t; +#ifdef DO_CLIPCHECK + if (x=clipx2 || y>=clipy2) +#else if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) +#endif return; if (a!=255) { @@ -132,7 +140,11 @@ void PIXELMETHODS_CLASS::blendpixel(int x, int y, int r, int g, int b, int a) void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a) { pixel t; +#ifdef DO_CLIPCHECK + if (x=clipx2 || y>=clipy2) +#else if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES) +#endif return; t = vid[y*(VIDXRES)+x]; r = (a*r + 255*PIXR(t)) >> 8; @@ -376,6 +388,20 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h) w -= 1; h -= 1; +#ifdef DO_CLIPCHECK + if (x+w > clipx2) w = clipx2-x; + if (y+h > clipy2) h = clipy2-y; + if (x VIDXRES) w = VIDXRES-x; if (y+h > VIDYRES) h = VIDYRES-y; if (x<0) @@ -388,6 +414,7 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h) h += y; y = 0; } +#endif if (w<0 || h<0) return; @@ -395,7 +422,7 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h) memset(vid+(x+(VIDXRES)*(y+i)), 0, PIXELSIZE*w); } -void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int a) +void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h, int a) { int startX = 0; if (!img) @@ -428,6 +455,9 @@ void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int img += startX; for (int i = startX; i < w; i++) { +#ifdef DO_CLIPCHECK + if (!(x+i=clipx2 || y+j>=clipy2)) +#endif vid[(y+j)*(VIDXRES)+(x+i)] = *img; img++; } @@ -450,12 +480,7 @@ void PIXELMETHODS_CLASS::draw_image(pixel *img, int x, int y, int w, int h, int } } -void PIXELMETHODS_CLASS::draw_image(const VideoBuffer & vidBuf, int x, int y, int a) -{ - draw_image(vidBuf.Buffer, x, y, vidBuf.Width, vidBuf.Height, a); -} - -void PIXELMETHODS_CLASS::draw_image(VideoBuffer * vidBuf, int x, int y, int a) +void PIXELMETHODS_CLASS::draw_image(const VideoBuffer * vidBuf, int x, int y, int a) { draw_image(vidBuf->Buffer, x, y, vidBuf->Width, vidBuf->Height, a); } diff --git a/src/graphics/RasterGraphics.cpp b/src/graphics/RasterGraphics.cpp index 0b77d5884..1f6156b92 100644 --- a/src/graphics/RasterGraphics.cpp +++ b/src/graphics/RasterGraphics.cpp @@ -28,6 +28,7 @@ void Graphics::Finalise() #define VIDXRES WINDOWW #define VIDYRES WINDOWH #define PIXELMETHODS_CLASS Graphics +#define DO_CLIPCHECK #include "RasterDrawMethods.inl" #undef VIDYRES #undef VIDXRES diff --git a/src/graphics/Renderer.h b/src/graphics/Renderer.h index 2d30211ec..c83233e17 100644 --- a/src/graphics/Renderer.h +++ b/src/graphics/Renderer.h @@ -120,9 +120,8 @@ public: void clearrect(int x, int y, int width, int height); void gradientrect(int x, int y, int width, int height, int r, int g, int b, int a, int r2, int g2, int b2, int a2); - void draw_image(pixel *img, int x, int y, int w, int h, int a); - void draw_image(const VideoBuffer & vidBuf, int w, int h, int a); - void draw_image(VideoBuffer * vidBuf, int w, int h, int a); + void draw_image(const pixel *img, int x, int y, int w, int h, int a); + void draw_image(const VideoBuffer * vidBuf, int w, int h, int a); VideoBuffer DumpFrame(); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index f9fe275b0..f52dbcbb0 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -576,6 +576,11 @@ void GameView::NotifyToolListChanged(GameModel * sender) else tempButton = new ToolButton(ui::Point(currentX, YRES+1), ui::Point(30, 18), tool->GetName(), tool->GetIdentifier(), tool->GetDescription()); + tempButton->clipRectX = 1; + tempButton->clipRectY = YRES + 1; + tempButton->clipRectW = XRES - 1; + tempButton->clipRectH = 18; + //currentY -= 17; currentX -= 31; tempButton->tool = tool; @@ -1014,10 +1019,6 @@ void GameView::updateToolButtonScroll() for (auto *button : toolButtons) { button->Position.X -= offsetDelta; - if (button->Position.X + button->Size.X <= 0 || (button->Position.X + button->Size.X) > XRES - 2) - button->Visible = false; - else - button->Visible = true; } // Ensure that mouseLeave events are make their way to the buttons should they move from underneath the mouse pointer @@ -1803,7 +1804,24 @@ void GameView::DoExit() void GameView::DoDraw() { Window::DoDraw(); + constexpr std::array fadeout = { { // * Gamma-corrected. + 255, 195, 145, 103, 69, 42, 23, 10, 3 + } }; + auto *g = GetGraphics(); + for (auto x = 0U; x < fadeout.size(); ++x) + { + g->draw_line(x, YRES + 1, x, YRES + 18, 0, 0, 0, fadeout[x]); + g->draw_line(XRES - x, YRES + 1, XRES - x, YRES + 18, 0, 0, 0, fadeout[x]); + } + c->Tick(); + { + int x = 0; + int y = 0; + int w = WINDOWW; + int h = WINDOWH; + g->SetClipRect(x, y, w, h); // reset any nonsense cliprect Lua left configured + } } void GameView::NotifyNotificationsChanged(GameModel * sender) diff --git a/src/gui/game/ToolButton.cpp b/src/gui/game/ToolButton.cpp index 1d3610d2f..3432ad212 100644 --- a/src/gui/game/ToolButton.cpp +++ b/src/gui/game/ToolButton.cpp @@ -49,6 +49,14 @@ void ToolButton::OnMouseUp(int x, int y, unsigned int button) void ToolButton::Draw(const ui::Point& screenPos) { Graphics * g = GetGraphics(); + int x = clipRectX; + int y = clipRectY; + int w = clipRectW; + int h = clipRectH; + if (clipRectW && clipRectH) + { + g->SetClipRect(x, y, w, h); // old cliprect is now in x, y, w, h + } int totalColour = Appearance.BackgroundInactive.Blue + (3*Appearance.BackgroundInactive.Green) + (2*Appearance.BackgroundInactive.Red); if (Appearance.GetTexture()) @@ -81,6 +89,10 @@ void ToolButton::Draw(const ui::Point& screenPos) { g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, buttonDisplayText, 0, 0, 0, 255); } + if (clipRectW && clipRectH) + { + g->SetClipRect(x, y, w, h); // apply old clip rect + } } void ToolButton::SetSelectionState(int state) diff --git a/src/gui/game/ToolButton.h b/src/gui/game/ToolButton.h index 6421d2cfd..e6d99ce72 100644 --- a/src/gui/game/ToolButton.h +++ b/src/gui/game/ToolButton.h @@ -18,6 +18,10 @@ public: void SetSelectionState(int state); int GetSelectionState(); Tool *tool; + int clipRectX = 0; + int clipRectY = 0; + int clipRectW = 0; + int clipRectH = 0; }; #endif /* TOOLBUTTON_H_ */ diff --git a/src/gui/interface/Panel.cpp b/src/gui/interface/Panel.cpp index e7cea286f..4eb0828bf 100644 --- a/src/gui/interface/Panel.cpp +++ b/src/gui/interface/Panel.cpp @@ -13,7 +13,6 @@ Panel::Panel(Point position, Point size): ViewportPosition(0, 0), mouseInside(false) { - myVid = new pixel[WINDOWW*WINDOWH]; } Panel::~Panel() @@ -22,7 +21,6 @@ Panel::~Panel() { delete children[i]; } - delete[] myVid; } void Panel::AddChild(Component* c) @@ -66,12 +64,14 @@ void Panel::RemoveChild(unsigned idx, bool freeMem) void Panel::Draw(const Point& screenPos) { - // draw ourself first XDraw(screenPos); - pixel * lastVid = ui::Engine::Ref().g->vid; - ui::Engine::Ref().g->vid = myVid; - std::fill(myVid, myVid+(WINDOWW*WINDOWH), 0); + + int x = screenPos.X; + int y = screenPos.Y; + int w = Size.X; + int h = Size.Y; + ui::Engine::Ref().g->SetClipRect(x, y, w, h); // old cliprect is now in x, y, w, h // attempt to draw all children for (size_t i = 0; i < children.size(); ++i) @@ -85,19 +85,13 @@ void Panel::Draw(const Point& screenPos) children[i]->Position.X + ViewportPosition.X < ui::Engine::Ref().GetWidth() && children[i]->Position.Y + ViewportPosition.Y < ui::Engine::Ref().GetHeight() ) { - Point scrpos = /*screenPos + */children[i]->Position + ViewportPosition; + Point scrpos = screenPos + children[i]->Position + ViewportPosition; children[i]->Draw(scrpos); } } } - ui::Engine::Ref().g->vid = lastVid; - - //dst=(pixel *)sdl_scrn->pixels+y*sdl_scrn->pitch/PIXELSIZE+x; - for (int row = 0; row < Size.Y; row++) - { - std::copy(myVid+(row*WINDOWW), myVid+(row*WINDOWW)+Size.X, lastVid+((screenPos.Y+row)*WINDOWW)+screenPos.X); - } + ui::Engine::Ref().g->SetClipRect(x, y, w, h); // apply old cliprect } void Panel::Tick(float dt) diff --git a/src/gui/interface/Panel.h b/src/gui/interface/Panel.h index d4d13740b..8ea827f0e 100644 --- a/src/gui/interface/Panel.h +++ b/src/gui/interface/Panel.h @@ -22,7 +22,6 @@ class Component; public: friend class Component; - pixel * myVid; ui::Point InnerSize; ui::Point ViewportPosition; diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 1e7b34069..03a1d4238 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -3579,6 +3579,7 @@ void LuaScriptInterface::initGraphicsAPI() {"fillCircle", graphics_fillCircle}, {"getColors", graphics_getColors}, {"getHexColor", graphics_getHexColor}, + {"setClipRect", graphics_setClipRect}, {NULL, NULL} }; luaL_register(l, "graphics", graphicsAPIMethods); @@ -3775,6 +3776,20 @@ int LuaScriptInterface::graphics_getHexColor(lua_State * l) return 1; } +int LuaScriptInterface::graphics_setClipRect(lua_State * l) +{ + int x = luaL_optinteger(l, 1, 0); + int y = luaL_optinteger(l, 2, 0); + int w = luaL_optinteger(l, 3, WINDOWW); + int h = luaL_optinteger(l, 4, WINDOWH); + luacon_g->SetClipRect(x, y, w, h); + lua_pushinteger(l, x); + lua_pushinteger(l, y); + lua_pushinteger(l, w); + lua_pushinteger(l, h); + return 4; +} + void LuaScriptInterface::initFileSystemAPI() { //Methods diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index 292d70b35..b824bfe59 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -167,6 +167,7 @@ class LuaScriptInterface: public CommandInterface static int graphics_fillCircle(lua_State * l); static int graphics_getColors(lua_State * l); static int graphics_getHexColor(lua_State * l); + static int graphics_setClipRect(lua_State * l); void initFileSystemAPI(); static int fileSystem_list(lua_State * l);