diff --git a/src/gui/game/BitmapBrush.cpp b/src/gui/game/BitmapBrush.cpp index d87fe70e9..0ff418d84 100644 --- a/src/gui/game/BitmapBrush.cpp +++ b/src/gui/game/BitmapBrush.cpp @@ -3,76 +3,60 @@ #include "Misc.h" #include -BitmapBrush::BitmapBrush(unsigned char *newBitmap, ui::Point rectSize_): - Brush(ui::Point(0, 0)), +BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap): + Brush(), + radius(inputSize / 2), origSize(0, 0) { - ui::Point newSize = rectSize_; + ui::Point newSize = inputSize; //Ensure the rect has odd dimensions so we can pull an integer radius with a 1x1 centre - if(!(newSize.X % 2)) + if (!(newSize.X % 2)) newSize.X += 1; - if(!(newSize.Y % 2)) + if (!(newSize.Y % 2)) newSize.Y += 1; - radius = (newSize-ui::Point(1, 1))/2; - size = newSize; - origSize = size; - - origBitmap = new unsigned char[size.X*size.Y]; - std::fill(origBitmap, origBitmap+(size.X*size.Y), 0); - for(int y = 0; y < rectSize_.Y; y++) - { - for(int x = 0; x < rectSize_.X; x++) - { - if(newBitmap[(y*rectSize_.X)+x] >= 128) - origBitmap[(y*size.X)+x] = newBitmap[(y*rectSize_.X)+x]; - } - } - - SetRadius(radius); + origSize = newSize; + origBitmap = std::make_unique(newSize.X * newSize.Y); + std::fill(&origBitmap[0], &origBitmap[newSize.X * newSize.Y], 0); + for (int y = 0; y < inputSize.Y; y++) + for (int x = 0; x < inputSize.X; x++) + origBitmap[x + y * newSize.X] = inputBitmap[x + y * inputSize.X]; }; -void BitmapBrush::GenerateBitmap() +std::pair> BitmapBrush::GenerateBitmap() const { - if(origBitmap) + ui::Point size = radius * 2 + 1; + auto bitmap = std::make_unique(size.X * size.Y); + if (size == origSize) + std::copy(&origBitmap[0], &origBitmap[origSize.X * origSize.Y], &bitmap[0]); + else { - delete[] bitmap; - bitmap = new unsigned char[size.X*size.Y]; - if(size == origSize) - std::copy(origBitmap, origBitmap+(origSize.X*origSize.Y), bitmap); - else + //Bilinear interpolation + float factorX = ((float)origSize.X)/((float)size.X); + float factorY = ((float)origSize.Y)/((float)size.Y); + for (int y = 0; y < size.Y; y++) { - //Bilinear interpolation - float factorX = ((float)origSize.X)/((float)size.X); - float factorY = ((float)origSize.Y)/((float)size.Y); - for(int y = 0; y < size.Y; y++) + for (int x = 0; x < size.X; x++) { - for(int x = 0; x < size.X; x++) - { - float originalY = ((float)y)*factorY; - float originalX = ((float)x)*factorX; + float originalY = ((float)y)*factorY; + float originalX = ((float)x)*factorX; - auto lowerX = int(std::floor(originalX)); - auto upperX = int(std::min((float)(origSize.X-1), std::floor(originalX+1.0f))); - auto lowerY = int(std::floor(originalY)); - auto upperY = int(std::min((float)(origSize.Y-1), std::floor(originalY+1.0f))); + auto lowerX = int(std::floor(originalX)); + auto upperX = int(std::min((float)(origSize.X-1), std::floor(originalX+1.0f))); + auto lowerY = int(std::floor(originalY)); + auto upperY = int(std::min((float)(origSize.Y-1), std::floor(originalY+1.0f))); - unsigned char topRight = origBitmap[(lowerY*origSize.X)+upperX]; - unsigned char topLeft = origBitmap[(lowerY*origSize.X)+lowerX]; - unsigned char bottomRight = origBitmap[(upperY*origSize.X)+upperX]; - unsigned char bottomLeft = origBitmap[(upperY*origSize.X)+lowerX]; - float top = LinearInterpolate(topLeft, topRight, float(lowerX), float(upperX), originalX); - float bottom = LinearInterpolate(bottomLeft, bottomRight, float(lowerX), float(upperX), originalX); - float mid = LinearInterpolate(top, bottom, float(lowerY), float(upperY), originalY); - bitmap[(y*size.X)+x] = mid > 128 ? 255 : 0; - } + unsigned char topRight = origBitmap[(lowerY*origSize.X)+upperX]; + unsigned char topLeft = origBitmap[(lowerY*origSize.X)+lowerX]; + unsigned char bottomRight = origBitmap[(upperY*origSize.X)+upperX]; + unsigned char bottomLeft = origBitmap[(upperY*origSize.X)+lowerX]; + float top = LinearInterpolate(topLeft, topRight, float(lowerX), float(upperX), originalX); + float bottom = LinearInterpolate(bottomLeft, bottomRight, float(lowerX), float(upperX), originalX); + float mid = LinearInterpolate(top, bottom, float(lowerY), float(upperY), originalY); + bitmap[(y*size.X)+x] = mid > 128 ? 255 : 0; } } } -} - -BitmapBrush::~BitmapBrush() -{ - delete[] origBitmap; + return std::make_pair(radius, std::move(bitmap)); } diff --git a/src/gui/game/BitmapBrush.h b/src/gui/game/BitmapBrush.h index 0bcd2e461..1eece024e 100644 --- a/src/gui/game/BitmapBrush.h +++ b/src/gui/game/BitmapBrush.h @@ -11,11 +11,24 @@ class BitmapBrush: public Brush { -protected: + ui::Point radius; ui::Point origSize; - unsigned char * origBitmap; + // 2D array with coords [0, origSize.X) by [0, origSize.Y) + std::unique_ptr origBitmap; + public: - BitmapBrush(unsigned char *newBitmap, ui::Point rectSize); - void GenerateBitmap() override; - virtual ~BitmapBrush(); + BitmapBrush(ui::Point size, unsigned char const *bitmap); + virtual ~BitmapBrush() override = default; + std::pair> GenerateBitmap() const override; + + ui::Point GetRadius() const override + { + return radius; + } + + void SetRadius(ui::Point radius) override + { + this->radius = radius; + InvalidateCache(); + } }; diff --git a/src/gui/game/Brush.cpp b/src/gui/game/Brush.cpp index c14a1eb78..8ab47461b 100644 --- a/src/gui/game/Brush.cpp +++ b/src/gui/game/Brush.cpp @@ -1,123 +1,117 @@ #include "Brush.h" #include "graphics/Renderer.h" -Brush::Brush(ui::Point size_): - outline(NULL), - bitmap(NULL), - size(0, 0), - radius(0, 0) +void Brush::InvalidateCache() { - SetRadius(size_); -}; - -Brush::~Brush() -{ - delete[] bitmap; - delete[] outline; + size = ui::Point(0, 0); + bitmap.reset(); + outline.reset(); } -void Brush::updateOutline() +void Brush::ensureBitmap() const { - if(!bitmap) - GenerateBitmap(); - if(!bitmap) + if (bitmap) return; - delete[] outline; - outline = new unsigned char[size.X*size.Y]; - for(int x = 0; x < size.X; x++) - { - for(int y = 0; y < size.Y; y++) + auto pair = GenerateBitmap(); + size = pair.first; + bitmap = std::move(pair.second); +} + +void Brush::ensureOutline() const +{ + if (outline) + return; + ensureBitmap(); + ui::Point bounds = size * 2 + 1; + outline = std::make_unique(bounds.X * bounds.Y); + for (int j = 0; j < bounds.Y; j++) + for (int i = 0; i < bounds.X; i++) { - if(bitmap[y*size.X+x] && (!y || !x || x == size.X-1 || y == size.Y-1 || !bitmap[y*size.X+(x+1)] || !bitmap[y*size.X+(x-1)] || !bitmap[(y-1)*size.X+x] || !bitmap[(y+1)*size.X+x])) + bool value = false; + if (bitmap[i + j * bounds.X]) { - outline[y*size.X+x] = 255; + if (i == 0 || j == 0 || i == bounds.X - 1 || j == bounds.Y - 1) + value = true; + else if (!bitmap[(i + 1) + j * bounds.X]) + value = true; + else if (!bitmap[(i - 1) + j * bounds.X]) + value = true; + else if (!bitmap[i + (j + 1) * bounds.X]) + value = true; + else if (!bitmap[i + (j - 1) * bounds.X]) + value = true; } - else - outline[y*size.X+x] = 0; + outline[i + j * bounds.X] = value ? 0xFF : 0; } - } } -void Brush::SetRadius(ui::Point radius) +void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY) { - this->radius = radius; - this->size = radius+radius+ui::Point(1, 1); + if (keepX && keepY) + return; - GenerateBitmap(); - updateOutline(); + ui::Point newSize(0, 0); + ui::Point oldSize = GetRadius(); + if (logarithmic) + newSize = oldSize + ui::Point(delta * std::max(oldSize.X / 5, 1), delta * std::max(oldSize.Y / 5, 1)); + else + newSize = oldSize + ui::Point(delta, delta); + if (newSize.X < 0) + newSize.X = 0; + if (newSize.Y < 0) + newSize.Y = 0; + if (newSize.X > 200) + newSize.X = 200; + if (newSize.Y > 200) + newSize.Y = 200; + + if (keepY) + SetRadius(ui::Point(newSize.X, oldSize.Y)); + else if (keepX) + SetRadius(ui::Point(oldSize.X, newSize.Y)); + else + SetRadius(newSize); } -void Brush::GenerateBitmap() -{ - delete[] bitmap; - bitmap = new unsigned char[size.X*size.Y]; - for(int x = 0; x < size.X; x++) - { - for(int y = 0; y < size.Y; y++) - { - bitmap[(y*size.X)+x] = 255; - } - } -} - -unsigned char *Brush::GetBitmap() -{ - if(!bitmap) - GenerateBitmap(); - return bitmap; -} - -unsigned char *Brush::GetOutline() -{ - if(!outline) - updateOutline(); - if(!outline) - return NULL; - return outline; -} - -void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) +void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const { int width, height; width = position2.X-position1.X; height = position2.Y-position1.Y; - if(height<0) + if (height<0) { position1.Y += height; height *= -1; } - if(width<0) + if (width<0) { position1.X += width; width *= -1; } ren->xor_line(position1.X, position1.Y, position1.X+width, position1.Y); - if(height>0){ + if (height>0){ ren->xor_line(position1.X, position1.Y+height, position1.X+width, position1.Y+height); - if(height>1){ + if (height>1){ ren->xor_line(position1.X+width, position1.Y+1, position1.X+width, position1.Y+height-1); - if(width>0) + if (width>0) ren->xor_line(position1.X, position1.Y+1, position1.X, position1.Y+height-1); } } } -void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) +void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) const { ren->xor_line(position1.X, position1.Y, position2.X, position2.Y); } -void Brush::RenderPoint(Renderer * ren, ui::Point position) +void Brush::RenderPoint(Renderer * ren, ui::Point position) const { - if(!outline) - updateOutline(); - if(!outline) - return; - ren->xor_bitmap(outline, position.X-radius.X, position.Y-radius.Y, size.X, size.Y); + ensureOutline(); + ren->xor_bitmap(&outline[0], position.X - size.X, position.Y - size.Y, 2 * size.X + 1, 2 * size.Y + 1); } -void Brush::RenderFill(Renderer * ren, ui::Point position) +void Brush::RenderFill(Renderer * ren, ui::Point position) const { ren->xor_line(position.X-5, position.Y, position.X-1, position.Y); ren->xor_line(position.X+5, position.Y, position.X+1, position.Y); diff --git a/src/gui/game/Brush.h b/src/gui/game/Brush.h index 70f3388b4..86f10cfec 100644 --- a/src/gui/game/Brush.h +++ b/src/gui/game/Brush.h @@ -1,39 +1,90 @@ #pragma once #include "gui/interface/Point.h" +#include class Renderer; class Brush { -protected: - unsigned char * outline; - unsigned char * bitmap; - ui::Point size; - ui::Point radius; - void updateOutline(); -public: - Brush(ui::Point size); +private: + ui::Point mutable size; + // 2D arrays indexed by coordinates from [-size.X, size.X] by [-size.Y, size.Y] + std::unique_ptr mutable bitmap; + std::unique_ptr mutable outline; - //Radius of the brush 0x0 - infxinf (Radius of 0x0 would be 1x1, radius of 1x1 would be 3x3) - ui::Point GetRadius() + void ensureBitmap() const; + void ensureOutline() const; + + struct iterator + { + Brush const &parent; + int x, y; + + iterator &operator++() + { + do + { + if (++x > parent.size.X) + { + --y; + x = -parent.size.X; + } + } while (y >= -parent.size.Y && !parent.bitmap[x + parent.size.X + (y + parent.size.Y) * (2 * parent.size.X + 1)]); + return *this; + } + + ui::Point operator*() const + { + return ui::Point(x, y); + } + + bool operator!=(iterator other) const + { + return x != other.x || y != other.y; + } + + public: + using difference_type = void; + using value_type = ui::Point; + using pointer = void; + using reference = void; + using iterator_category = std::forward_iterator_tag; + }; + +protected: + Brush(): + size(0, 0), + bitmap(), + outline() { - return radius; } - //Size of the brush bitmap mask, 1x1 - infxinf - ui::Point GetSize() + void InvalidateCache(); + virtual std::pair> GenerateBitmap() const = 0; + +public: + virtual ~Brush() = default; + virtual ui::Point GetRadius() const = 0; + virtual void SetRadius(ui::Point radius) = 0; + virtual void AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY); + + ui::Point GetSize() const { return size; } - virtual void SetRadius(ui::Point radius); - virtual ~Brush(); - virtual void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2); - virtual void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2); - virtual void RenderPoint(Renderer * ren, ui::Point position); - virtual void RenderFill(Renderer * ren, ui::Point position); - virtual void GenerateBitmap(); - //Get a bitmap for drawing particles - unsigned char * GetBitmap(); - unsigned char * GetOutline(); + iterator begin() const + { + // bottom to top is the preferred order for Simulation::CreateParts + return ++iterator{*this, size.X, size.Y + 1}; + } + + iterator end() const + { + return iterator{*this, -size.X, -size.Y - 1}; + } + + void RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const; + void RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) const; + void RenderPoint(Renderer * ren, ui::Point position) const; + void RenderFill(Renderer * ren, ui::Point position) const; }; - diff --git a/src/gui/game/DecorationTool.cpp b/src/gui/game/DecorationTool.cpp index 1e4b9ef85..247318349 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 * brush, ui::Point position) +void DecorationTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { sim->ApplyDecorationPoint(position.X, position.Y, Red, Green, Blue, Alpha, toolID, brush); } -void DecorationTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) +void DecorationTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point 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 * brush, ui::Point position1, ui::Point position2) +void DecorationTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { sim->ApplyDecorationBox(position1.X, position1.Y, position2.X, position2.Y, Red, Green, Blue, Alpha, toolID); } -void DecorationTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) +void DecorationTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point 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 f86761626..d5724a6cf 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 * brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush * 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) 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; }; diff --git a/src/gui/game/EllipseBrush.h b/src/gui/game/EllipseBrush.h index 99c6e3e9b..9b4633aac 100644 --- a/src/gui/game/EllipseBrush.h +++ b/src/gui/game/EllipseBrush.h @@ -4,20 +4,23 @@ class EllipseBrush: public Brush { + ui::Point radius; bool perfectCircle; public: - EllipseBrush(ui::Point size, bool perfectCircle = true): - Brush(size) + EllipseBrush(ui::Point radius, bool perfectCircle = true): + Brush(), + radius(radius), + perfectCircle(perfectCircle) { - this->perfectCircle = perfectCircle; - SetRadius(size); } + virtual ~EllipseBrush() override = default; - void GenerateBitmap() override + std::pair> GenerateBitmap() const override { - delete[] bitmap; - bitmap = new unsigned char[size.X*size.Y]; + ui::Point size = radius * 2 + 1; + auto bitmap = std::make_unique(size.X * size.Y); + int rx = radius.X; int ry = radius.Y; @@ -61,5 +64,17 @@ public: bitmap[size.X/2] = 255; bitmap[size.X*size.Y-size.X/2-1] = 255; } + return std::make_pair(radius, std::move(bitmap)); + } + + ui::Point GetRadius() const override + { + return radius; + } + + void SetRadius(ui::Point radius) override + { + this->radius = radius; + InvalidateCache(); } }; diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index 961955fd1..81b3ea44b 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -285,37 +285,14 @@ void GameController::InvertAirSim() } -void GameController::AdjustBrushSize(int delta, bool logarithmic, bool xAxis, bool yAxis) +void GameController::AdjustBrushSize(int delta, bool logarithmic, bool keepX, bool keepY) { - if(xAxis && yAxis) - return; - - ui::Point newSize(0, 0); - ui::Point oldSize = gameModel->GetBrush()->GetRadius(); - if(logarithmic) - newSize = gameModel->GetBrush()->GetRadius() + ui::Point(delta * std::max(gameModel->GetBrush()->GetRadius().X / 5, 1), delta * std::max(gameModel->GetBrush()->GetRadius().Y / 5, 1)); - else - newSize = gameModel->GetBrush()->GetRadius() + ui::Point(delta, delta); - if(newSize.X < 0) - newSize.X = 0; - if(newSize.Y < 0) - newSize.Y = 0; - if(newSize.X > 200) - newSize.X = 200; - if(newSize.Y > 200) - newSize.Y = 200; - - if(xAxis) - SetBrushSize(ui::Point(newSize.X, oldSize.Y)); - else if(yAxis) - SetBrushSize(ui::Point(oldSize.X, newSize.Y)); - else - SetBrushSize(newSize); + gameModel->GetBrush().AdjustSize(delta, logarithmic, keepX, keepY); } void GameController::SetBrushSize(ui::Point newSize) { - gameModel->GetBrush()->SetRadius(newSize); + gameModel->GetBrush().SetRadius(newSize); } void GameController::AdjustZoomSize(int delta, bool logarithmic) @@ -380,8 +357,8 @@ void GameController::DrawRect(int toolSelection, ui::Point point1, ui::Point poi Simulation * sim = gameModel->GetSimulation(); Tool * activeTool = gameModel->GetActiveTool(toolSelection); gameModel->SetLastTool(activeTool); - Brush * cBrush = gameModel->GetBrush(); - if(!activeTool || !cBrush) + Brush &cBrush = gameModel->GetBrush(); + if (!activeTool) return; activeTool->SetStrength(1.0f); activeTool->DrawRect(sim, cBrush, point1, point2); @@ -392,8 +369,8 @@ void GameController::DrawLine(int toolSelection, ui::Point point1, ui::Point poi Simulation * sim = gameModel->GetSimulation(); Tool * activeTool = gameModel->GetActiveTool(toolSelection); gameModel->SetLastTool(activeTool); - Brush * cBrush = gameModel->GetBrush(); - if(!activeTool || !cBrush) + Brush &cBrush = gameModel->GetBrush(); + if (!activeTool) return; activeTool->SetStrength(1.0f); activeTool->DrawLine(sim, cBrush, point1, point2); @@ -404,8 +381,8 @@ void GameController::DrawFill(int toolSelection, ui::Point point) Simulation * sim = gameModel->GetSimulation(); Tool * activeTool = gameModel->GetActiveTool(toolSelection); gameModel->SetLastTool(activeTool); - Brush * cBrush = gameModel->GetBrush(); - if(!activeTool || !cBrush) + Brush &cBrush = gameModel->GetBrush(); + if (!activeTool) return; activeTool->SetStrength(1.0f); activeTool->DrawFill(sim, cBrush, point); @@ -416,8 +393,8 @@ void GameController::DrawPoints(int toolSelection, ui::Point oldPos, ui::Point n Simulation * sim = gameModel->GetSimulation(); Tool * activeTool = gameModel->GetActiveTool(toolSelection); gameModel->SetLastTool(activeTool); - Brush * cBrush = gameModel->GetBrush(); - if (!activeTool || !cBrush) + Brush &cBrush = gameModel->GetBrush(); + if (!activeTool) { return; } @@ -464,8 +441,8 @@ void GameController::ToolClick(int toolSelection, ui::Point point) { Simulation * sim = gameModel->GetSimulation(); Tool * activeTool = gameModel->GetActiveTool(toolSelection); - Brush * cBrush = gameModel->GetBrush(); - if(!activeTool || !cBrush) + Brush &cBrush = gameModel->GetBrush(); + if (!activeTool) return; activeTool->Click(sim, cBrush, point); } @@ -1481,9 +1458,9 @@ void GameController::Vote(int direction) void GameController::ChangeBrush() { - auto prev_size = gameModel->GetBrush()->GetRadius(); + auto prev_size = gameModel->GetBrush().GetRadius(); gameModel->SetBrushID(gameModel->GetBrushID()+1); - gameModel->GetBrush()->SetRadius(prev_size); + gameModel->GetBrush().SetRadius(prev_size); } void GameController::ClearSim() diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index 4c92c18d0..5ff5e9ca5 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -8,6 +8,7 @@ #include "GameView.h" #include "Menu.h" #include "Notification.h" +#include "RectangleBrush.h" #include "TriangleBrush.h" #include "QuickOptions.h" #include "lua/CommandInterface.h" @@ -31,6 +32,7 @@ #include "gui/interface/Engine.h" #include #include +#include HistoryEntry::~HistoryEntry() { @@ -183,10 +185,6 @@ GameModel::~GameModel() { delete *iter; } - for (size_t i = 0; i < brushList.size(); i++) - { - delete brushList[i]; - } delete sim; delete ren; delete placeSave; @@ -464,18 +462,14 @@ void GameModel::BuildFavoritesMenu() void GameModel::BuildBrushList() { - bool hasStoredRadius = false; - ui::Point radius = ui::Point(0, 0); + std::optional radius; if (brushList.size()) - { radius = brushList[currentBrush]->GetRadius(); - hasStoredRadius = true; - } brushList.clear(); - brushList.push_back(new EllipseBrush(ui::Point(4, 4), perfectCircle)); - brushList.push_back(new Brush(ui::Point(4, 4))); - brushList.push_back(new TriangleBrush(ui::Point(4, 4))); + brushList.push_back(std::make_unique(ui::Point(4, 4), perfectCircle)); + brushList.push_back(std::make_unique(ui::Point(4, 4))); + brushList.push_back(std::make_unique(ui::Point(4, 4))); //Load more from brushes folder std::vector brushFiles = Platform::DirectorySearch(BRUSH_DIR, "", { ".ptb" }); @@ -493,11 +487,11 @@ void GameModel::BuildBrushList() std::cout << "Brushes: Skipping " << brushFiles[i] << ". Invalid bitmap size" << std::endl; continue; } - brushList.push_back(new BitmapBrush(reinterpret_cast(&brushData[0]), ui::Point(dimension, dimension))); + brushList.push_back(std::make_unique(ui::Point(dimension, dimension), reinterpret_cast(brushData.data()))); } - if (hasStoredRadius && (size_t)currentBrush < brushList.size()) - brushList[currentBrush]->SetRadius(radius); + if (radius && (size_t)currentBrush < brushList.size()) + brushList[currentBrush]->SetRadius(*radius); notifyBrushChanged(); } @@ -813,12 +807,12 @@ void GameModel::SetVote(int direction) } } -Brush * GameModel::GetBrush() +Brush &GameModel::GetBrush() { - return brushList[currentBrush]; + return *brushList[currentBrush]; } -std::vector GameModel::GetBrushList() +std::vector> const &GameModel::GetBrushList() { return brushList; } diff --git a/src/gui/game/GameModel.h b/src/gui/game/GameModel.h index 835871ff8..d06a23e5a 100644 --- a/src/gui/game/GameModel.h +++ b/src/gui/game/GameModel.h @@ -61,7 +61,7 @@ private: std::vector quickOptions; int activeMenu; int currentBrush; - std::vector brushList; + std::vector> brushList; SaveInfo * currentSave; SaveFile * currentFile; Tool * lastTool; @@ -175,8 +175,8 @@ public: std::vector GetToolList(); std::vector GetUnlistedTools(); - Brush * GetBrush(); - std::vector GetBrushList(); + Brush &GetBrush(); + std::vector> const &GetBrushList(); int GetBrushID(); void SetBrushID(int i); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index 1a7038600..35af0ee7e 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -918,7 +918,7 @@ void GameView::NotifySaveChanged(GameModel * sender) void GameView::NotifyBrushChanged(GameModel * sender) { - activeBrush = sender->GetBrush(); + activeBrush = &sender->GetBrush(); } ByteString GameView::TakeScreenshot(int captureUI, int fileType) @@ -1320,7 +1320,7 @@ void GameView::OnMouseWheel(int x, int y, int d) } else { - c->AdjustBrushSize(d, false, shiftBehaviour, ctrlBehaviour); + c->AdjustBrushSize(d, false, ctrlBehaviour, shiftBehaviour); } } @@ -1575,13 +1575,13 @@ void GameView::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, if(zoomEnabled && !zoomCursorFixed) c->AdjustZoomSize(1, !alt); else - c->AdjustBrushSize(1, !alt, shiftBehaviour, ctrlBehaviour); + c->AdjustBrushSize(1, !alt, ctrlBehaviour, shiftBehaviour); break; case SDL_SCANCODE_LEFTBRACKET: if(zoomEnabled && !zoomCursorFixed) c->AdjustZoomSize(-1, !alt); else - c->AdjustBrushSize(-1, !alt, shiftBehaviour, ctrlBehaviour); + c->AdjustBrushSize(-1, !alt, ctrlBehaviour, shiftBehaviour); break; case SDL_SCANCODE_I: if(ctrl) diff --git a/src/gui/game/GameView.h b/src/gui/game/GameView.h index 08863915d..5ed87ab95 100644 --- a/src/gui/game/GameView.h +++ b/src/gui/game/GameView.h @@ -78,7 +78,7 @@ private: ui::Point currentPoint, lastPoint; GameController * c; Renderer * ren; - Brush * activeBrush; + Brush const *activeBrush; //UI Elements std::vector quickOptionButtons; diff --git a/src/gui/game/PropertyTool.cpp b/src/gui/game/PropertyTool.cpp index e27bce691..4878d6372 100644 --- a/src/gui/game/PropertyTool.cpp +++ b/src/gui/game/PropertyTool.cpp @@ -288,24 +288,21 @@ void PropertyTool::SetProperty(Simulation *sim, ui::Point position) } } -void PropertyTool::Draw(Simulation *sim, Brush *cBrush, ui::Point position) +void PropertyTool::Draw(Simulation *sim, Brush const &cBrush, ui::Point position) { - if(cBrush) + for (ui::Point off : cBrush) { - int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y; - unsigned char *bitmap = cBrush->GetBitmap(); - for(int y = 0; y < sizeY; y++) - for(int x = 0; x < sizeX; x++) - if(bitmap[(y*sizeX)+x] && (position.X+(x-radiusX) >= 0 && position.Y+(y-radiusY) >= 0 && position.X+(x-radiusX) < XRES && position.Y+(y-radiusY) < YRES)) - SetProperty(sim, ui::Point(position.X+(x-radiusX), position.Y+(y-radiusY))); + ui::Point coords = position + off; + if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES) + SetProperty(sim, coords); } } -void PropertyTool::DrawLine(Simulation *sim, Brush *cBrush, ui::Point position, ui::Point position2, bool dragging) +void PropertyTool::DrawLine(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point 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; + int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; float e = 0.0f, de; if (reverseXY) { @@ -355,7 +352,7 @@ void PropertyTool::DrawLine(Simulation *sim, Brush *cBrush, ui::Point position, } } -void PropertyTool::DrawRect(Simulation *sim, Brush *cBrush, ui::Point position, ui::Point position2) +void PropertyTool::DrawRect(Simulation *sim, Brush const &cBrush, ui::Point position, ui::Point position2) { int x1 = position.X, y1 = position.Y, x2 = position2.X, y2 = position2.Y; int i, j; @@ -376,7 +373,7 @@ void PropertyTool::DrawRect(Simulation *sim, Brush *cBrush, ui::Point position, SetProperty(sim, ui::Point(i, j)); } -void PropertyTool::DrawFill(Simulation *sim, Brush *cBrush, ui::Point position) +void PropertyTool::DrawFill(Simulation *sim, Brush const &cBrush, ui::Point position) { if (validProperty) sim->flood_prop(position.X, position.Y, propOffset, propValue, propType); diff --git a/src/gui/game/RectangleBrush.h b/src/gui/game/RectangleBrush.h new file mode 100644 index 000000000..5f26e1ac3 --- /dev/null +++ b/src/gui/game/RectangleBrush.h @@ -0,0 +1,35 @@ +#pragma once +#include "Brush.h" + +class RectangleBrush: public Brush +{ + ui::Point radius; + +public: + RectangleBrush(ui::Point radius): + Brush(), + radius(radius) + { + } + + virtual ~RectangleBrush() override = default; + + std::pair> GenerateBitmap() const override + { + ui::Point size = radius * 2 + 1; + auto bitmap = std::make_unique(size.X * size.Y); + std::fill(&bitmap[0], &bitmap[size.X * size.Y], 0xFF); + return std::make_pair(radius, std::move(bitmap)); + } + + ui::Point GetRadius() const override + { + return radius; + } + + void SetRadius(ui::Point radius) override + { + this->radius = radius; + InvalidateCache(); + } +}; diff --git a/src/gui/game/SampleTool.cpp b/src/gui/game/SampleTool.cpp index bacf49d57..d06dda58f 100644 --- a/src/gui/game/SampleTool.cpp +++ b/src/gui/game/SampleTool.cpp @@ -29,7 +29,7 @@ VideoBuffer * SampleTool::GetIcon(int toolID, int width, int height) return newTexture; } -void SampleTool::Draw(Simulation * sim, Brush * brush, ui::Point position) +void SampleTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { if(gameModel->GetColourSelectorVisibility()) { diff --git a/src/gui/game/SignTool.cpp b/src/gui/game/SignTool.cpp index 9f2142c0e..f43990b51 100644 --- a/src/gui/game/SignTool.cpp +++ b/src/gui/game/SignTool.cpp @@ -242,7 +242,7 @@ VideoBuffer * SignTool::GetIcon(int toolID, int width, int height) return newTexture; } -void SignTool::Click(Simulation * sim, Brush * brush, ui::Point position) +void SignTool::Click(Simulation * sim, Brush const &brush, ui::Point position) { int signX, signY, signW, signH, signIndex = -1; for (size_t i = 0; i < sim->signs.size(); i++) diff --git a/src/gui/game/Tool.cpp b/src/gui/game/Tool.cpp index cb5051e94..92d83c08e 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 * brush, ui::Point position) { } -void Tool::Draw(Simulation * sim, Brush * brush, ui::Point position) { +void Tool::Click(Simulation * sim, Brush const &brush, ui::Point position) { } +void Tool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { sim->ToolBrush(position.X, position.Y, toolID, brush, strength); } -void Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { +void Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { sim->ToolLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush, strength); } -void Tool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { +void Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { sim->ToolBox(position1.X, position1.Y, position2.X, position2.Y, toolID, strength); } -void Tool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) {} +void Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point 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,16 @@ ElementTool::ElementTool(int id, String name, String description, int r, int g, { } ElementTool::~ElementTool() {} -void ElementTool::Draw(Simulation * sim, Brush * brush, ui::Point position){ +void ElementTool::Draw(Simulation * sim, Brush const &brush, ui::Point position){ sim->CreateParts(position.X, position.Y, toolID, brush); } -void ElementTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { +void ElementTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { sim->CreateLine(position1.X, position1.Y, position2.X, position2.Y, toolID, brush); } -void ElementTool::DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) { +void ElementTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { sim->CreateBox(position1.X, position1.Y, position2.X, position2.Y, toolID); } -void ElementTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { +void ElementTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) { sim->FloodParts(position.X, position.Y, toolID, -1); } @@ -75,10 +75,10 @@ Tool(id, name, description, r, g, b, identifier, textureGen) blocky = true; } WallTool::~WallTool() {} -void WallTool::Draw(Simulation * sim, Brush * brush, ui::Point position) { - sim->CreateWalls(position.X, position.Y, 1, 1, toolID, brush); +void WallTool::Draw(Simulation * sim, Brush const &brush, ui::Point position) { + sim->CreateWalls(position.X, position.Y, 1, 1, toolID, &brush); } -void WallTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) { +void WallTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point 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) @@ -99,13 +99,13 @@ void WallTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui } else { - 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 * brush, ui::Point position1, ui::Point position2) { +void WallTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2) { sim->CreateWallBox(position1.X, position1.Y, position2.X, position2.Y, toolID); } -void WallTool::DrawFill(Simulation * sim, Brush * brush, ui::Point position) { +void WallTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position) { if (toolID != WL_STREAM) sim->FloodWalls(position.X, position.Y, toolID, -1); } @@ -115,53 +115,41 @@ WindTool::WindTool(int id, String name, String description, int r, int g, int b, { } -void WindTool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) +void WindTool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool dragging) { - int radiusX, radiusY, sizeX, sizeY; - float strength = dragging?0.01f:0.002f; strength *= this->strength; - radiusX = brush->GetRadius().X; - radiusY = brush->GetRadius().Y; - - sizeX = brush->GetSize().X; - sizeY = brush->GetSize().Y; - - unsigned char *bitmap = brush->GetBitmap(); - - for(int y = 0; y < sizeY; y++) + for (ui::Point off : brush) { - for(int x = 0; x < sizeX; x++) + ui::Point coords = position1 + off; + if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES) { - if(bitmap[(y*sizeX)+x] && (position1.X+(x-radiusX) >= 0 && position1.Y+(y-radiusY) >= 0 && position1.X+(x-radiusX) < XRES && position1.Y+(y-radiusY) < YRES)) - { - sim->vx[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.X-position1.X)*strength; - sim->vy[(position1.Y+(y-radiusY))/CELL][(position1.X+(x-radiusX))/CELL] += (position2.Y-position1.Y)*strength; - } + sim->vx[coords.Y / CELL][coords.X / CELL] += (position2 - position1).X * strength; + sim->vy[coords.Y / CELL][coords.X / CELL] += (position2 - position1).Y * strength; } } } -void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging) +void Element_LIGH_Tool::DrawLine(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point position2, bool 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 * brush, ui::Point position1, ui::Point position2) { - int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; +void Element_TESC_Tool::DrawRect(Simulation * sim, Brush const &brush, ui::Point position1, ui::Point 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 * brush, ui::Point position) { - int radiusInfo = brush->GetRadius().X*4+brush->GetRadius().Y*4+7; +void Element_TESC_Tool::DrawFill(Simulation * sim, Brush const &brush, ui::Point 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 * brush, ui::Point position) +void PlopTool::Click(Simulation * sim, Brush const &brush, ui::Point 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 ff13d4c7d..7ea84a5f1 100644 --- a/src/gui/game/Tool.h +++ b/src/gui/game/Tool.h @@ -31,11 +31,11 @@ public: VideoBuffer * GetTexture(int width, int height); void SetTextureGen(VideoBuffer * (*textureGen)(int, int, int)); virtual ~Tool(); - virtual void Click(Simulation * sim, Brush * brush, ui::Point position); - virtual void Draw(Simulation * sim, Brush * brush, ui::Point position); - virtual void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false); - virtual void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2); - virtual void DrawFill(Simulation * sim, Brush * brush, ui::Point position); + 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); }; class GameModel; @@ -51,11 +51,11 @@ public: } static VideoBuffer * GetIcon(int toolID, int width, int height); virtual ~SignTool() {} - void Click(Simulation * sim, Brush * brush, ui::Point position) override; - void Draw(Simulation * sim, Brush * brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { } + 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 { } }; class SampleTool: public Tool @@ -69,11 +69,11 @@ public: } static VideoBuffer * GetIcon(int toolID, int width, int height); virtual ~SampleTool() {} - void Click(Simulation * sim, Brush * brush, ui::Point position) override { } - void Draw(Simulation * sim, Brush * brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { } + 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 { } }; class PropertyTool: public Tool @@ -94,11 +94,11 @@ public: void OpenWindow(Simulation *sim); virtual ~PropertyTool() {} virtual void SetProperty(Simulation *sim, ui::Point position); - void Click(Simulation * sim, Brush * brush, ui::Point position) override { } - void Draw(Simulation *sim, Brush *brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override; + 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; }; class GOLTool: public Tool @@ -112,11 +112,11 @@ public: } void OpenWindow(Simulation *sim, int toolSelection, int rule = 0, int colour1 = 0, int colour2 = 0); virtual ~GOLTool() {} - void Click(Simulation * sim, Brush * brush, ui::Point position) override { } - void Draw(Simulation *sim, Brush *brush, ui::Point position) override { }; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { }; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { }; - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { }; + 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 { }; }; @@ -125,10 +125,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 * brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush * 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; }; class Element_LIGH_Tool: public ElementTool @@ -138,10 +138,10 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~Element_LIGH_Tool() { } - void Click(Simulation * sim, Brush * brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush * 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 { } }; class Element_TESC_Tool: public ElementTool @@ -151,8 +151,8 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~Element_TESC_Tool() {} - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) 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; }; class PlopTool: public ElementTool @@ -162,11 +162,11 @@ public: ElementTool(id, name, description, r, g, b, identifier, textureGen) { } virtual ~PlopTool() { } - void Draw(Simulation * sim, Brush * brush, ui::Point position) override { } - void Click(Simulation * sim, Brush * brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override { } - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush * brush, ui::Point position) override { } + 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 { } }; class WallTool: public Tool @@ -174,10 +174,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 * brush, ui::Point position) override; - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override; - void DrawFill(Simulation * sim, Brush * 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; }; class WindTool: public Tool @@ -185,8 +185,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 * brush, ui::Point position) override { } - void DrawLine(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2, bool dragging = false) override; - void DrawRect(Simulation * sim, Brush * brush, ui::Point position1, ui::Point position2) override { } - void DrawFill(Simulation * sim, Brush * 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 { } }; diff --git a/src/gui/game/TriangleBrush.h b/src/gui/game/TriangleBrush.h index dce853c80..14056952a 100644 --- a/src/gui/game/TriangleBrush.h +++ b/src/gui/game/TriangleBrush.h @@ -11,16 +11,22 @@ class TriangleBrush: public Brush { + ui::Point radius; + public: - TriangleBrush(ui::Point size_): - Brush(size_) + TriangleBrush(ui::Point radius): + Brush(), + radius(radius) { - SetRadius(size_); - }; - void GenerateBitmap() override + } + + virtual ~TriangleBrush() override = default; + + std::pair> GenerateBitmap() const override { - delete[] bitmap; - bitmap = new unsigned char[size.X*size.Y]; + ui::Point size = radius * 2 + 1; + auto bitmap = std::make_unique(size.X * size.Y); + int rx = radius.X; int ry = radius.Y; for(int x = -rx; x <= rx; x++) @@ -37,5 +43,17 @@ public: } } } + return std::make_pair(radius, std::move(bitmap)); + } + + ui::Point GetRadius() const override + { + return radius; + } + + void SetRadius(ui::Point radius) override + { + this->radius = radius; + InvalidateCache(); } }; diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 2b1ea9aec..de66d43cb 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -489,9 +489,9 @@ int LuaScriptInterface::tpt_index(lua_State *l) else if (byteStringEqualsLiteral(key, "selectedreplace")) return tpt_lua_pushByteString(l, m->GetActiveTool(3)->GetIdentifier()), 1; else if (byteStringEqualsLiteral(key, "brushx")) - return lua_pushnumber(l, m->GetBrush()->GetRadius().X), 1; + return lua_pushnumber(l, m->GetBrush().GetRadius().X), 1; else if (byteStringEqualsLiteral(key, "brushy")) - return lua_pushnumber(l, m->GetBrush()->GetRadius().Y), 1; + return lua_pushnumber(l, m->GetBrush().GetRadius().Y), 1; else if (byteStringEqualsLiteral(key, "brushID")) return lua_pushnumber(l, m->GetBrushID()), 1; else if (byteStringEqualsLiteral(key, "decoSpace")) @@ -542,7 +542,7 @@ int LuaScriptInterface::tpt_newIndex(lua_State *l) if (brushx < 0 || brushx >= XRES) luaL_error(l, "Invalid brush width"); - c->SetBrushSize(ui::Point(brushx, m->GetBrush()->GetRadius().Y)); + c->SetBrushSize(ui::Point(brushx, m->GetBrush().GetRadius().Y)); } else if (byteStringEqualsLiteral(key, "brushy")) { @@ -550,7 +550,7 @@ int LuaScriptInterface::tpt_newIndex(lua_State *l) if (brushy < 0 || brushy >= YRES) luaL_error(l, "Invalid brush height"); - c->SetBrushSize(ui::Point(m->GetBrush()->GetRadius().X, brushy)); + c->SetBrushSize(ui::Point(m->GetBrush().GetRadius().X, brushy)); } else if (byteStringEqualsLiteral(key, "brushID")) m->SetBrushID(luaL_checkinteger(l, 3)); @@ -1472,13 +1472,13 @@ int LuaScriptInterface::simulation_createParts(lua_State * l) int brush = luaL_optint(l,6,CIRCLE_BRUSH); int flags = luaL_optint(l,7,luacon_sim->replaceModeFlags); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); brushList[brush]->SetRadius(ui::Point(rx, ry)); - int ret = luacon_sim->CreateParts(x, y, c, brushList[brush], flags); + int ret = luacon_sim->CreateParts(x, y, c, *brushList[brush], flags); brushList[brush]->SetRadius(tempRadius); lua_pushinteger(l, ret); return 1; @@ -1496,13 +1496,13 @@ int LuaScriptInterface::simulation_createLine(lua_State * l) int brush = luaL_optint(l,8,CIRCLE_BRUSH); int flags = luaL_optint(l,9,luacon_sim->replaceModeFlags); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); brushList[brush]->SetRadius(ui::Point(rx, ry)); - luacon_sim->CreateLine(x1, y1, x2, y2, c, brushList[brush], flags); + luacon_sim->CreateLine(x1, y1, x2, y2, c, *brushList[brush], flags); brushList[brush]->SetRadius(tempRadius); return 0; } @@ -1627,13 +1627,13 @@ int LuaScriptInterface::simulation_toolBrush(lua_State * l) else if (tool < 0 || tool > (int)luacon_sim->tools.size()) return luaL_error(l, "Invalid tool id '%d'", tool); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); brushList[brush]->SetRadius(ui::Point(rx, ry)); - int ret = luacon_sim->ToolBrush(x, y, tool, brushList[brush], strength); + int ret = luacon_sim->ToolBrush(x, y, tool, *brushList[brush], strength); brushList[brush]->SetRadius(tempRadius); lua_pushinteger(l, ret); return 1; @@ -1656,7 +1656,7 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l) if (tool < 0 || tool >= (int)luacon_sim->tools.size()+1) return luaL_error(l, "Invalid tool id '%d'", tool); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); @@ -1667,11 +1667,11 @@ int LuaScriptInterface::simulation_toolLine(lua_State * l) Tool *windTool = luacon_model->GetToolFromIdentifier("DEFAULT_UI_WIND"); float oldStrength = windTool->GetStrength(); windTool->SetStrength(strength); - windTool->DrawLine(luacon_sim, brushList[brush], ui::Point(x1, y1), ui::Point(x2, y2)); + windTool->DrawLine(luacon_sim, *brushList[brush], ui::Point(x1, y1), ui::Point(x2, y2)); windTool->SetStrength(oldStrength); } else - luacon_sim->ToolLine(x1, y1, x2, y2, tool, brushList[brush], strength); + luacon_sim->ToolLine(x1, y1, x2, y2, tool, *brushList[brush], strength); brushList[brush]->SetRadius(tempRadius); return 0; } @@ -1711,13 +1711,13 @@ int LuaScriptInterface::simulation_decoBrush(lua_State * l) int tool = luaL_optint(l,9,DECO_DRAW); int brush = luaL_optint(l,10,CIRCLE_BRUSH); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); brushList[brush]->SetRadius(ui::Point(rx, ry)); - luacon_sim->ApplyDecorationPoint(x, y, r, g, b, a, tool, brushList[brush]); + luacon_sim->ApplyDecorationPoint(x, y, r, g, b, a, tool, *brushList[brush]); brushList[brush]->SetRadius(tempRadius); return 0; } @@ -1740,13 +1740,13 @@ int LuaScriptInterface::simulation_decoLine(lua_State * l) if (x1 < 0 || x2 < 0 || x1 >= XRES || x2 >= XRES || y1 < 0 || y2 < 0 || y1 >= YRES || y2 >= YRES) return luaL_error(l, "coordinates out of range (%d,%d),(%d,%d)", x1, y1, x2, y2); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brush < 0 || brush >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brush); ui::Point tempRadius = brushList[brush]->GetRadius(); brushList[brush]->SetRadius(ui::Point(rx, ry)); - luacon_sim->ApplyDecorationLine(x1, y1, x2, y2, r, g, b, a, tool, brushList[brush]); + luacon_sim->ApplyDecorationLine(x1, y1, x2, y2, r, g, b, a, tool, *brushList[brush]); brushList[brush]->SetRadius(tempRadius); return 0; } @@ -2166,47 +2166,18 @@ int BrushClosure(lua_State * l) // see Simulation::ToolBrush int positionX = lua_tointeger(l, lua_upvalueindex(1)); int positionY = lua_tointeger(l, lua_upvalueindex(2)); - int radiusX = lua_tointeger(l, lua_upvalueindex(3)); - int radiusY = lua_tointeger(l, lua_upvalueindex(4)); - int sizeX = lua_tointeger(l, lua_upvalueindex(5)); - int sizeY = lua_tointeger(l, lua_upvalueindex(6)); - int x = lua_tointeger(l, lua_upvalueindex(7)); - int y = lua_tointeger(l, lua_upvalueindex(8)); - unsigned char *bitmap = (unsigned char *)lua_touserdata(l, lua_upvalueindex(9)); + int i = lua_tointeger(l, lua_upvalueindex(3)); + int size = lua_tointeger(l, lua_upvalueindex(4)); + auto points = reinterpret_cast(lua_touserdata(l, lua_upvalueindex(5))); + if (i == size) + return 0; - int yield_x, yield_y; - while (true) - { - if (!(y < sizeY)) - return 0; - if (x < sizeX) - { - bool yield_coords = false; - if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES)) - { - yield_coords = true; - yield_x = positionX+(x-radiusX); - yield_y = positionY+(y-radiusY); - } - x++; - if (yield_coords) - break; - } - else - { - x = 0; - y++; - } - } + lua_pushnumber(l, i + 1); + lua_replace(l, lua_upvalueindex(3)); - lua_pushnumber(l, x); - lua_replace(l, lua_upvalueindex(7)); - lua_pushnumber(l, y); - lua_replace(l, lua_upvalueindex(8)); - - lua_pushnumber(l, yield_x); - lua_pushnumber(l, yield_y); + lua_pushnumber(l, points[i].X + positionX); + lua_pushnumber(l, points[i].Y + positionY); return 2; } @@ -2216,43 +2187,37 @@ int LuaScriptInterface::simulation_brush(lua_State * l) int positionX = luaL_checkint(l, 1); int positionY = luaL_checkint(l, 2); int brushradiusX, brushradiusY; - if (argCount >= 4 || !luacon_model->GetBrush()) + if (argCount >= 4) { brushradiusX = luaL_checkint(l, 3); brushradiusY = luaL_checkint(l, 4); } else { - ui::Point radius = luacon_model->GetBrush()->GetRadius(); + ui::Point radius = luacon_model->GetBrush().GetRadius(); brushradiusX = radius.X; brushradiusY = radius.Y; } int brushID = luaL_optint(l, 5, luacon_model->GetBrushID()); - std::vector brushList = luacon_model->GetBrushList(); + auto &brushList = luacon_model->GetBrushList(); if (brushID < 0 || brushID >= (int)brushList.size()) return luaL_error(l, "Invalid brush id '%d'", brushID); - ui::Point tempRadius = brushList[brushID]->GetRadius(); - brushList[brushID]->SetRadius(ui::Point(brushradiusX, brushradiusY)); + Brush &brush = *brushList[brushID]; + ui::Point tempRadius = brush.GetRadius(); + brush.SetRadius(ui::Point(brushradiusX, brushradiusY)); lua_pushnumber(l, positionX); lua_pushnumber(l, positionY); - int radiusX = brushList[brushID]->GetRadius().X; - int radiusY = brushList[brushID]->GetRadius().Y; - int sizeX = brushList[brushID]->GetSize().X; - int sizeY = brushList[brushID]->GetSize().Y; - lua_pushnumber(l, radiusX); - lua_pushnumber(l, radiusY); - lua_pushnumber(l, sizeX); - lua_pushnumber(l, sizeY); - lua_pushnumber(l, 0); - lua_pushnumber(l, 0); - int bitmapSize = sizeX * sizeY * sizeof(unsigned char); - void *bitmapCopy = lua_newuserdata(l, bitmapSize); - memcpy(bitmapCopy, brushList[brushID]->GetBitmap(), bitmapSize); - brushList[brushID]->SetRadius(tempRadius); + std::vector points; + std::copy(brush.begin(), brush.end(), std::back_inserter(points)); + lua_pushnumber(l, 0); // index + lua_pushnumber(l, points.size()); + auto points_ud = reinterpret_cast(lua_newuserdata(l, points.size() * sizeof(ui::Point))); + std::copy(points.begin(), points.end(), points_ud); + brush.SetRadius(tempRadius); - lua_pushcclosure(l, BrushClosure, 9); + lua_pushcclosure(l, BrushClosure, 5); return 1; } diff --git a/src/simulation/Editing.cpp b/src/simulation/Editing.cpp index 9e0982a74..c8c343b86 100644 --- a/src/simulation/Editing.cpp +++ b/src/simulation/Editing.cpp @@ -179,7 +179,7 @@ int Simulation::Tool(int x, int y, int tool, int brushX, int brushY, float stren return tools[tool].Perform(this, cpart, x, y, brushX, brushY, strength); } -int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush) +int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush) { if(cBrush) { @@ -239,7 +239,7 @@ int Simulation::CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBru return 1; } -void Simulation::CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush * 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; bool reverseXY = abs(y2-y1) > abs(x2-x1); @@ -608,37 +608,24 @@ void Simulation::ApplyDecoration(int x, int y, int colR_, int colG_, int colB_, parts[ID(rp)].dcolour = ((colA_<<24)|(colR_<<16)|(colG_<<8)|colB_); } -void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush * cBrush) +void Simulation::ApplyDecorationPoint(int positionX, int positionY, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush) { - if(cBrush) + for (ui::Point off : cBrush) { - int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y; - unsigned char *bitmap = cBrush->GetBitmap(); - - for(int y = 0; y < sizeY; y++) - { - for(int x = 0; x < sizeX; x++) - { - if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES)) - { - ApplyDecoration(positionX+(x-radiusX), positionY+(y-radiusY), colR, colG, colB, colA, mode); - } - } - } + ui::Point coords = ui::Point(positionX, positionY) + off; + if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES) + ApplyDecoration(coords.X, coords.Y, colR, colG, colB, colA, mode); } } -void Simulation::ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * 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); int x, y, dx, dy, sy, rx = 0, ry = 0; float e = 0.0f, de; - if(cBrush) - { - rx = cBrush->GetRadius().X; - ry = cBrush->GetRadius().Y; - } + rx = cBrush.GetRadius().X; + ry = cBrush.GetRadius().Y; if (reverseXY) { @@ -784,24 +771,21 @@ void Simulation::ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int free(bitmap); } -int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush * cBrush, float strength) +int Simulation::ToolBrush(int positionX, int positionY, int tool, Brush const &cBrush, float strength) { - if(cBrush) + for (ui::Point off : cBrush) { - int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y; - unsigned char *bitmap = cBrush->GetBitmap(); - for(int y = 0; y < sizeY; y++) - for(int x = 0; x < sizeX; x++) - if(bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES)) - Tool(positionX + (x - radiusX), positionY + (y - radiusY), tool, positionX, positionY, strength); + ui::Point coords = ui::Point(positionX, positionY) + off; + if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES) + Tool(coords.X, coords.Y, tool, positionX, positionY, strength); } return 0; } -void Simulation::ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * 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); - int x, y, dx, dy, sy, rx = cBrush->GetRadius().X, ry = cBrush->GetRadius().Y; + int x, y, dx, dy, sy, rx = cBrush.GetRadius().X, ry = cBrush.GetRadius().Y; float e = 0.0f, de; if (reverseXY) { @@ -871,45 +855,37 @@ void Simulation::ToolBox(int x1, int y1, int x2, int y2, int tool, float strengt Tool(i, j, tool, brushX, brushY, strength); } -int Simulation::CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags) +int Simulation::CreateParts(int positionX, int positionY, int c, Brush const &cBrush, int flags) { if (flags == -1) flags = replaceModeFlags; - if (cBrush) + int radiusX = cBrush.GetRadius().X, radiusY = cBrush.GetRadius().Y; + + // special case for LIGH + if (c == PT_LIGH) { - int radiusX = cBrush->GetRadius().X, radiusY = cBrush->GetRadius().Y, sizeX = cBrush->GetSize().X, sizeY = cBrush->GetSize().Y; - unsigned char *bitmap = cBrush->GetBitmap(); + if (currentTick < lightningRecreate) + return 1; + int newlife = radiusX + radiusY; + if (newlife > 55) + newlife = 55; + c = PMAP(newlife, c); + lightningRecreate = currentTick + std::max(newlife / 4, 1); + return CreatePartFlags(positionX, positionY, c, flags); + } + else if (c == PT_TESC) + { + int newtmp = (radiusX*4+radiusY*4+7); + if (newtmp > 300) + newtmp = 300; + c = PMAP(newtmp, c); + } - // special case for LIGH - if (c == PT_LIGH) - { - if (currentTick < lightningRecreate) - return 1; - int newlife = radiusX + radiusY; - if (newlife > 55) - newlife = 55; - c = PMAP(newlife, c); - lightningRecreate = currentTick + std::max(newlife / 4, 1); - return CreatePartFlags(positionX, positionY, c, flags); - } - else if (c == PT_TESC) - { - int newtmp = (radiusX*4+radiusY*4+7); - if (newtmp > 300) - newtmp = 300; - c = PMAP(newtmp, c); - } - - for (int y = sizeY-1; y >=0; y--) - { - for (int x = 0; x < sizeX; x++) - { - if (bitmap[(y*sizeX)+x] && (positionX+(x-radiusX) >= 0 && positionY+(y-radiusY) >= 0 && positionX+(x-radiusX) < XRES && positionY+(y-radiusY) < YRES)) - { - CreatePartFlags(positionX+(x-radiusX), positionY+(y-radiusY), c, flags); - } - } - } + for (ui::Point off : cBrush) + { + ui::Point coords = ui::Point(positionX, positionY) + off; + if (coords.X >= 0 && coords.Y >= 0 && coords.X < XRES && coords.Y < YRES) + CreatePartFlags(coords.X, coords.Y, c, flags); } return 0; } @@ -948,9 +924,9 @@ int Simulation::CreateParts(int x, int y, int rx, int ry, int c, int flags) return !created; } -void Simulation::CreateLine(int x1, int y1, int x2, int y2, int c, Brush * 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; + 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) diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index b184a5e32..52397aef4 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -15,6 +15,7 @@ #include #include #include +#include constexpr int CHANNELS = int(MAX_TEMP - 73) / 100 + 2; @@ -174,29 +175,29 @@ public: //Drawing Deco void ApplyDecoration(int x, int y, int colR, int colG, int colB, int colA, int mode); - void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL); - void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush * cBrush = NULL); + void ApplyDecorationPoint(int x, int y, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush); + void ApplyDecorationLine(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode, Brush const &cBrush); void ApplyDecorationBox(int x1, int y1, int x2, int y2, int colR, int colG, int colB, int colA, int mode); bool ColorCompare(Renderer *ren, int x, int y, int replaceR, int replaceG, int replaceB); void ApplyDecorationFill(Renderer *ren, int x, int y, int colR, int colG, int colB, int colA, int replaceR, int replaceG, int replaceB); //Drawing Tools like HEAT, AIR, and GRAV int Tool(int x, int y, int tool, int brushX, int brushY, float strength = 1.0f); - int ToolBrush(int x, int y, int tool, Brush * cBrush, float strength = 1.0f); - void ToolLine(int x1, int y1, int x2, int y2, int tool, Brush * cBrush, float strength = 1.0f); + int ToolBrush(int x, int y, int tool, Brush const &cBrush, float strength = 1.0f); + void ToolLine(int x1, int y1, int x2, int y2, int tool, Brush const &cBrush, float strength = 1.0f); void ToolBox(int x1, int y1, int x2, int y2, int tool, float strength = 1.0f); //Drawing Walls - int CreateWalls(int x, int y, int rx, int ry, int wall, Brush * cBrush = NULL); - void CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush * cBrush = NULL); + int CreateWalls(int x, int y, int rx, int ry, int wall, Brush const *cBrush = nullptr); + void CreateWallLine(int x1, int y1, int x2, int y2, int rx, int ry, int wall, Brush const *cBrush = nullptr); void CreateWallBox(int x1, int y1, int x2, int y2, int wall); int FloodWalls(int x, int y, int wall, int bm); //Drawing Particles - int CreateParts(int positionX, int positionY, int c, Brush * cBrush, int flags = -1); + int CreateParts(int positionX, int positionY, int c, Brush const &cBrush, int flags = -1); int CreateParts(int x, int y, int rx, int ry, int c, int flags = -1); int CreatePartFlags(int x, int y, int c, int flags); - void CreateLine(int x1, int y1, int x2, int y2, int c, Brush * cBrush, int flags = -1); + void CreateLine(int x1, int y1, int x2, int y2, int c, Brush const &cBrush, int flags = -1); void CreateLine(int x1, int y1, int x2, int y2, int c); void CreateBox(int x1, int y1, int x2, int y2, int c, int flags = -1); int FloodParts(int x, int y, int c, int cm, int flags = -1);