Add clip rect feature to Graphics and gfx.setClipRect

Also retire the separate VideoBuffer in Panel and hiding ToolButtons in the GameView ToolButton panel in favour of clip rects.
This commit is contained in:
Tamás Bálint Misius 2022-10-11 20:24:11 +02:00
parent f18bd6553f
commit 715333295b
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
12 changed files with 127 additions and 33 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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<clipx1 || y<clipy1 || 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<clipx1 || y<clipy1 || 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<clipx1 || y<clipy1 || 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<clipx1)
{
w += x - clipx1;
x = clipx1;
}
if (y<clipy1)
{
h += y - clipy1;
y = clipy1;
}
#else
if (x+w > 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<clipx1 || y+j<clipy1 || 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);
}

View File

@ -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

View File

@ -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();

View File

@ -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<int, 9> 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)

View File

@ -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)

View File

@ -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_ */

View File

@ -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)

View File

@ -22,7 +22,6 @@ class Component;
public:
friend class Component;
pixel * myVid;
ui::Point InnerSize;
ui::Point ViewportPosition;

View File

@ -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

View File

@ -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);