Refactor rect clipping
This commit is contained in:
parent
31abb8a48f
commit
7d9fdfea4e
@ -9,21 +9,23 @@ constexpr float M_GRAV = 6.67300e-1f;
|
||||
|
||||
//CELL, the size of the pressure, gravity, and wall maps. Larger than 1 to prevent extreme lag
|
||||
constexpr int CELL = 4;
|
||||
constexpr int XCELLS = 153;
|
||||
constexpr int YCELLS = 96;
|
||||
|
||||
constexpr auto CELLS = Vec2<int>(153, 96);
|
||||
constexpr int XCELLS = CELLS.X;
|
||||
constexpr int YCELLS = CELLS.Y;
|
||||
constexpr int NCELL = XCELLS * YCELLS;
|
||||
constexpr Rect<int> CELLS = Rect<int>(Vec2<int>(0, 0), Vec2<int>(XCELLS - 1, YCELLS - 1));
|
||||
constexpr int XRES = XCELLS * CELL;
|
||||
constexpr int YRES = YCELLS * CELL;
|
||||
|
||||
constexpr auto RES = CELLS * CELL;
|
||||
constexpr int XRES = RES.X;
|
||||
constexpr int YRES = RES.Y;
|
||||
constexpr int NPART = XRES * YRES;
|
||||
constexpr Rect<int> RES = Rect<int>(Vec2<int>(0, 0), Vec2<int>(XRES - 1, YRES - 1));
|
||||
|
||||
constexpr int XCNTR = XRES / 2;
|
||||
constexpr int YCNTR = YRES / 2;
|
||||
|
||||
constexpr int WINDOWW = XRES + BARSIZE;
|
||||
constexpr int WINDOWH = YRES + MENUSIZE;
|
||||
constexpr Rect<int> WINDOW = Rect<int>(Vec2<int>(0, 0), Vec2<int>(WINDOWW - 1, WINDOWH - 1));
|
||||
constexpr auto WINDOW = RES + Vec2<int>(BARSIZE, MENUSIZE);
|
||||
constexpr int WINDOWW = WINDOW.X;
|
||||
constexpr int WINDOWH = WINDOW.Y;
|
||||
|
||||
constexpr int MAXSIGNS = 16;
|
||||
|
||||
|
@ -122,16 +122,16 @@ inline Vec2<int> lroundNegInf(Vec2<float> v)
|
||||
|
||||
Vec2<int> GameSave::Translate(Vec2<int> translate)
|
||||
{
|
||||
auto bounds = Rect<float>(Vec2<float>::Zero);
|
||||
auto bounds = RectAt(Vec2<float>::Zero);
|
||||
|
||||
// determine minimum and maximum position of all particles / signs
|
||||
for (auto &sign : signs)
|
||||
bounds |= Rect<float>(roundNegInf(Vec2<float>(sign.x, sign.y) + translate));
|
||||
bounds |= RectAt(roundNegInf(Vec2<float>(sign.x, sign.y) + translate));
|
||||
|
||||
for (int i = 0; i < particlesCount; i++)
|
||||
{
|
||||
if (!particles[i].type) continue;
|
||||
bounds |= Rect<float>(roundNegInf(Vec2<float>(particles[i].x, particles[i].y) + translate));
|
||||
bounds |= RectAt(roundNegInf(Vec2<float>(particles[i].x, particles[i].y) + translate));
|
||||
}
|
||||
// determine whether corrections are needed. If moving in this direction would delete stuff, expand the save
|
||||
auto backCorrection = Vec2<int>(
|
||||
@ -171,12 +171,12 @@ void GameSave::Transform(Mat2<int> transform, Vec2<int> translate)
|
||||
Vec2<int>(blockDimen.X * CELL - 1, blockDimen.Y * CELL - 1),
|
||||
};
|
||||
// undo any translation caused by rotation
|
||||
auto bounds = Rect<int>(transform * cornerso[0]);
|
||||
auto bounds = RectAt(transform * cornerso[0]);
|
||||
for (int i = 1; i < 4; i++)
|
||||
bounds |= Rect<int>(transform * cornerso[i]);
|
||||
bounds |= RectAt(transform * cornerso[i]);
|
||||
Vec2<int> translateReal = translate;
|
||||
translate -= bounds.TopLeft;
|
||||
auto newBounds = bounds.BottomRight - bounds.TopLeft + Vec2<int>(1, 1);
|
||||
auto newBounds = bounds.Size();
|
||||
Transform(transform, translate, translateReal, newBounds);
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ void GameSave::Transform(Mat2<int> transform, Vec2<int> translate, Vec2<int> tra
|
||||
bool patchPipeV = transform == Mat2<int>::MirrorY;
|
||||
|
||||
// rotate and translate signs, parts, walls
|
||||
auto bounds = Rect<int>(Vec2<int>::Zero, newDimen - Vec2<int>(1, 1));
|
||||
auto bounds = newDimen.OriginRect();
|
||||
for (auto &sign : signs)
|
||||
{
|
||||
auto pos = transform * Vec2<int>(sign.x, sign.y) + translate;
|
||||
@ -266,7 +266,7 @@ void GameSave::Transform(Mat2<int> transform, Vec2<int> translate, Vec2<int> tra
|
||||
|| (translated.Y > 0 && (int)translated.Y%CELL == 0)))
|
||||
blockTranslate.Y = -CELL;
|
||||
|
||||
auto blockBounds = Rect<int>(Vec2<int>::Zero, newBlockDimen - Vec2<int>(1, 1));
|
||||
auto blockBounds = newBlockDimen.OriginRect();
|
||||
for (int y=0; y<blockDimen.Y; y++)
|
||||
for (int x=0; x<blockDimen.X; x++)
|
||||
{
|
||||
|
@ -743,24 +743,11 @@ VideoBuffer Graphics::DumpFrame()
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
void Graphics::SetClipRect(int &x, int &y, int &w, int &h)
|
||||
void Graphics::SetClipRect(Rect<int> &rect)
|
||||
{
|
||||
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;
|
||||
auto newRect = RectBetween(WINDOW.OriginRect().Clamp(rect.TopLeft), WINDOW.OriginRect().Clamp(rect.BottomRight));
|
||||
rect = clip;
|
||||
clip = newRect;
|
||||
}
|
||||
|
||||
bool VideoBuffer::WritePNG(const ByteString &path) const
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "common/Geometry.h"
|
||||
#include "common/String.h"
|
||||
#include "common/tpt-inline.h"
|
||||
#include "Pixel.h"
|
||||
@ -68,10 +69,7 @@ public:
|
||||
|
||||
class Graphics
|
||||
{
|
||||
int clipx1;
|
||||
int clipy1;
|
||||
int clipx2;
|
||||
int clipy2;
|
||||
Rect<int> clip;
|
||||
|
||||
public:
|
||||
pixel *vid;
|
||||
@ -131,7 +129,7 @@ public:
|
||||
Graphics();
|
||||
~Graphics();
|
||||
|
||||
void SetClipRect(int &x, int &y, int &w, int &h);
|
||||
void SetClipRect(Rect<int> &);
|
||||
};
|
||||
|
||||
bool PngDataToPixels(std::vector<pixel> &imageData, int &imgw, int &imgh, const char *pngData, size_t pngDataSize, bool addBackground);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
typedef unsigned int pixel;
|
||||
typedef uint32_t pixel;
|
||||
|
||||
constexpr int PIXELCHANNELS = 3;
|
||||
constexpr int PIXELSIZE = 4;
|
||||
@ -24,3 +27,30 @@ constexpr int PIXB(pixel x)
|
||||
{
|
||||
return x & 0xFF;
|
||||
}
|
||||
|
||||
template<typename T, typename = std::enable_if<std::is_arithmetic_v<T>, void>>
|
||||
struct RGB
|
||||
{
|
||||
T Red, Green, Blue;
|
||||
|
||||
constexpr RGB(T r, T g, T b):
|
||||
Red(r),
|
||||
Green(g),
|
||||
Blue(b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename = std::enable_if<std::is_arithmetic_v<T>, void>>
|
||||
struct RGBA
|
||||
{
|
||||
T Red, Green, Blue, Alpha;
|
||||
|
||||
constexpr RGBA(T r, T g, T b, T a = std::numeric_limits<T>::max()):
|
||||
Red(r),
|
||||
Green(g),
|
||||
Blue(b),
|
||||
Alpha(a)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -117,9 +117,9 @@ TPT_INLINE void PIXELMETHODS_CLASS::xor_pixel(int x, int y)
|
||||
{
|
||||
int c;
|
||||
#ifdef DO_CLIPCHECK
|
||||
if (x<clipx1 || y<clipy1 || x>=clipx2 || y>=clipy2)
|
||||
if (!clip.Contains(Vec2<int>(x, y)))
|
||||
#else
|
||||
if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
|
||||
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
|
||||
#endif
|
||||
return;
|
||||
c = vid[y*(VIDXRES)+x];
|
||||
@ -134,9 +134,9 @@ 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)
|
||||
if (!clip.Contains(Vec2<int>(x, y)))
|
||||
#else
|
||||
if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
|
||||
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
|
||||
#endif
|
||||
return;
|
||||
if (a!=255)
|
||||
@ -153,9 +153,9 @@ 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)
|
||||
if (!clip.Contains(Vec2<int>(x, y)))
|
||||
#else
|
||||
if (x<0 || y<0 || x>=VIDXRES || y>=VIDYRES)
|
||||
if (!VIDRES.OriginRect().Contains(Vec2<int>(x, y)))
|
||||
#endif
|
||||
return;
|
||||
t = vid[y*(VIDXRES)+x];
|
||||
@ -401,32 +401,15 @@ void PIXELMETHODS_CLASS::clearrect(int x, int y, int w, int h)
|
||||
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;
|
||||
}
|
||||
auto rect = clip.Clamp(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)));
|
||||
#else
|
||||
if (x+w > VIDXRES) w = VIDXRES-x;
|
||||
if (y+h > VIDYRES) h = VIDYRES-y;
|
||||
if (x<0)
|
||||
{
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y<0)
|
||||
{
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
auto rect = VIDRES.OriginRect().Clamp(RectSized(Vec2<int>(x, y), Vec2<int>(w, h)));
|
||||
#endif
|
||||
x = rect.TopLeft.X;
|
||||
y = rect.TopLeft.Y;
|
||||
w = rect.Size().X;
|
||||
h = rect.Size().Y;
|
||||
|
||||
if (w<0 || h<0)
|
||||
return;
|
||||
|
||||
@ -468,9 +451,9 @@ void PIXELMETHODS_CLASS::draw_image(const pixel *img, int x, int y, int w, int h
|
||||
for (int i = startX; i < w; i++)
|
||||
{
|
||||
#ifdef DO_CLIPCHECK
|
||||
if (!(x+i<clipx1 || y+j<clipy1 || x+i>=clipx2 || y+j>=clipy2))
|
||||
if (clip.Contains(Vec2<int>(x + i, y + j)))
|
||||
#endif
|
||||
vid[(y+j)*(VIDXRES)+(x+i)] = *img;
|
||||
vid[(y+j)*(VIDXRES)+(x+i)] = *img;
|
||||
img++;
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,7 @@
|
||||
#include <cstring>
|
||||
|
||||
Graphics::Graphics():
|
||||
clipx1(0),
|
||||
clipy1(0),
|
||||
clipx2(WINDOWW),
|
||||
clipy2(WINDOWH),
|
||||
clip(WINDOW.OriginRect()),
|
||||
sdl_scale(1)
|
||||
{
|
||||
vid = (pixel *)malloc(PIXELSIZE * (WINDOWW * WINDOWH));
|
||||
|
@ -5,8 +5,9 @@
|
||||
#include "simulation/ElementClasses.h"
|
||||
#include <cmath>
|
||||
|
||||
constexpr auto VIDXRES = WINDOWW;
|
||||
constexpr auto VIDYRES = WINDOWH;
|
||||
constexpr auto VIDRES = WINDOW;
|
||||
constexpr auto VIDXRES = VIDRES.X;
|
||||
constexpr auto VIDYRES = VIDRES.Y;
|
||||
|
||||
void Renderer::RenderBegin()
|
||||
{
|
||||
|
@ -36,10 +36,12 @@ public:
|
||||
};
|
||||
|
||||
GOLWindow::GOLWindow(GameModel * gameModel_, Simulation *sim_, int toolSelection, int rule, int colour1, int colour2):
|
||||
ui::Window(ui::Point(-1, -1), ui::Point(200, 108)),
|
||||
gameModel(gameModel_),
|
||||
sim(sim_),
|
||||
toolSelection(toolSelection)
|
||||
ui::Window(ui::Point(-1, -1), ui::Point(200, 108)),
|
||||
highColour(0, 0, 0, 0),
|
||||
lowColour(0, 0, 0, 0),
|
||||
gameModel(gameModel_),
|
||||
sim(sim_),
|
||||
toolSelection(toolSelection)
|
||||
{
|
||||
ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 14), "Edit custom GOL type");
|
||||
messageLabel->SetTextColour(style::Colour::InformationTitle);
|
||||
|
@ -575,10 +575,7 @@ 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;
|
||||
tempButton->clip = RectBetween(Vec2<int>(1, YRES + 1), Vec2<int>(XRES - 1, YRES + 18));
|
||||
|
||||
//currentY -= 17;
|
||||
currentX -= 31;
|
||||
@ -1859,11 +1856,8 @@ void GameView::DoDraw()
|
||||
|
||||
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
|
||||
auto rect = WINDOW.OriginRect();
|
||||
g->SetClipRect(rect); // reset any nonsense cliprect Lua left configured
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,13 +45,10 @@ 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)
|
||||
auto rect = clip;
|
||||
if (rect)
|
||||
{
|
||||
g->SetClipRect(x, y, w, h); // old cliprect is now in x, y, w, h
|
||||
g->SetClipRect(*rect); // old cliprect is now in rect
|
||||
}
|
||||
int totalColour = Appearance.BackgroundInactive.Blue + (3*Appearance.BackgroundInactive.Green) + (2*Appearance.BackgroundInactive.Red);
|
||||
|
||||
@ -85,9 +82,9 @@ 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)
|
||||
if (rect)
|
||||
{
|
||||
g->SetClipRect(x, y, w, h); // apply old clip rect
|
||||
g->SetClipRect(*rect); // apply old clip rect
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "gui/interface/Button.h"
|
||||
#include <optional>
|
||||
|
||||
class Tool;
|
||||
|
||||
@ -16,8 +17,5 @@ public:
|
||||
void SetSelectionState(int state);
|
||||
int GetSelectionState();
|
||||
Tool *tool;
|
||||
int clipRectX = 0;
|
||||
int clipRectY = 0;
|
||||
int clipRectW = 0;
|
||||
int clipRectH = 0;
|
||||
std::optional<Rect<int>> clip = std::nullopt;
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ namespace ui
|
||||
BorderHover(255, 255, 255),
|
||||
BorderInactive(200, 200, 200),
|
||||
BorderActive(235, 235, 235),
|
||||
BorderFavorite(255, 255, 0),
|
||||
BorderDisabled(100, 100, 100),
|
||||
|
||||
Margin(1, 4),
|
||||
|
@ -1,21 +1,8 @@
|
||||
#pragma once
|
||||
#include "graphics/Pixel.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class Colour
|
||||
{
|
||||
public:
|
||||
unsigned char Red, Green, Blue, Alpha;
|
||||
Colour(unsigned char red, unsigned char green, unsigned char blue):
|
||||
Red(red), Green(green), Blue(blue), Alpha(255)
|
||||
{
|
||||
}
|
||||
Colour(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha):
|
||||
Red(red), Green(green), Blue(blue), Alpha(alpha)
|
||||
{
|
||||
}
|
||||
Colour()
|
||||
{
|
||||
}
|
||||
};
|
||||
using Colour = RGBA<uint8_t>;
|
||||
}
|
||||
|
@ -67,11 +67,8 @@ void Panel::Draw(const Point& screenPos)
|
||||
// draw ourself first
|
||||
XDraw(screenPos);
|
||||
|
||||
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
|
||||
auto rect = RectSized(screenPos, Size);
|
||||
ui::Engine::Ref().g->SetClipRect(rect); // old cliprect is now in rect
|
||||
|
||||
// attempt to draw all children
|
||||
for (size_t i = 0; i < children.size(); ++i)
|
||||
@ -91,7 +88,7 @@ void Panel::Draw(const Point& screenPos)
|
||||
}
|
||||
}
|
||||
|
||||
ui::Engine::Ref().g->SetClipRect(x, y, w, h); // apply old cliprect
|
||||
ui::Engine::Ref().g->SetClipRect(rect); // apply old cliprect
|
||||
}
|
||||
|
||||
void Panel::Tick(float dt)
|
||||
|
@ -3901,11 +3901,12 @@ int LuaScriptInterface::graphics_setClipRect(lua_State * l)
|
||||
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);
|
||||
auto rect = RectSized(Vec2<int>(x, y), Vec2<int>(w, h));
|
||||
luacon_g->SetClipRect(rect);
|
||||
lua_pushinteger(l, rect.TopLeft.X);
|
||||
lua_pushinteger(l, rect.TopLeft.Y);
|
||||
lua_pushinteger(l, rect.Size().X);
|
||||
lua_pushinteger(l, rect.Size().Y);
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user