From 369dadf81e6454e4352342d04bf22934382f327d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Tue, 28 Feb 2023 14:55:57 +0100 Subject: [PATCH] Fix crash from new brush code when TPTMP is enabled Okay yeah this is actually a well-camouflaged refactor. --- src/gui/game/BitmapBrush.cpp | 18 +++++----- src/gui/game/BitmapBrush.h | 24 ++------------ src/gui/game/Brush.cpp | 60 +++++++++++++++------------------- src/gui/game/Brush.h | 46 +++++++++++++------------- src/gui/game/EllipseBrush.h | 26 +++------------ src/gui/game/GameModel.cpp | 11 +++---- src/gui/game/RectangleBrush.h | 31 +++--------------- src/gui/game/TriangleBrush.h | 34 ++----------------- src/lua/LuaScriptInterface.cpp | 2 +- 9 files changed, 80 insertions(+), 172 deletions(-) diff --git a/src/gui/game/BitmapBrush.cpp b/src/gui/game/BitmapBrush.cpp index b3aa735ca..3d4fbfda2 100644 --- a/src/gui/game/BitmapBrush.cpp +++ b/src/gui/game/BitmapBrush.cpp @@ -3,10 +3,7 @@ #include "Misc.h" #include -BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap): - Brush(), - radius(inputSize / 2), - origSize(0, 0) +BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap) { ui::Point newSize = inputSize; @@ -24,7 +21,11 @@ BitmapBrush::BitmapBrush(ui::Point inputSize, unsigned char const *inputBitmap): origBitmap[x + y * newSize.X] = inputBitmap[x + y * inputSize.X]; } -std::pair> BitmapBrush::GenerateBitmap() const +BitmapBrush::BitmapBrush(const BitmapBrush &other) : BitmapBrush(other.origSize, &other.origBitmap[0]) +{ +} + +std::unique_ptr BitmapBrush::GenerateBitmap() const { ui::Point size = radius * 2 + 1; auto bitmap = std::make_unique(size.X * size.Y); @@ -58,13 +59,10 @@ std::pair> BitmapBrush::GenerateBit } } } - return std::make_pair(radius, std::move(bitmap)); + return bitmap; } std::unique_ptr BitmapBrush::Clone() const { - auto into = std::make_unique(origSize, &origBitmap[0]); - into->radius = radius; - copyBitmaps(*into); - return into; + return std::make_unique(*this); } diff --git a/src/gui/game/BitmapBrush.h b/src/gui/game/BitmapBrush.h index 36bc4041d..3a087b7b0 100644 --- a/src/gui/game/BitmapBrush.h +++ b/src/gui/game/BitmapBrush.h @@ -1,36 +1,18 @@ -/* - * BitmapBrush.h - * - * Created on: Nov 18, 2012 - * Author: Simon Robertshaw - */ - #pragma once #include #include "Brush.h" class BitmapBrush: public Brush { - ui::Point radius; - ui::Point origSize; + ui::Point origSize{ 0, 0 }; // 2D array with coords [0, origSize.X) by [0, origSize.Y) std::unique_ptr origBitmap; public: BitmapBrush(ui::Point size, unsigned char const *bitmap); + BitmapBrush(const BitmapBrush &other); 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(); - } + std::unique_ptr GenerateBitmap() const override; std::unique_ptr Clone() const override; }; diff --git a/src/gui/game/Brush.cpp b/src/gui/game/Brush.cpp index ef1a6b16c..b9675998a 100644 --- a/src/gui/game/Brush.cpp +++ b/src/gui/game/Brush.cpp @@ -1,30 +1,34 @@ #include "Brush.h" #include "graphics/Renderer.h" -void Brush::InvalidateCache() +Brush::Brush(const Brush &other) { - size = ui::Point(0, 0); - bitmap.reset(); - outline.reset(); + radius = other.radius; + auto size = GetSize(); + if (other.bitmap) + { + bitmap = std::make_unique(size.X * size.Y); + std::copy(&other.bitmap[0], &other.bitmap[0] + size.X * size.Y, &bitmap[0]); + } + if (other.outline) + { + outline = std::make_unique(size.X * size.Y); + std::copy(&other.outline[0], &other.outline[0] + size.X * size.Y, &outline[0]); + } } -void Brush::ensureBitmap() const +void Brush::InitBitmap() { - if (bitmap) - return; - auto pair = GenerateBitmap(); - size = pair.first; - bitmap = std::move(pair.second); + bitmap = GenerateBitmap(); } -void Brush::ensureOutline() const +void Brush::InitOutline() { - if (outline) - return; - ensureBitmap(); - ui::Point bounds = size * 2 + 1; + InitBitmap(); + ui::Point bounds = GetSize(); outline = std::make_unique(bounds.X * bounds.Y); for (int j = 0; j < bounds.Y; j++) + { for (int i = 0; i < bounds.X; i++) { bool value = false; @@ -43,6 +47,13 @@ void Brush::ensureOutline() const } outline[i + j * bounds.X] = value ? 0xFF : 0; } + } +} + +void Brush::SetRadius(ui::Point newRadius) +{ + radius = newRadius; + InitOutline(); } void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY) @@ -73,22 +84,6 @@ void Brush::AdjustSize(int delta, bool logarithmic, bool keepX, bool keepY) SetRadius(newSize); } -void Brush::copyBitmaps(Brush &into) const -{ - into.size = size; - size_t bounds = (2 * size.X + 1) * (2 * size.Y + 1); - if (bitmap) - { - into.bitmap = std::make_unique(bounds); - std::copy(&bitmap[0], &bitmap[bounds], &into.bitmap[0]); - } - if (outline) - { - into.outline = std::make_unique(bounds); - std::copy(&outline[0], &outline[bounds], &into.outline[0]); - } -} - void Brush::RenderRect(Renderer * ren, ui::Point position1, ui::Point position2) const { int width, height; @@ -123,8 +118,7 @@ void Brush::RenderLine(Renderer * ren, ui::Point position1, ui::Point position2) void Brush::RenderPoint(Renderer * ren, ui::Point position) const { - ensureOutline(); - ren->xor_bitmap(&outline[0], position.X - size.X, position.Y - size.Y, 2 * size.X + 1, 2 * size.Y + 1); + ren->xor_bitmap(&outline[0], position.X - radius.X, position.Y - radius.Y, 2 * radius.X + 1, 2 * radius.Y + 1); } void Brush::RenderFill(Renderer * ren, ui::Point position) const diff --git a/src/gui/game/Brush.h b/src/gui/game/Brush.h index 6c5b281e0..5d56829cb 100644 --- a/src/gui/game/Brush.h +++ b/src/gui/game/Brush.h @@ -6,13 +6,12 @@ class Renderer; class Brush { 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; + // 2D arrays indexed by coordinates from [-radius.X, radius.X] by [-radius.Y, radius.Y] + std::unique_ptr bitmap; + std::unique_ptr outline; - void ensureBitmap() const; - void ensureOutline() const; + void InitBitmap(); + void InitOutline(); struct iterator { @@ -21,14 +20,15 @@ private: iterator &operator++() { + auto radius = parent.GetRadius(); do { - if (++x > parent.size.X) + if (++x > radius.X) { --y; - x = -parent.size.X; + x = -radius.X; } - } while (y >= -parent.size.Y && !parent.bitmap[x + parent.size.X + (y + parent.size.Y) * (2 * parent.size.X + 1)]); + } while (y >= -radius.Y && !parent.bitmap[x + radius.X + (y + radius.Y) * (2 * radius.X + 1)]); return *this; } @@ -50,42 +50,42 @@ private: }; protected: - Brush(): - size(0, 0), - bitmap(), - outline() - { - } + ui::Point radius{ 0, 0 }; - void InvalidateCache(); - virtual std::pair> GenerateBitmap() const = 0; - void copyBitmaps(Brush &into) const; + virtual std::unique_ptr GenerateBitmap() const = 0; public: + Brush() = default; + Brush(const Brush &other); 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); virtual std::unique_ptr Clone() const = 0; ui::Point GetSize() const { - return size; + return radius * 2 + 1; + } + + ui::Point GetRadius() const + { + return radius; } iterator begin() const { // bottom to top is the preferred order for Simulation::CreateParts - return ++iterator{*this, size.X, size.Y + 1}; + return ++iterator{*this, radius.X, radius.Y + 1}; } iterator end() const { - return iterator{*this, -size.X, -size.Y - 1}; + return iterator{*this, -radius.X, -radius.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; + + void SetRadius(ui::Point newRadius); }; diff --git a/src/gui/game/EllipseBrush.h b/src/gui/game/EllipseBrush.h index 99e7e06af..865a53341 100644 --- a/src/gui/game/EllipseBrush.h +++ b/src/gui/game/EllipseBrush.h @@ -4,19 +4,16 @@ class EllipseBrush: public Brush { - ui::Point radius; bool perfectCircle; public: - EllipseBrush(ui::Point radius, bool perfectCircle = true): - Brush(), - radius(radius), - perfectCircle(perfectCircle) + EllipseBrush(bool newPerfectCircle) : + perfectCircle(newPerfectCircle) { } virtual ~EllipseBrush() override = default; - std::pair> GenerateBitmap() const override + std::unique_ptr GenerateBitmap() const override { ui::Point size = radius * 2 + 1; auto bitmap = std::make_unique(size.X * size.Y); @@ -64,24 +61,11 @@ 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(); + return bitmap; } std::unique_ptr Clone() const override { - auto into = std::make_unique(radius, perfectCircle); - copyBitmaps(*into); - return into; + return std::make_unique(*this); } }; diff --git a/src/gui/game/GameModel.cpp b/src/gui/game/GameModel.cpp index ddb2e15ba..d4bdebe45 100644 --- a/src/gui/game/GameModel.cpp +++ b/src/gui/game/GameModel.cpp @@ -462,14 +462,14 @@ void GameModel::BuildFavoritesMenu() void GameModel::BuildBrushList() { - std::optional radius; + ui::Point radius{ 4, 4 }; if (brushList.size()) radius = brushList[currentBrush]->GetRadius(); brushList.clear(); - 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))); + brushList.push_back(std::make_unique(perfectCircle)); + brushList.push_back(std::make_unique()); + brushList.push_back(std::make_unique()); //Load more from brushes folder for (ByteString brushFile : Platform::DirectorySearch(BRUSH_DIR, "", { ".ptb" })) @@ -489,8 +489,7 @@ void GameModel::BuildBrushList() brushList.push_back(std::make_unique(ui::Point(dimension, dimension), reinterpret_cast(brushData.data()))); } - if (radius && (size_t)currentBrush < brushList.size()) - brushList[currentBrush]->SetRadius(*radius); + brushList[currentBrush]->SetRadius(radius); notifyBrushChanged(); } diff --git a/src/gui/game/RectangleBrush.h b/src/gui/game/RectangleBrush.h index 309e1db8e..3695c2f3a 100644 --- a/src/gui/game/RectangleBrush.h +++ b/src/gui/game/RectangleBrush.h @@ -3,40 +3,19 @@ class RectangleBrush: public Brush { - ui::Point radius; - public: - RectangleBrush(ui::Point radius): - Brush(), - radius(radius) - { - } - virtual ~RectangleBrush() override = default; - std::pair> GenerateBitmap() const override + std::unique_ptr GenerateBitmap() const override { - ui::Point size = radius * 2 + 1; + auto size = GetSize(); 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(); + std::fill(&bitmap[0], &bitmap[0] + size.X * size.Y, 0xFF); + return bitmap; } std::unique_ptr Clone() const override { - auto into = std::make_unique(radius); - copyBitmaps(*into); - return into; + return std::make_unique(*this); } }; diff --git a/src/gui/game/TriangleBrush.h b/src/gui/game/TriangleBrush.h index 771c71eaf..e9e8695dc 100644 --- a/src/gui/game/TriangleBrush.h +++ b/src/gui/game/TriangleBrush.h @@ -1,28 +1,13 @@ -/* - * TriangleBrush.h - * - * Created on: Jan 26, 2012 - * Author: Savely Skresanov - */ - #pragma once #include "Brush.h" #include class TriangleBrush: public Brush { - ui::Point radius; - public: - TriangleBrush(ui::Point radius): - Brush(), - radius(radius) - { - } - virtual ~TriangleBrush() override = default; - std::pair> GenerateBitmap() const override + std::unique_ptr GenerateBitmap() const override { ui::Point size = radius * 2 + 1; auto bitmap = std::make_unique(size.X * size.Y); @@ -43,24 +28,11 @@ 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(); + return bitmap; } std::unique_ptr Clone() const override { - auto into = std::make_unique(radius); - copyBitmaps(*into); - return into; + return std::make_unique(*this); } }; diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 49ac36428..31b86fb51 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -2202,7 +2202,7 @@ int LuaScriptInterface::simulation_brush(lua_State * l) lua_pushnumber(l, positionX); lua_pushnumber(l, positionY); std::vector points; - std::copy(brush->begin(), brush->end(), std::back_inserter(points)); + std::copy(newBrush->begin(), newBrush->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)));