diff --git a/src/common/RasterGeometry.h b/src/common/RasterGeometry.h new file mode 100644 index 000000000..3d21f0796 --- /dev/null +++ b/src/common/RasterGeometry.h @@ -0,0 +1,95 @@ +#include "Geometry.h" + +// Assuming abs(dw) <= dz +template +void rasterizeLineZW(int dz, int dw, F f) +{ + const int incW = dw >= 0 ? 1 : -1; + int z = 0, w = 0, err = 0; + // err / (2 * dz) is the fractional error in w + while (z <= dz) + { + f(z, w); + + err += 2 * dw * incW; + if (err >= dz) + { + w += incW; + err -= 2 * dz; + if (Ortho && z < dz) + f(z, w); + } + + z++; + } +} + +// Ortho makes the resulting line orthogonally connected +template +void RasterizeLine(Vec2 p1, Vec2 p2, F f) +{ + if(std::abs(p1.X - p2.X) >= std::abs(p1.Y - p2.Y)) + { + auto source = p1.X < p2.X ? p1 : p2; + auto delta = p1.X < p2.X ? p2 - p1 : p1 - p2; + rasterizeLineZW(delta.X, delta.Y, [source, f](int z, int w) { f(source + Vec2(z, w)); }); + } + else + { + auto source = p1.Y < p2.Y ? p1 : p2; + auto delta = p1.Y < p2.Y ? p2 - p1 : p1 - p2; + rasterizeLineZW(delta.Y, delta.X, [source, f](int z, int w) { f(source + Vec2(w, z)); }); + } +} + +template +void rasterizeEllipseQuadrant(Vec2 radiusSquared, F f) +{ + auto inEllipse = [=](int x, int y) + { + return y * y * radiusSquared.X + x * x * radiusSquared.Y <= radiusSquared.X * radiusSquared.Y; + }; + int x = int(std::floor(std::sqrt(radiusSquared.X))); + int maxY = int(std::floor(std::sqrt(radiusSquared.Y))); + for (int y = 0; y <= maxY; y++) + { + if (inEllipse(x, y + 1)) + { + f(x, x, y); + } + else + { + int xStart = x; + do + { + x--; + } while (x >= 0 && !inEllipse(x, y + 1)); + f(x + 1, xStart, y); + } + } +} + +template +void RasterizeEllipsePoints(Vec2 radiusSquared, F f) +{ + rasterizeEllipseQuadrant(radiusSquared, [f](int x1, int x2, int y) + { + for (int x = x1; x <= x2; x++) + { + f(Vec2(x, y)); + if (x) f(Vec2(-x, y)); + if (y) f(Vec2(x, -y)); + if (x && y) f(Vec2(-x, -y)); + } + }); +} + +template +void RasterizeEllipseRows(Vec2 radiusSquared, F f) +{ + rasterizeEllipseQuadrant(radiusSquared, [f](int _, int xLim, int y) + { + f(xLim, y); + if (y) f(xLim, -y); + }); +} diff --git a/src/graphics/RasterDrawMethods.inl b/src/graphics/RasterDrawMethods.inl index d57dc7df9..edfb8330c 100644 --- a/src/graphics/RasterDrawMethods.inl +++ b/src/graphics/RasterDrawMethods.inl @@ -1,5 +1,6 @@ -#include #include "FontReader.h" +#include "common/RasterGeometry.h" +#include int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a) { @@ -173,48 +174,8 @@ void PIXELMETHODS_CLASS::addpixel(int x, int y, int r, int g, int b, int a) void PIXELMETHODS_CLASS::xor_line(int x1, int y1, int x2, int y2) { - int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; - float e, de; - if (cp) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - e = 0.0f; - if (dx) - de = dy/(float)dx; - else - de = 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - e -= 1.0f; - } - } + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this](Vec2 p) { xor_pixel(p.X, p.Y); }); } void PIXELMETHODS_CLASS::xor_rect(int x, int y, int w, int h) @@ -263,48 +224,8 @@ void PIXELMETHODS_CLASS::xor_bitmap(unsigned char * bitmap, int x, int y, int w, void PIXELMETHODS_CLASS::draw_line(int x1, int y1, int x2, int y2, int r, int g, int b, int a) { - int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; - float e, de; - if (cp) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - e = 0.0f; - if (dx) - de = dy/(float)dx; - else - de = 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - e -= 1.0f; - } - } + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, r, g, b, a](Vec2 p) { blendpixel(p.X, p.Y, r, g, b, a); }); } void PIXELMETHODS_CLASS::drawrect(int x, int y, int w, int h, int r, int g, int b, int a) @@ -334,55 +255,17 @@ void PIXELMETHODS_CLASS::fillrect(int x, int y, int w, int h, int r, int g, int void PIXELMETHODS_CLASS::drawcircle(int x, int y, int rx, int ry, int r, int g, int b, int a) { - int yTop = ry, yBottom, i, j; - if (!rx) - { - for (j = -ry; j <= ry; j++) - blendpixel(x, y+j, r, g, b, a); - return; - } - for (i = 0; i <= rx; i++) { - yBottom = yTop; - while (pow(i-rx,2.0)*pow(ry,2.0) + pow(yTop-ry,2.0)*pow(rx,2.0) <= pow(rx,2.0)*pow(ry,2.0)) - yTop++; - if (yBottom != yTop) - yTop--; - for (int j = yBottom; j <= yTop; j++) - { - blendpixel(x+i-rx, y+j-ry, r, g, b, a); - if (i != rx) - blendpixel(x-i+rx, y+j-ry, r, g, b, a); - if (j != ry) - { - blendpixel(x+i-rx, y-j+ry, r, g, b, a); - if (i != rx) - blendpixel(x-i+rx, y-j+ry, r, g, b, a); - } - } - } + RasterizeEllipsePoints(Vec2(rx * rx, ry * ry), + [=](Vec2 p) { blendpixel(x + p.X, y + p.Y, r, g, b, a); }); } void PIXELMETHODS_CLASS::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int a) { - int yTop = ry+1, yBottom, i, j; - if (!rx) - { - for (j = -ry; j <= ry; j++) - blendpixel(x, y+j, r, g, b, a); - return; - } - for (i = 0; i <= rx; i++) - { - while (pow(i-rx,2.0)*pow(ry,2.0) + pow(yTop-ry,2.0)*pow(rx,2.0) <= pow(rx,2.0)*pow(ry,2.0)) - yTop++; - yBottom = 2*ry - yTop; - for (int j = yBottom+1; j < yTop; j++) + RasterizeEllipseRows(Vec2(rx * rx, ry * ry), [=](int xLim, int dy) { - blendpixel(x+i-rx, y+j-ry, r, g, b, a); - if (i != rx) - blendpixel(x-i+rx, y+j-ry, r, g, b, a); - } - } + for (int dx = -xLim; dx <= xLim; dx++) + blendpixel(x + dx, y + dy, r, g, b, a); + }); } void PIXELMETHODS_CLASS::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) diff --git a/src/gui/game/BitmapBrush.cpp b/src/gui/game/BitmapBrush.cpp index 3d4fbfda2..f4cd9b183 100644 --- a/src/gui/game/BitmapBrush.cpp +++ b/src/gui/game/BitmapBrush.cpp @@ -27,7 +27,7 @@ BitmapBrush::BitmapBrush(const BitmapBrush &other) : BitmapBrush(other.origSize, std::unique_ptr BitmapBrush::GenerateBitmap() const { - ui::Point size = radius * 2 + 1; + ui::Point size = radius * 2 + ui::Point(1, 1); auto bitmap = std::make_unique(size.X * size.Y); if (size == origSize) std::copy(&origBitmap[0], &origBitmap[origSize.X * origSize.Y], &bitmap[0]); diff --git a/src/gui/game/Brush.h b/src/gui/game/Brush.h index 5d56829cb..cdef216ba 100644 --- a/src/gui/game/Brush.h +++ b/src/gui/game/Brush.h @@ -63,7 +63,7 @@ public: ui::Point GetSize() const { - return radius * 2 + 1; + return radius * 2 + ui::Point(1, 1); } ui::Point GetRadius() const diff --git a/src/gui/game/DecorationTool.cpp b/src/gui/game/DecorationTool.cpp index 247318349..9be34fad2 100644 --- a/src/gui/game/DecorationTool.cpp +++ b/src/gui/game/DecorationTool.cpp @@ -62,22 +62,22 @@ DecorationTool::~DecorationTool() { } -void DecorationTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) +void DecorationTool::Draw(Simulation * sim, Brush const &brush, Pos position) { sim->ApplyDecorationPoint(position.X, position.Y, Red, Green, Blue, Alpha, toolID, brush); } -void DecorationTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) +void DecorationTool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { sim->ApplyDecorationLine(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID, brush); } -void DecorationTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) +void DecorationTool::DrawRect(Simulation * sim, Brush const &brush, Pos position1, Pos position2) { sim->ApplyDecorationBox(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID); } -void DecorationTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) +void DecorationTool::DrawFill(Simulation * sim, Brush const &brush, Pos position) { pixel loc = ren->vid[position.X+position.Y*WINDOWW]; if (toolID == DECO_CLEAR) diff --git a/src/gui/game/DecorationTool.h b/src/gui/game/DecorationTool.h index d5724a6cf..c5dd6cbdd 100644 --- a/src/gui/game/DecorationTool.h +++ b/src/gui/game/DecorationTool.h @@ -16,8 +16,8 @@ public: DecorationTool(Renderer *ren_, int decoMode, String name, String description, int r, int g, int b, ByteString identifier); virtual ~DecorationTool(); - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + void Draw(Simulation *, Brush const &, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override; + void DrawFill(Simulation *, Brush const &, Pos) override; }; diff --git a/src/gui/game/EllipseBrush.h b/src/gui/game/EllipseBrush.h index 865a53341..d226ad02d 100644 --- a/src/gui/game/EllipseBrush.h +++ b/src/gui/game/EllipseBrush.h @@ -1,4 +1,5 @@ #pragma once +#include "common/RasterGeometry.h" #include "Brush.h" #include @@ -15,52 +16,21 @@ public: std::unique_ptr GenerateBitmap() const override { - ui::Point size = radius * 2 + 1; + ui::Point size = radius * 2 + ui::Point(1, 1); auto bitmap = std::make_unique(size.X * size.Y); - int rx = radius.X; - int ry = radius.Y; - - if (!rx) + std::fill(&bitmap[0], &bitmap[size.X * size.Y], 0); + float rx = radius.X, ry = radius.Y; + if (perfectCircle) { - for (int j = 0; j <= 2*ry; j++) - { - bitmap[j*(size.X)+rx] = 255; - } + rx += 0.5; + ry += 0.5; } - else - { - int yTop = ry+1, yBottom, i; - for (i = 0; i <= rx; i++) + RasterizeEllipseRows(Vec2(rx * rx, ry * ry), [this, &bitmap, size](int xLim, int y) { - if (perfectCircle) - { - while (pow(i - rx, 2.0) * pow(ry - 0.5, 2.0) + pow(yTop - ry, 2.0) * pow(rx - 0.5, 2.0) <= pow(rx, 2.0) * pow(ry, 2.0)) - yTop++; - } - else - { - while (pow(i - rx, 2.0) * pow(ry, 2.0) + pow(yTop - ry, 2.0) * pow(rx, 2.0) <= pow(rx, 2.0) * pow(ry, 2.0)) - yTop++; - } - yBottom = 2*ry - yTop; - for (int j = 0; j <= ry*2; j++) - { - if (j > yBottom && j < yTop) - { - bitmap[j*(size.X)+i] = 255; - bitmap[j*(size.X)+2*rx-i] = 255; - } - else - { - bitmap[j*(size.X)+i] = 0; - bitmap[j*(size.X)+2*rx-i] = 0; - } - } - } - bitmap[size.X/2] = 255; - bitmap[size.X*size.Y-size.X/2-1] = 255; - } + for (int x = -xLim; x <= xLim; x++) + bitmap[x + radius.X + (y + radius.Y) * size.X] = 0xFF; + }); return bitmap; } diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp index 4878d6372..e2922fea8 100644 --- a/src/gui/game/PropertyTool.cpp +++ b/src/gui/game/PropertyTool.cpp @@ -1,5 +1,6 @@ #include "Tool.h" +#include "common/RasterGeometry.h" #include "prefs/GlobalPrefs.h" #include "Menu.h" #include "Format.h" @@ -255,7 +256,7 @@ void PropertyTool::OpenWindow(Simulation *sim) new PropertyWindow(this, sim); } -void PropertyTool::SetProperty(Simulation *sim, ui::Point position) +void PropertyTool::SetProperty(Simulation *sim, Pos position) { if(position.X<0 || position.X>XRES || position.Y<0 || position.Y>YRES || !validProperty) return; @@ -288,7 +289,7 @@ void PropertyTool::SetProperty(Simulation *sim, ui::Point position) } } -void PropertyTool::Draw(Simulation *sim, Brush const &cBrush, ui::Point position) +void PropertyTool::Draw(Simulation *sim, Brush const &cBrush, Pos position) { for (ui::Point off : cBrush) { @@ -298,61 +299,15 @@ void PropertyTool::Draw(Simulation *sim, Brush const &cBrush, ui::Point position } } -void PropertyTool::DrawLine(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point position2, bool dragging) +void PropertyTool::DrawLine(Simulation *sim, Brush const &cBrush, Pos position1, Pos position2, bool dragging) { - int x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y; - bool reverseXY = abs(y2-y1) > abs(x2-x1); - int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; - float e = 0.0f, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - if (dx) - de = dy/(float)dx; + if (cBrush.GetRadius() == Pos::Zero) + RasterizeLine(position1, position2, [this, sim, &cBrush](Pos p) { Draw(sim, cBrush, p); }); else - de = 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if (!(rx+ry) && ((y1=y2))) - { - if (reverseXY) - Draw(sim, cBrush, ui::Point(y, x)); - else - Draw(sim, cBrush, ui::Point(x, y)); - } - e -= 1.0f; - } - } + RasterizeLine(position1, position2, [this, sim, &cBrush](Pos p) { Draw(sim, cBrush, p); }); } -void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point position2) +void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, Pos position, Pos position2) { int x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y; int i, j; @@ -370,10 +325,10 @@ void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point posi } for (j=y1; j<=y2; j++) for (i=x1; i<=x2; i++) - SetProperty(sim, ui::Point(i, j)); + SetProperty(sim, Pos(i, j)); } -void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position) +void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, Pos position) { if (validProperty) sim->flood_prop(position.X, position.Y, propOffset, propValue, propType); diff --git a/src/gui/game/Tool.cpp b/src/gui/game/Tool.cpp index 92d83c08e..3d0d24f90 100644 --- a/src/gui/game/Tool.cpp +++ b/src/gui/game/Tool.cpp @@ -37,17 +37,17 @@ String Tool::GetName() { return toolName; } String Tool::GetDescription() { return toolDescription; } Tool::~Tool() {} -void Tool::Click(Simulation * sim, Brush const &brush, ui::Point position) { } -void Tool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { +void Tool::Click(Simulation * sim, Brush const &brush, Pos position) { } +void Tool::Draw(Simulation * sim, Brush const &brush, Pos position) { sim->ToolBrush(position.X, position.Y, toolID, brush, strength); } -void Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { +void Tool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { sim->ToolLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush, strength); } -void Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { +void Tool::DrawRect(Simulation * sim, Brush const &brush, Pos position1, Pos position2) { sim->ToolBox(position1.X, position1.Y, position2.X, position2.Y, toolID, strength); } -void Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) {} +void Tool::DrawFill(Simulation * sim, Brush const &brush, Pos position) {} ElementTool::ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int)): @@ -55,16 +55,17 @@ ElementTool::ElementTool(int id, String name, String description, int r, int g, { } ElementTool::~ElementTool() {} -void ElementTool::Draw(Simulation * sim, Brush const &brush, ui::Point position){ + +void ElementTool::Draw(Simulation * sim, Brush const &brush, Pos position){ sim->CreateParts(position.X, position.Y, toolID, brush); } -void ElementTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { +void ElementTool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush); } -void ElementTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { +void ElementTool::DrawRect(Simulation * sim, Brush const &brush, Pos position1, Pos position2) { sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID); } -void ElementTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) { +void ElementTool::DrawFill(Simulation * sim, Brush const &brush, Pos position) { sim->FloodParts(position.X, position.Y, toolID, -1); } @@ -75,10 +76,10 @@ Tool(id, name, description, r, g, b, identifier, textureGen) blocky = true; } WallTool::~WallTool() {} -void WallTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { +void WallTool::Draw(Simulation * sim, Brush const &brush, Pos position) { sim->CreateWalls(position.X, position.Y, 1, 1, toolID, &brush); } -void WallTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { +void WallTool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { int wallX = position1.X/CELL; int wallY = position1.Y/CELL; if(dragging == false && toolID == WL_FAN && sim->bmap[wallY][wallX]==WL_FAN) @@ -102,10 +103,10 @@ void WallTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position sim->CreateWallLine(position1.X, position1.Y, position2.X, position2.Y, 1, 1, toolID, &brush); } } -void WallTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { +void WallTool::DrawRect(Simulation * sim, Brush const &brush, Pos position1, Pos position2) { sim->CreateWallBox(position1.X, position1.Y, position2.X, position2.Y, toolID); } -void WallTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) { +void WallTool::DrawFill(Simulation * sim, Brush const &brush, Pos position) { if (toolID != WL_STREAM) sim->FloodWalls(position.X, position.Y, toolID, -1); } @@ -115,7 +116,7 @@ WindTool::WindTool(int id, String name, String description, int r, int g, int b, { } -void WindTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) +void WindTool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { float strength = dragging?0.01f:0.002f; strength *= this->strength; @@ -132,24 +133,24 @@ void WindTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position } -void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) +void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush const &brush, Pos position1, Pos position2, bool dragging) { if (dragging) sim->CreateParts(position1.X, position1.Y, brush.GetRadius().X, brush.GetRadius().Y, PT_LIGH); } -void Element_TESC_Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { +void Element_TESC_Tool::DrawRect(Simulation * sim, Brush const &brush, Pos position1, Pos position2) { int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7; sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID | PMAPID(radiusInfo)); } -void Element_TESC_Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) { +void Element_TESC_Tool::DrawFill(Simulation * sim, Brush const &brush, Pos position) { int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7; sim->FloodParts(position.X, position.Y, toolID | PMAPID(radiusInfo), -1); } -void PlopTool::Click(Simulation * sim, Brush const &brush, ui::Point position) +void PlopTool::Click(Simulation * sim, Brush const &brush, Pos position) { sim->create_part(-2, position.X, position.Y, TYP(toolID), ID(toolID)); } diff --git a/src/gui/game/Tool.h b/src/gui/game/Tool.h index 7ea84a5f1..5b324bd09 100644 --- a/src/gui/game/Tool.h +++ b/src/gui/game/Tool.h @@ -1,6 +1,6 @@ #pragma once +#include "common/Geometry.h" #include "common/String.h" -#include "gui/interface/Point.h" #include "simulation/StructProperty.h" class Simulation; @@ -10,6 +10,7 @@ class VideoBuffer; class Tool { protected: + using Pos = Vec2; VideoBuffer * (*textureGen)(int, int, int); int toolID; String toolName; @@ -31,11 +32,11 @@ public: VideoBuffer * GetTexture(int width, int height); void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int)); virtual ~Tool(); - virtual void Click(Simulation * sim, Brush const &brush, ui::Point position); - virtual void Draw(Simulation * sim, Brush const &brush, ui::Point position); - virtual void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false); - virtual void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2); - virtual void DrawFill(Simulation * sim, Brush const &brush, ui::Point position); + virtual void Click(Simulation *, Brush const &, Pos); + virtual void Draw(Simulation *, Brush const &, Pos); + virtual void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false); + virtual void DrawRect(Simulation *, Brush const &, Pos, Pos); + virtual void DrawFill(Simulation *, Brush const &, Pos); }; class GameModel; @@ -51,11 +52,11 @@ public: } static VideoBuffer * GetIcon(int toolID, int width, int height); virtual ~SignTool() {} - void Click(Simulation * sim, Brush const &brush, ui::Point position) override; - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } + void Click(Simulation *, Brush const &, Pos) override; + void Draw(Simulation *, Brush const &, Pos) override { } + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { } + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { } + void DrawFill(Simulation *, Brush const &, Pos) override { } }; class SampleTool: public Tool @@ -69,11 +70,11 @@ public: } static VideoBuffer * GetIcon(int toolID, int width, int height); virtual ~SampleTool() {} - void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } + void Click(Simulation *, Brush const &, Pos) override { } + void Draw(Simulation *, Brush const &, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { } + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { } + void DrawFill(Simulation *, Brush const &, Pos) override { } }; class PropertyTool: public Tool @@ -91,14 +92,14 @@ public: size_t propOffset; bool validProperty; - void OpenWindow(Simulation *sim); + void OpenWindow(Simulation *); virtual ~PropertyTool() {} - virtual void SetProperty(Simulation *sim, ui::Point position); - void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } - void Draw(Simulation *sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + virtual void SetProperty(Simulation *, Pos); + void Click(Simulation *, Brush const &, Pos) override { } + void Draw(Simulation *, Brush const &brush, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override; + void DrawFill(Simulation *, Brush const &, Pos) override; }; class GOLTool: public Tool @@ -110,13 +111,13 @@ public: gameModel(gameModel) { } - void OpenWindow(Simulation *sim, int toolSelection, int rule = 0, int colour1 = 0, int colour2 = 0); + void OpenWindow(Simulation *, int toolSelection, int rule = 0, int colour1 = 0, int colour2 = 0); virtual ~GOLTool() {} - void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } - void Draw(Simulation *sim, Brush const &brush, ui::Point position) override { }; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }; + void Click(Simulation *, Brush const &, Pos) override { } + void Draw(Simulation *, Brush const &brush, Pos) override { }; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { }; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }; + void DrawFill(Simulation *, Brush const &, Pos) override { }; }; @@ -125,10 +126,10 @@ class ElementTool: public Tool public: ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); virtual ~ElementTool(); - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + void Draw(Simulation *, Brush const &, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override; + void DrawFill(Simulation *, Brush const &, Pos) override; }; class Element_LIGH_Tool: public ElementTool @@ -138,10 +139,10 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~Element_LIGH_Tool() { } - void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } + void Click(Simulation *, Brush const &, Pos) override { } + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { } + void DrawFill(Simulation *, Brush const &, Pos) override { } }; class Element_TESC_Tool: public ElementTool @@ -151,8 +152,8 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~Element_TESC_Tool() {} - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override; + void DrawFill(Simulation *, Brush const &, Pos) override; }; class PlopTool: public ElementTool @@ -162,11 +163,11 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~PlopTool() { } - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } - void Click(Simulation * sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } + void Draw(Simulation *, Brush const &, Pos) override { } + void Click(Simulation *, Brush const &, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { } + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { } + void DrawFill(Simulation *, Brush const &, Pos) override { } }; class WallTool: public Tool @@ -174,10 +175,10 @@ class WallTool: public Tool public: WallTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); virtual ~WallTool(); - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; + void Draw(Simulation *, Brush const &, Pos) override; + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override; + void DrawFill(Simulation *, Brush const &, Pos) override; }; class WindTool: public Tool @@ -185,8 +186,8 @@ class WindTool: public Tool public: WindTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); virtual ~WindTool() { } - void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } + void Draw(Simulation *, Brush const &, Pos) override { } + void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override; + void DrawRect(Simulation *, Brush const &, Pos, Pos) override { } + void DrawFill(Simulation *, Brush const &, Pos) override { } }; diff --git a/src/gui/game/TriangleBrush.h b/src/gui/game/TriangleBrush.h index e9e8695dc..e8ac33f59 100644 --- a/src/gui/game/TriangleBrush.h +++ b/src/gui/game/TriangleBrush.h @@ -9,7 +9,7 @@ public: std::unique_ptr GenerateBitmap() const override { - ui::Point size = radius * 2 + 1; + ui::Point size = radius * 2 + ui::Point(1, 1); auto bitmap = std::make_unique(size.X * size.Y); int rx = radius.X; diff --git a/src/simulation/Editing.cpp b/src/simulation/Editing.cpp index ccfa86f92..25d342b98 100644 --- a/src/simulation/Editing.cpp +++ b/src/simulation/Editing.cpp @@ -5,6 +5,7 @@ #include "Snapshot.h" #include "Air.h" #include "gravity/Gravity.h" +#include "common/RasterGeometry.h" #include "common/tpt-rand.h" #include "common/tpt-compat.h" #include "client/GameSave.h" @@ -242,52 +243,8 @@ int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush const void Simulation::CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush const *cBrush) { - int x, y, dx, dy, sy; - bool reverseXY = abs(y2-y1) > abs(x2-x1); - float e = 0.0f, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - de = dx ? dy/(float)dx : 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if ((y1=y2)) - { - if (reverseXY) - CreateWalls(y, x, rx, ry, wall, cBrush); - else - CreateWalls(x, y, rx, ry, wall, cBrush); - } - e -= 1.0f; - } - } + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [=](Vec2 p) { CreateWalls(p.X, p.Y, rx, ry, wall, cBrush); }); } void Simulation::CreateWallBox(int x1, int y1, int x2, int y2, int wall) @@ -621,56 +578,12 @@ void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, in void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush) { - bool reverseXY = abs(y2-y1) > abs(x2-x1); - int x, y, dx, dy, sy, rx = 0, ry = 0; - float e = 0.0f, de; - - rx = cBrush.GetRadius().X; - ry = cBrush.GetRadius().Y; - - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - de = dx ? dy/(float)dx : 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if (!(rx+ry)) - { - if (reverseXY) - ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush); - else - ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush); - } - e -= 1.0f; - } - } + if (cBrush.GetRadius() == Vec2::Zero) + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, colR, colG, colB, colA, mode, &cBrush](Vec2 p) { ApplyDecorationPoint(p.X, p.Y, colR, colG, colB, colA, mode, cBrush); }); + else + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, colR, colG, colB, colA, mode, &cBrush](Vec2 p) { ApplyDecorationPoint(p.X, p.Y, colR, colG, colB, colA, mode, cBrush); }); } void Simulation::ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode) @@ -785,52 +698,12 @@ int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush const &c void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush const &cBrush, float strength) { - bool reverseXY = abs(y2-y1) > abs(x2-x1); - int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; - float e = 0.0f, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - de = dx ? dy/(float)dx : 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if (!(rx+ry) && ((y1=y2))) - { - if (reverseXY) - ToolBrush(y, x, tool, cBrush, strength); - else - ToolBrush(x, y, tool, cBrush, strength); - } - e -= 1.0f; - } - } + if (cBrush.GetRadius() == Vec2::Zero) + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, tool, strength, &cBrush](Vec2 p) { ToolBrush(p.X, p.Y, tool, cBrush, strength); }); + else + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, tool, strength, &cBrush](Vec2 p) { ToolBrush(p.X, p.Y, tool, cBrush, strength); }); } void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float strength) @@ -927,52 +800,12 @@ int Simulation::CreateParts(int x, int y, int rx, int ry, int c, int flags) void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush const &cBrush, int flags) { - int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; - bool reverseXY = abs(y2-y1) > abs(x2-x1); - float e = 0.0f, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - de = dx ? dy/(float)dx : 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if (!(rx+ry) && ((y1=y2))) - { - if (reverseXY) - CreateParts(y, x, c, cBrush, flags); - else - CreateParts(x, y, c, cBrush, flags); - } - e -= 1.0f; - } - } + if (cBrush.GetRadius() == Vec2::Zero) + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, c, flags, &cBrush](Vec2 p) { CreateParts(p.X, p.Y, c, cBrush, flags); }); + else + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [this, c, flags, &cBrush](Vec2 p) { CreateParts(p.X, p.Y, c, cBrush, flags); }); } void Simulation::CreateBox(int x1, int y1, int x2, int y2, int c, int flags) diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index a0a45f903..c56215f5f 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -6,6 +6,7 @@ #include "SimulationData.h" #include "GOLString.h" #include "client/GameSave.h" +#include "common/RasterGeometry.h" #include "common/tpt-compat.h" #include "common/tpt-rand.h" #include "common/tpt-thread-local.h" @@ -837,55 +838,10 @@ void Simulation::SetEdgeMode(int newEdgeMode) // Would make sense to move to Editing.cpp but SPRK needs it. void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c) { - bool reverseXY = abs(y2-y1) > abs(x2-x1); - int x, y, dx, dy, sy; - float e, de; int v = ID(c); c = TYP(c); - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - e = 0.0f; - de = dx ? dy/(float)dx : 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if ((y1=y2)) - { - if (reverseXY) - create_part(-1, y, x, c, v); - else - create_part(-1, x, y, c, v); - } - e -= 1.0f; - } - } + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [=](Vec2 p) { create_part(-1, p.X, p.Y, c, v); }); } void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]) diff --git a/src/simulation/elements/HEAC.cpp b/src/simulation/elements/HEAC.cpp index 0a11cee77..9758374d3 100644 --- a/src/simulation/elements/HEAC.cpp +++ b/src/simulation/elements/HEAC.cpp @@ -1,3 +1,4 @@ +#include "common/RasterGeometry.h" #include "simulation/ElementCommon.h" #include "simulation/Air.h" @@ -55,65 +56,13 @@ static const auto isInsulator = [](Simulation* a, int b) -> bool { template bool CheckLine(Simulation* sim, int x1, int y1, int x2, int y2, BinaryPredicate func) { - bool reverseXY = abs(y2-y1) > abs(x2-x1); - int x, y, dx, dy, sy; - float e, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - e = 0.0f; - if (dx) - de = dy/(float)dx; - else - de = 0.0f; - y = y1; - sy = (y1(Vec2(x1, y1), Vec2(x2, y2), [func, sim, &found](Vec2 p) { - if (func(sim, sim->pmap[x][y])) return true; - } - else - { - if (func(sim, sim->pmap[y][x])) return true; - } - e += de; - if (e >= 0.5f) - { - y += sy; - if ((y1=y2)) - { - if (reverseXY) - { - if (func(sim, sim->pmap[x][y])) return true; - } - else - { - if (func(sim, sim->pmap[y][x])) return true; - } - } - e -= 1.0f; - } - } - return false; + if (!found) + found = func(sim, sim->pmap[p.Y][p.X]); + }); + return found; } static int update(UPDATE_FUNC_ARGS) diff --git a/src/simulation/elements/LIGH.cpp b/src/simulation/elements/LIGH.cpp index ade7e005d..5f88276f6 100644 --- a/src/simulation/elements/LIGH.cpp +++ b/src/simulation/elements/LIGH.cpp @@ -1,3 +1,4 @@ +#include "common/RasterGeometry.h" #include "simulation/ElementCommon.h" static int update(UPDATE_FUNC_ARGS); @@ -225,68 +226,23 @@ static bool create_LIGH(Simulation * sim, int x, int y, int c, float temp, int l static void create_line_par(Simulation * sim, int x1, int y1, int x2, int y2, int c, float temp, int life, int tmp, int tmp2, int i) { - bool reverseXY = abs(y2-y1) > abs(x2-x1), back = false; - int x, y, dx, dy, Ystep; - float e = 0.0f, de; - if (reverseXY) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - back = 1; - dx = x2 - x1; - dy = abs(y2 - y1); - if (dx) - de = dy/(float)dx; - else - de = 0.0f; - y = y1; - Ystep = (y1= 0.5f) + // force particles to be created in order from (x1,y1) to (x2,y2) + bool back = std::abs(x1 - x2) >= std::abs(y2 - y1) ? x1 >= x2 : y1 >= y2; + bool done = false; + if (back) + RasterizeLine(Vec2(x1, y1), Vec2(x2, y2), + [&done, sim, c, temp, life, tmp, tmp2, x2, y2, i] (Vec2 p) { - y += Ystep; - e -= 1.0f; - } - } - } + if (!done) + done = create_LIGH(sim, p.X, p.Y, c, temp, life, tmp, tmp2, p == Vec2(x2, y2), i); + }); else - { - for (x = x1; x >= x2; x--) - { - bool ret; - if (reverseXY) - ret = create_LIGH(sim, y, x, c, temp, life, tmp, tmp2,x==x2, i); - else - ret = create_LIGH(sim, x, y, c, temp, life, tmp, tmp2,x==x2, i); - if (ret) - return; - - e += de; - if (e <= -0.5f) + RasterizeLine(-Vec2(x1, y1), -Vec2(x2, y2), + [&done, sim, c, temp, life, tmp, tmp2, x2, y2, i] (Vec2 p) { - y += Ystep; - e += 1.0f; - } - } - } + if (!done) + done = create_LIGH(sim, -p.X, -p.Y, c, temp, life, tmp, tmp2, -p == Vec2(x2, y2), i); + }); } static int graphics(GRAPHICS_FUNC_ARGS)