Refactor rasterized line/ellipse calculation code

This commit is contained in:
mniip 2023-02-20 14:48:32 +01:00
parent 7d9fdfea4e
commit e937c3d254
15 changed files with 257 additions and 658 deletions

View File

@ -0,0 +1,95 @@
#include "Geometry.h"
// Assuming abs(dw) <= dz
template<bool Ortho, typename F>
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<bool Ortho, typename F>
void RasterizeLine(Vec2<int> p1, Vec2<int> 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<Ortho>(delta.X, delta.Y, [source, f](int z, int w) { f(source + Vec2<int>(z, w)); });
}
else
{
auto source = p1.Y < p2.Y ? p1 : p2;
auto delta = p1.Y < p2.Y ? p2 - p1 : p1 - p2;
rasterizeLineZW<Ortho>(delta.Y, delta.X, [source, f](int z, int w) { f(source + Vec2<int>(w, z)); });
}
}
template<typename F>
void rasterizeEllipseQuadrant(Vec2<float> 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<typename F>
void RasterizeEllipsePoints(Vec2<float> radiusSquared, F f)
{
rasterizeEllipseQuadrant(radiusSquared, [f](int x1, int x2, int y)
{
for (int x = x1; x <= x2; x++)
{
f(Vec2<int>(x, y));
if (x) f(Vec2<int>(-x, y));
if (y) f(Vec2<int>(x, -y));
if (x && y) f(Vec2<int>(-x, -y));
}
});
}
template<typename F>
void RasterizeEllipseRows(Vec2<float> radiusSquared, F f)
{
rasterizeEllipseQuadrant(radiusSquared, [f](int _, int xLim, int y)
{
f(xLim, y);
if (y) f(xLim, -y);
});
}

View File

@ -1,5 +1,6 @@
#include <cmath>
#include "FontReader.h" #include "FontReader.h"
#include "common/RasterGeometry.h"
#include <cmath>
int PIXELMETHODS_CLASS::drawtext_outline(int x, int y, const String &s, int r, int g, int b, int a) 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) 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; RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
float e, de; [this](Vec2<int> p) { xor_pixel(p.X, p.Y); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (cp)
xor_pixel(y, x);
else
xor_pixel(x, y);
e += de;
if (e >= 0.5f)
{
y += sy;
e -= 1.0f;
}
}
} }
void PIXELMETHODS_CLASS::xor_rect(int x, int y, int w, int h) 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) 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; RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
float e, de; [this, r, g, b, a](Vec2<int> p) { blendpixel(p.X, p.Y, r, g, b, a); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (cp)
blendpixel(y, x, r, g, b, a);
else
blendpixel(x, y, r, g, b, a);
e += de;
if (e >= 0.5f)
{
y += sy;
e -= 1.0f;
}
}
} }
void PIXELMETHODS_CLASS::drawrect(int x, int y, int w, int h, int r, int g, int b, int 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) 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; RasterizeEllipsePoints(Vec2<float>(rx * rx, ry * ry),
if (!rx) [=](Vec2<int> p) { blendpixel(x + p.X, y + p.Y, r, g, b, a); });
{
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);
}
}
}
} }
void PIXELMETHODS_CLASS::fillcircle(int x, int y, int rx, int ry, int r, int g, int b, int 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; RasterizeEllipseRows(Vec2<float>(rx * rx, ry * ry), [=](int xLim, int dy)
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++)
{ {
blendpixel(x+i-rx, y+j-ry, r, g, b, a); for (int dx = -xLim; dx <= xLim; dx++)
if (i != rx) blendpixel(x + dx, y + dy, r, g, b, a);
blendpixel(x-i+rx, y+j-ry, 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) 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)

View File

@ -27,7 +27,7 @@ BitmapBrush::BitmapBrush(const BitmapBrush &other) : BitmapBrush(other.origSize,
std::unique_ptr<unsigned char []> BitmapBrush::GenerateBitmap() const std::unique_ptr<unsigned char []> BitmapBrush::GenerateBitmap() const
{ {
ui::Point size = radius * 2 + 1; ui::Point size = radius * 2 + ui::Point(1, 1);
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y); auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
if (size == origSize) if (size == origSize)
std::copy(&origBitmap[0], &origBitmap[origSize.X * origSize.Y], &bitmap[0]); std::copy(&origBitmap[0], &origBitmap[origSize.X * origSize.Y], &bitmap[0]);

View File

@ -63,7 +63,7 @@ public:
ui::Point GetSize() const ui::Point GetSize() const
{ {
return radius * 2 + 1; return radius * 2 + ui::Point(1, 1);
} }
ui::Point GetRadius() const ui::Point GetRadius() const

View File

@ -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); 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); 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); 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]; pixel loc = ren->vid[position.X+position.Y*WINDOWW];
if (toolID == DECO_CLEAR) if (toolID == DECO_CLEAR)

View File

@ -16,8 +16,8 @@ public:
DecorationTool(Renderer *ren_, int decoMode, String name, String description, int r, int g, int b, ByteString identifier); DecorationTool(Renderer *ren_, int decoMode, String name, String description, int r, int g, int b, ByteString identifier);
virtual ~DecorationTool(); virtual ~DecorationTool();
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; void Draw(Simulation *, Brush const &, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawRect(Simulation *, Brush const &, Pos, Pos) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; void DrawFill(Simulation *, Brush const &, Pos) override;
}; };

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "common/RasterGeometry.h"
#include "Brush.h" #include "Brush.h"
#include <cmath> #include <cmath>
@ -15,52 +16,21 @@ public:
std::unique_ptr<unsigned char []> GenerateBitmap() const override std::unique_ptr<unsigned char []> GenerateBitmap() const override
{ {
ui::Point size = radius * 2 + 1; ui::Point size = radius * 2 + ui::Point(1, 1);
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y); auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
int rx = radius.X; std::fill(&bitmap[0], &bitmap[size.X * size.Y], 0);
int ry = radius.Y; float rx = radius.X, ry = radius.Y;
if (perfectCircle)
if (!rx)
{ {
for (int j = 0; j <= 2*ry; j++) rx += 0.5;
{ ry += 0.5;
bitmap[j*(size.X)+rx] = 255;
}
} }
else RasterizeEllipseRows(Vec2<float>(rx * rx, ry * ry), [this, &bitmap, size](int xLim, int y)
{
int yTop = ry+1, yBottom, i;
for (i = 0; i <= rx; i++)
{ {
if (perfectCircle) for (int x = -xLim; x <= xLim; x++)
{ bitmap[x + radius.X + (y + radius.Y) * size.X] = 0xFF;
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;
}
return bitmap; return bitmap;
} }

View File

@ -1,5 +1,6 @@
#include "Tool.h" #include "Tool.h"
#include "common/RasterGeometry.h"
#include "prefs/GlobalPrefs.h" #include "prefs/GlobalPrefs.h"
#include "Menu.h" #include "Menu.h"
#include "Format.h" #include "Format.h"
@ -255,7 +256,7 @@ void PropertyTool::OpenWindow(Simulation *sim)
new PropertyWindow(this, 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) if(position.X<0 || position.X>XRES || position.Y<0 || position.Y>YRES || !validProperty)
return; 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) 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; if (cBrush.GetRadius() == Pos::Zero)
bool reverseXY = abs(y2-y1) > abs(x2-x1); RasterizeLine<true>(position1, position2, [this, sim, &cBrush](Pos p) { Draw(sim, cBrush, p); });
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;
else else
de = 0.0f; RasterizeLine<false>(position1, position2, [this, sim, &cBrush](Pos p) { Draw(sim, cBrush, p); });
y = y1;
sy = (y1<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
Draw(sim, cBrush, ui::Point(y, x));
else
Draw(sim, cBrush, ui::Point(x, y));
e += de;
if (e >= 0.5f)
{
y += sy;
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
{
if (reverseXY)
Draw(sim, cBrush, ui::Point(y, x));
else
Draw(sim, cBrush, ui::Point(x, y));
}
e -= 1.0f;
}
}
} }
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 x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y;
int i, j; 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 (j=y1; j<=y2; j++)
for (i=x1; i<=x2; i++) 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) if (validProperty)
sim->flood_prop(position.X, position.Y, propOffset, propValue, propType); sim->flood_prop(position.X, position.Y, propOffset, propValue, propType);

View File

@ -37,17 +37,17 @@ String Tool::GetName() { return toolName; }
String Tool::GetDescription() { return toolDescription; } String Tool::GetDescription() { return toolDescription; }
Tool::~Tool() {} Tool::~Tool() {}
void Tool::Click(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, ui::Point position) { void Tool::Draw(Simulation * sim, Brush const &brush, Pos position) {
sim->ToolBrush(position.X, position.Y, toolID, brush, strength); 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); 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); 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)): 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() {} 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); 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); 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); 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); sim->FloodParts(position.X, position.Y, toolID, -1);
} }
@ -75,10 +76,10 @@ Tool(id, name, description, r, g, b, identifier, textureGen)
blocky = true; blocky = true;
} }
WallTool::~WallTool() {} 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); 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 wallX = position1.X/CELL;
int wallY = position1.Y/CELL; int wallY = position1.Y/CELL;
if(dragging == false && toolID == WL_FAN && sim->bmap[wallY][wallX]==WL_FAN) 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); 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); 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) if (toolID != WL_STREAM)
sim->FloodWalls(position.X, position.Y, toolID, -1); 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; float strength = dragging?0.01f:0.002f;
strength *= this->strength; 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) if (dragging)
sim->CreateParts(position1.X, position1.Y, brush.GetRadius().X, brush.GetRadius().Y, PT_LIGH); 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; int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7;
sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID | PMAPID(radiusInfo)); 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; int radiusInfo = brush.GetRadius().X*4+brush.GetRadius().Y*4+7;
sim->FloodParts(position.X, position.Y, toolID | PMAPID(radiusInfo), -1); 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)); sim->create_part(-2, position.X, position.Y, TYP(toolID), ID(toolID));
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "common/Geometry.h"
#include "common/String.h" #include "common/String.h"
#include "gui/interface/Point.h"
#include "simulation/StructProperty.h" #include "simulation/StructProperty.h"
class Simulation; class Simulation;
@ -10,6 +10,7 @@ class VideoBuffer;
class Tool class Tool
{ {
protected: protected:
using Pos = Vec2<int>;
VideoBuffer * (*textureGen)(int, int, int); VideoBuffer * (*textureGen)(int, int, int);
int toolID; int toolID;
String toolName; String toolName;
@ -31,11 +32,11 @@ public:
VideoBuffer * GetTexture(int width, int height); VideoBuffer * GetTexture(int width, int height);
void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int)); void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int));
virtual ~Tool(); virtual ~Tool();
virtual void Click(Simulation * sim, Brush const &brush, ui::Point position); virtual void Click(Simulation *, Brush const &, Pos);
virtual void Draw(Simulation * sim, Brush const &brush, ui::Point position); virtual void Draw(Simulation *, Brush const &, Pos);
virtual void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false); virtual void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false);
virtual void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2); virtual void DrawRect(Simulation *, Brush const &, Pos, Pos);
virtual void DrawFill(Simulation * sim, Brush const &brush, ui::Point position); virtual void DrawFill(Simulation *, Brush const &, Pos);
}; };
class GameModel; class GameModel;
@ -51,11 +52,11 @@ public:
} }
static VideoBuffer * GetIcon(int toolID, int width, int height); static VideoBuffer * GetIcon(int toolID, int width, int height);
virtual ~SignTool() {} virtual ~SignTool() {}
void Click(Simulation * sim, Brush const &brush, ui::Point position) override; void Click(Simulation *, Brush const &, Pos) override;
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } void Draw(Simulation *, Brush const &, Pos) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } void DrawFill(Simulation *, Brush const &, Pos) override { }
}; };
class SampleTool: public Tool class SampleTool: public Tool
@ -69,11 +70,11 @@ public:
} }
static VideoBuffer * GetIcon(int toolID, int width, int height); static VideoBuffer * GetIcon(int toolID, int width, int height);
virtual ~SampleTool() {} virtual ~SampleTool() {}
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } void Click(Simulation *, Brush const &, Pos) override { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; void Draw(Simulation *, Brush const &, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } void DrawFill(Simulation *, Brush const &, Pos) override { }
}; };
class PropertyTool: public Tool class PropertyTool: public Tool
@ -91,14 +92,14 @@ public:
size_t propOffset; size_t propOffset;
bool validProperty; bool validProperty;
void OpenWindow(Simulation *sim); void OpenWindow(Simulation *);
virtual ~PropertyTool() {} virtual ~PropertyTool() {}
virtual void SetProperty(Simulation *sim, ui::Point position); virtual void SetProperty(Simulation *, Pos);
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } void Click(Simulation *, Brush const &, Pos) override { }
void Draw(Simulation *sim, Brush const &brush, ui::Point position) override; void Draw(Simulation *, Brush const &brush, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawRect(Simulation *, Brush const &, Pos, Pos) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; void DrawFill(Simulation *, Brush const &, Pos) override;
}; };
class GOLTool: public Tool class GOLTool: public Tool
@ -110,13 +111,13 @@ public:
gameModel(gameModel) 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() {} virtual ~GOLTool() {}
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } void Click(Simulation *, Brush const &, Pos) override { }
void Draw(Simulation *sim, Brush const &brush, ui::Point position) override { }; void Draw(Simulation *, Brush const &brush, Pos) override { };
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { };
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { }; void DrawRect(Simulation *, Brush const &, Pos, Pos) override { };
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { }; void DrawFill(Simulation *, Brush const &, Pos) override { };
}; };
@ -125,10 +126,10 @@ class ElementTool: public Tool
public: public:
ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); ElementTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~ElementTool(); virtual ~ElementTool();
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; void Draw(Simulation *, Brush const &, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawRect(Simulation *, Brush const &, Pos, Pos) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; void DrawFill(Simulation *, Brush const &, Pos) override;
}; };
class Element_LIGH_Tool: public ElementTool class Element_LIGH_Tool: public ElementTool
@ -138,10 +139,10 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen) ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ } { }
virtual ~Element_LIGH_Tool() { } virtual ~Element_LIGH_Tool() { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override { } void Click(Simulation *, Brush const &, Pos) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } void DrawFill(Simulation *, Brush const &, Pos) override { }
}; };
class Element_TESC_Tool: public ElementTool class Element_TESC_Tool: public ElementTool
@ -151,8 +152,8 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen) ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ } { }
virtual ~Element_TESC_Tool() {} virtual ~Element_TESC_Tool() {}
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawRect(Simulation *, Brush const &, Pos, Pos) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; void DrawFill(Simulation *, Brush const &, Pos) override;
}; };
class PlopTool: public ElementTool class PlopTool: public ElementTool
@ -162,11 +163,11 @@ public:
ElementTool(id, name, description, r, g, b, identifier, textureGen) ElementTool(id, name, description, r, g, b, identifier, textureGen)
{ } { }
virtual ~PlopTool() { } virtual ~PlopTool() { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } void Draw(Simulation *, Brush const &, Pos) override { }
void Click(Simulation * sim, Brush const &brush, ui::Point position) override; void Click(Simulation *, Brush const &, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override { }
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } void DrawFill(Simulation *, Brush const &, Pos) override { }
}; };
class WallTool: public Tool class WallTool: public Tool
@ -174,10 +175,10 @@ class WallTool: public Tool
public: public:
WallTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); WallTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~WallTool(); virtual ~WallTool();
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override; void Draw(Simulation *, Brush const &, Pos) override;
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override; void DrawRect(Simulation *, Brush const &, Pos, Pos) override;
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override; void DrawFill(Simulation *, Brush const &, Pos) override;
}; };
class WindTool: public Tool class WindTool: public Tool
@ -185,8 +186,8 @@ class WindTool: public Tool
public: public:
WindTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL); WindTool(int id, String name, String description, int r, int g, int b, ByteString identifier, VideoBuffer * (*textureGen)(int, int, int) = NULL);
virtual ~WindTool() { } virtual ~WindTool() { }
void Draw(Simulation * sim, Brush const &brush, ui::Point position) override { } void Draw(Simulation *, Brush const &, Pos) override { }
void DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging = false) override; void DrawLine(Simulation *, Brush const &, Pos, Pos, bool dragging = false) override;
void DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) override { } void DrawRect(Simulation *, Brush const &, Pos, Pos) override { }
void DrawFill(Simulation * sim, Brush const &brush, ui::Point position) override { } void DrawFill(Simulation *, Brush const &, Pos) override { }
}; };

View File

@ -9,7 +9,7 @@ public:
std::unique_ptr<unsigned char []> GenerateBitmap() const override std::unique_ptr<unsigned char []> GenerateBitmap() const override
{ {
ui::Point size = radius * 2 + 1; ui::Point size = radius * 2 + ui::Point(1, 1);
auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y); auto bitmap = std::make_unique<unsigned char []>(size.X * size.Y);
int rx = radius.X; int rx = radius.X;

View File

@ -5,6 +5,7 @@
#include "Snapshot.h" #include "Snapshot.h"
#include "Air.h" #include "Air.h"
#include "gravity/Gravity.h" #include "gravity/Gravity.h"
#include "common/RasterGeometry.h"
#include "common/tpt-rand.h" #include "common/tpt-rand.h"
#include "common/tpt-compat.h" #include "common/tpt-compat.h"
#include "client/GameSave.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) 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; RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
bool reverseXY = abs(y2-y1) > abs(x2-x1); [=](Vec2<int> p) { CreateWalls(p.X, p.Y, rx, ry, wall, cBrush); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
CreateWalls(y, x, rx, ry, wall, cBrush);
else
CreateWalls(x, y, rx, ry, wall, cBrush);
e += de;
if (e >= 0.5f)
{
y += sy;
if ((y1<y2) ? (y<=y2) : (y>=y2))
{
if (reverseXY)
CreateWalls(y, x, rx, ry, wall, cBrush);
else
CreateWalls(x, y, rx, ry, wall, cBrush);
}
e -= 1.0f;
}
}
} }
void Simulation::CreateWallBox(int x1, int y1, int x2, int y2, int wall) 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) 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); if (cBrush.GetRadius() == Vec2<int>::Zero)
int x, y, dx, dy, sy, rx = 0, ry = 0; RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
float e = 0.0f, de; [this, colR, colG, colB, colA, mode, &cBrush](Vec2<int> p) { ApplyDecorationPoint(p.X, p.Y, colR, colG, colB, colA, mode, cBrush); });
else
rx = cBrush.GetRadius().X; RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
ry = cBrush.GetRadius().Y; [this, colR, colG, colB, colA, mode, &cBrush](Vec2<int> p) { ApplyDecorationPoint(p.X, p.Y, colR, colG, colB, colA, mode, cBrush); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
ApplyDecorationPoint(y, x, colR, colG, colB, colA, mode, cBrush);
else
ApplyDecorationPoint(x, y, colR, colG, colB, colA, mode, cBrush);
e += de;
if (e >= 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;
}
}
} }
void Simulation::ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode) 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) 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); if (cBrush.GetRadius() == Vec2<int>::Zero)
int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
float e = 0.0f, de; [this, tool, strength, &cBrush](Vec2<int> p) { ToolBrush(p.X, p.Y, tool, cBrush, strength); });
if (reverseXY) else
{ RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
y = x1; [this, tool, strength, &cBrush](Vec2<int> p) { ToolBrush(p.X, p.Y, tool, cBrush, strength); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
ToolBrush(y, x, tool, cBrush, strength);
else
ToolBrush(x, y, tool, cBrush, strength);
e += de;
if (e >= 0.5f)
{
y += sy;
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
{
if (reverseXY)
ToolBrush(y, x, tool, cBrush, strength);
else
ToolBrush(x, y, tool, cBrush, strength);
}
e -= 1.0f;
}
}
} }
void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float 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) 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; if (cBrush.GetRadius() == Vec2<int>::Zero)
bool reverseXY = abs(y2-y1) > abs(x2-x1); RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
float e = 0.0f, de; [this, c, flags, &cBrush](Vec2<int> p) { CreateParts(p.X, p.Y, c, cBrush, flags); });
if (reverseXY) else
{ RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
y = x1; [this, c, flags, &cBrush](Vec2<int> p) { CreateParts(p.X, p.Y, c, cBrush, flags); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
CreateParts(y, x, c, cBrush, flags);
else
CreateParts(x, y, c, cBrush, flags);
e += de;
if (e >= 0.5f)
{
y += sy;
if (!(rx+ry) && ((y1<y2) ? (y<=y2) : (y>=y2)))
{
if (reverseXY)
CreateParts(y, x, c, cBrush, flags);
else
CreateParts(x, y, c, cBrush, flags);
}
e -= 1.0f;
}
}
} }
void Simulation::CreateBox(int x1, int y1, int x2, int y2, int c, int flags) void Simulation::CreateBox(int x1, int y1, int x2, int y2, int c, int flags)

View File

@ -6,6 +6,7 @@
#include "SimulationData.h" #include "SimulationData.h"
#include "GOLString.h" #include "GOLString.h"
#include "client/GameSave.h" #include "client/GameSave.h"
#include "common/RasterGeometry.h"
#include "common/tpt-compat.h" #include "common/tpt-compat.h"
#include "common/tpt-rand.h" #include "common/tpt-rand.h"
#include "common/tpt-thread-local.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. // 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) 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); int v = ID(c);
c = TYP(c); c = TYP(c);
if (reverseXY) RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
{ [=](Vec2<int> p) { create_part(-1, p.X, p.Y, c, v); });
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
create_part(-1, y, x, c, v);
else
create_part(-1, x, y, c, v);
e += de;
if (e >= 0.5f)
{
y += sy;
if ((y1<y2) ? (y<=y2) : (y>=y2))
{
if (reverseXY)
create_part(-1, y, x, c, v);
else
create_part(-1, x, y, c, v);
}
e -= 1.0f;
}
}
} }
void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]) void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[])

View File

@ -1,3 +1,4 @@
#include "common/RasterGeometry.h"
#include "simulation/ElementCommon.h" #include "simulation/ElementCommon.h"
#include "simulation/Air.h" #include "simulation/Air.h"
@ -55,65 +56,13 @@ static const auto isInsulator = [](Simulation* a, int b) -> bool {
template<class BinaryPredicate> template<class BinaryPredicate>
bool CheckLine(Simulation* sim, int x1, int y1, int x2, int y2, BinaryPredicate func) bool CheckLine(Simulation* sim, int x1, int y1, int x2, int y2, BinaryPredicate func)
{ {
bool reverseXY = abs(y2-y1) > abs(x2-x1); bool found = false;
int x, y, dx, dy, sy; RasterizeLine<true>(Vec2<int>(x1, y1), Vec2<int>(x2, y2), [func, sim, &found](Vec2<int> p)
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<y2) ? 1 : -1;
for (x=x1; x<=x2; x++)
{
if (reverseXY)
{ {
if (func(sim, sim->pmap[x][y])) return true; if (!found)
} found = func(sim, sim->pmap[p.Y][p.X]);
else });
{ return found;
if (func(sim, sim->pmap[y][x])) return true;
}
e += de;
if (e >= 0.5f)
{
y += sy;
if ((y1<y2) ? (y<=y2) : (y>=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;
} }
static int update(UPDATE_FUNC_ARGS) static int update(UPDATE_FUNC_ARGS)

View File

@ -1,3 +1,4 @@
#include "common/RasterGeometry.h"
#include "simulation/ElementCommon.h" #include "simulation/ElementCommon.h"
static int update(UPDATE_FUNC_ARGS); 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) 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; // force particles to be created in order from (x1,y1) to (x2,y2)
int x, y, dx, dy, Ystep; bool back = std::abs(x1 - x2) >= std::abs(y2 - y1) ? x1 >= x2 : y1 >= y2;
float e = 0.0f, de; bool done = false;
if (reverseXY) if (back)
{ RasterizeLine<false>(Vec2<int>(x1, y1), Vec2<int>(x2, y2),
y = x1; [&done, sim, c, temp, life, tmp, tmp2, x2, y2, i] (Vec2<int> p)
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<y2) ? 1 : -1;
if (!back)
{
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)
{ {
y += Ystep; if (!done)
e -= 1.0f; done = create_LIGH(sim, p.X, p.Y, c, temp, life, tmp, tmp2, p == Vec2<int>(x2, y2), i);
} });
}
}
else else
{ RasterizeLine<false>(-Vec2<int>(x1, y1), -Vec2<int>(x2, y2),
for (x = x1; x >= x2; x--) [&done, sim, c, temp, life, tmp, tmp2, x2, y2, i] (Vec2<int> p)
{
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)
{ {
y += Ystep; if (!done)
e += 1.0f; done = create_LIGH(sim, -p.X, -p.Y, c, temp, life, tmp, tmp2, -p == Vec2<int>(x2, y2), i);
} });
}
}
} }
static int graphics(GRAPHICS_FUNC_ARGS) static int graphics(GRAPHICS_FUNC_ARGS)