From 206048fb5d825c3b39e7014e7eb069936e6d093c Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Mon, 8 May 2023 23:54:37 +0100 Subject: [PATCH 01/10] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f6f9d67..afeb4e8 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ extlibs/ backup/ backup_*/ test/ +test-*/ test_*/ temp/ temp_*/ From ec16480f8a7784e01a1339c8b86fe60477f3a3c1 Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Tue, 9 May 2023 16:26:56 +0100 Subject: [PATCH 02/10] Line - update to v1.2.3 patch update. since updating Selba Ward to no longer use quads, Line uses a triangle strip. However, it had been setup similar to other objects - that instead use triangles - following the 6 vertices per quad rule. this caused attempts at accessing vertices that didn't exist as the triangle strip only needs 4 vertices for a quad. this fixes that problem, reducing all vertex looping to only go 4 times and no attempting to access the 5th and 6th vertex that do not exist. --- src/SelbaWard/Line.cpp | 6 ++---- src/SelbaWard/Line.hpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/SelbaWard/Line.cpp b/src/SelbaWard/Line.cpp index f922df4..0eab1e1 100644 --- a/src/SelbaWard/Line.cpp +++ b/src/SelbaWard/Line.cpp @@ -97,7 +97,7 @@ sf::FloatRect Line::getLocalBounds() const float minX, maxX, minY, maxY; minX = maxX = m_quad[0].position.x; minY = maxY = m_quad[0].position.y; - for (unsigned int v{ 1u }; v < 6u; ++v) + for (unsigned int v{ 1u }; v < 4u; ++v) { minX = std::min(minX, m_quad[v].position.x); maxX = std::max(maxX, m_quad[v].position.x); @@ -129,7 +129,7 @@ sf::FloatRect Line::getGlobalBounds() const float minX, maxX, minY, maxY; minX = maxX = transformedPosition0.x; minY = maxY = transformedPosition0.y; - for (unsigned int v{ 1u }; v < 6u; ++v) + for (unsigned int v{ 1u }; v < 4u; ++v) { const sf::Vector2f transformedPosition{ transform.transformPoint(m_quad[v].position) }; minX = std::min(minX, transformedPosition.x); @@ -177,8 +177,6 @@ void Line::setColor(const sf::Color& color) m_quad[1u].color = color; m_quad[2u].color = color; m_quad[3u].color = color; - m_quad[4u].color = color; - m_quad[5u].color = color; } void Line::setTexture(const sf::Texture& texture) diff --git a/src/SelbaWard/Line.hpp b/src/SelbaWard/Line.hpp index 66e9990..308ab02 100644 --- a/src/SelbaWard/Line.hpp +++ b/src/SelbaWard/Line.hpp @@ -41,7 +41,7 @@ namespace selbaward { -// SW Line v1.2.2 +// SW Line v1.2.3 class Line : public sf::Drawable, public sf::Transformable { public: From e3b96f5e4ca8f6902982d4c488f8a8e751b3ccee Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Wed, 10 May 2023 20:31:02 +0100 Subject: [PATCH 03/10] update to SFML3 (WIP) update all to work with the latest (wip) version of SFML 3 - currently in the 'master' branch during development. --- src/SelbaWard/BitmapText.cpp | 9 ++++--- src/SelbaWard/BitmapText.hpp | 2 +- src/SelbaWard/ConsoleScreen.cpp | 45 +++++++++++++++++---------------- src/SelbaWard/ConsoleScreen.hpp | 2 +- src/SelbaWard/Crosshair.cpp | 2 +- src/SelbaWard/Crosshair.hpp | 4 ++- src/SelbaWard/ElasticSprite.cpp | 11 ++++---- src/SelbaWard/ElasticSprite.hpp | 2 +- src/SelbaWard/GallerySprite.cpp | 5 ++-- src/SelbaWard/GallerySprite.hpp | 4 +-- src/SelbaWard/Line.cpp | 3 ++- src/SelbaWard/Line.hpp | 2 +- src/SelbaWard/NinePatch.cpp | 23 +++++++++-------- src/SelbaWard/NinePatch.hpp | 2 +- src/SelbaWard/PieChart.cpp | 3 ++- src/SelbaWard/PieChart.hpp | 2 +- src/SelbaWard/PixelDisplay.cpp | 3 ++- src/SelbaWard/PixelDisplay.hpp | 18 ++++++------- src/SelbaWard/Polygon.cpp | 5 ++-- src/SelbaWard/Polygon.hpp | 2 +- src/SelbaWard/ProgressBar.cpp | 3 ++- src/SelbaWard/ProgressBar.hpp | 2 +- src/SelbaWard/Ring.cpp | 3 ++- src/SelbaWard/Ring.hpp | 2 +- src/SelbaWard/SpinningCard.cpp | 3 ++- src/SelbaWard/SpinningCard.hpp | 2 +- src/SelbaWard/Spline.cpp | 7 ++--- src/SelbaWard/Spline.hpp | 4 +-- src/SelbaWard/Sprite3d.cpp | 11 ++++---- src/SelbaWard/Sprite3d.hpp | 2 +- src/SelbaWard/Starfield.cpp | 7 ++--- src/SelbaWard/Starfield.hpp | 2 +- src/SelbaWard/TileMap.hpp | 7 ++--- src/SelbaWard/TileMap.inl | 18 +++++++------ 34 files changed, 120 insertions(+), 102 deletions(-) diff --git a/src/SelbaWard/BitmapText.cpp b/src/SelbaWard/BitmapText.cpp index da817cd..6ce62a1 100644 --- a/src/SelbaWard/BitmapText.cpp +++ b/src/SelbaWard/BitmapText.cpp @@ -96,12 +96,12 @@ void BitmapText::setScale(unsigned int scale) void BitmapText::setScale(sf::Vector2u scale) { - setScale(scale.x, scale.y); + this->Transformable::setScale(sf::Vector2f(scale)); } void BitmapText::setScale(unsigned int scaleX, unsigned int scaleY) { - this->Transformable::setScale(static_cast(scaleX), static_cast(scaleY)); + setScale({ scaleX, scaleY }); } sf::FloatRect BitmapText::getGlobalBounds() const @@ -118,11 +118,12 @@ sf::FloatRect BitmapText::getLocalBounds() const // PRIVATE -void BitmapText::draw(sf::RenderTarget& target, sf::RenderStates states) const +void BitmapText::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { if (m_vertices.getVertexCount() == 0) return; + sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = m_pBitmapFont->getTexture(); target.draw(m_vertices, states); @@ -133,7 +134,7 @@ void BitmapText::priv_updateVertices() if (m_pBitmapFont == nullptr) { m_vertices.clear(); - m_bounds = { 0.f, 0.f, 0.f, 0.f }; + m_bounds = { { 0.f, 0.f }, { 0.f, 0.f } }; } m_vertices.resize(m_string.length() * 6u); diff --git a/src/SelbaWard/BitmapText.hpp b/src/SelbaWard/BitmapText.hpp index f401a01..a3d52fa 100644 --- a/src/SelbaWard/BitmapText.hpp +++ b/src/SelbaWard/BitmapText.hpp @@ -67,7 +67,7 @@ class BitmapText : public sf::Drawable, public sf::Transformable int m_tracking; sf::FloatRect m_bounds; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices(); void priv_updateColor(); }; diff --git a/src/SelbaWard/ConsoleScreen.cpp b/src/SelbaWard/ConsoleScreen.cpp index ae59e22..0f79e94 100644 --- a/src/SelbaWard/ConsoleScreen.cpp +++ b/src/SelbaWard/ConsoleScreen.cpp @@ -93,7 +93,7 @@ inline sf::Color sepiaColor(const float alpha) const unsigned int r{ static_cast(linearInterpolation(0.f, 344.505f, alpha)) }; const unsigned int g{ static_cast(linearInterpolation(0.f, 306.765f, alpha)) }; const unsigned int b{ static_cast(linearInterpolation(0.f, 238.935f, alpha)) }; - return sf::Color((r > 255 ? 255u : static_cast(r)), (g > 255 ? 255u : static_cast(g)), (b > 255 ? 255u : static_cast(b))); + return sf::Color((r > 255 ? 255u : static_cast(r)), (g > 255 ? 255u : static_cast(g)), (b > 255 ? 255u : static_cast(b))); } inline float relativeLuminance(const sf::Color& color) @@ -170,21 +170,21 @@ void addPalette8ColorRgb(std::vector& palette) void addPalette16ColorGreenscale(std::vector& palette) { - for (sf::Uint8 i{ 0u }; i < 16u; ++i) - addColorToPalette(palette, sf::Color(0, i * 17u, 0)); + for (uint8_t i{ 0u }; i < 16u; ++i) + addColorToPalette(palette, sf::Color(0u, i * 17u, 0u)); } void addPalette16ColorGrayscale(std::vector& palette) { - for (sf::Uint8 i{ 0u }; i < 16u; ++i) + for (uint8_t i{ 0u }; i < 16u; ++i) addColorToPalette(palette, sf::Color(i * 17u, i * 17u, i * 17u)); } void addPalette16ColorSepia(std::vector& palette) { - const unsigned int numberOfColors{ 16 }; - for (unsigned int i{ 0 }; i < numberOfColors; ++i) - addColorToPalette(palette, sepiaColor(static_cast(i) / (numberOfColors - 1))); + constexpr unsigned int numberOfColors{ 16u }; + for (unsigned int i{ 0u }; i < numberOfColors; ++i) + addColorToPalette(palette, sepiaColor(static_cast(i) / (numberOfColors - 1u))); } void addPalette16ColorCga(std::vector& palette) @@ -294,11 +294,11 @@ void addPalette16Color16Html(std::vector& palette) void addPalette216ColorWebSafe(std::vector& palette) { - for (sf::Uint8 r{ 0u }; r < 6; ++r) + for (uint8_t r{ 0u }; r < 6; ++r) { - for (sf::Uint8 g{ 0u }; g < 6; ++g) + for (uint8_t g{ 0u }; g < 6; ++g) { - for (sf::Uint8 b{ 0u }; b < 6; ++b) + for (uint8_t b{ 0u }; b < 6; ++b) addColorToPalette(palette, sf::Color(r * 51u, g * 51u, b * 51u)); } } @@ -306,21 +306,21 @@ void addPalette216ColorWebSafe(std::vector& palette) void addPalette256ColorGreenscale(std::vector& palette) { - for (unsigned int i{ 0u }; i < 256; ++i) - addColorToPalette(palette, sf::Color(0, static_cast(i), 0)); + for (unsigned int i{ 0u }; i < 256u; ++i) + addColorToPalette(palette, sf::Color(0, static_cast(i), 0)); } void addPalette256ColorGrayscale(std::vector& palette) { - for (unsigned int i{ 0 }; i < 256; ++i) - addColorToPalette(palette, sf::Color(static_cast(i), static_cast(i), static_cast(i))); + for (unsigned int i{ 0u }; i < 256u; ++i) + addColorToPalette(palette, sf::Color(static_cast(i), static_cast(i), static_cast(i))); } void addPalette256ColorSepia(std::vector& palette) { - const unsigned int numberOfColors{ 256 }; - for (unsigned int i{ 0 }; i < numberOfColors; ++i) - addColorToPalette(palette, sepiaColor(static_cast(i) / (numberOfColors - 1))); + constexpr unsigned int numberOfColors{ 256u }; + for (unsigned int i{ 0u }; i < numberOfColors; ++i) + addColorToPalette(palette, sepiaColor(static_cast(i) / (numberOfColors - 1u))); } } // namespace @@ -1935,7 +1935,7 @@ sf::Color ConsoleScreen::getPaletteColor(const Color color) const return sf::Color::Transparent; } - return m_is.rgbMode ? sf::Color(static_cast(color.id / 65536), static_cast((color.id % 65536) / 256), static_cast(color.id % 256)) : m_palette[color.id]; + return m_is.rgbMode ? sf::Color(static_cast(color.id / 65536), static_cast((color.id % 65536) / 256), static_cast(color.id % 256)) : m_palette[color.id]; } void ConsoleScreen::setPaletteSize(const unsigned long int size) @@ -2405,8 +2405,9 @@ ConsoleScreen::Cell& ConsoleScreen::bufferCell(const unsigned int bufferIndex, c // PRIVATE -void ConsoleScreen::draw(sf::RenderTarget& target, sf::RenderStates states) const +void ConsoleScreen::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_do.showBackround && m_backgroundDisplay.size() > 0) @@ -3014,9 +3015,9 @@ void ConsoleScreen::priv_modifyCellUsingPrintProperties(const unsigned int index void ConsoleScreen::priv_makeColorDark(sf::Color& color) { - color.r = static_cast(m_darkAttributeMultiplier * color.r); - color.g = static_cast(m_darkAttributeMultiplier * color.g); - color.b = static_cast(m_darkAttributeMultiplier * color.b); + color.r = static_cast(m_darkAttributeMultiplier * color.r); + color.g = static_cast(m_darkAttributeMultiplier * color.g); + color.b = static_cast(m_darkAttributeMultiplier * color.b); } } // namespace selbaward diff --git a/src/SelbaWard/ConsoleScreen.hpp b/src/SelbaWard/ConsoleScreen.hpp index 6f6b863..285bd18 100644 --- a/src/SelbaWard/ConsoleScreen.hpp +++ b/src/SelbaWard/ConsoleScreen.hpp @@ -531,7 +531,7 @@ class ConsoleScreen : public sf::Drawable, public sf::Transformable sf::Vector2u m_tileSize; unsigned int m_numberOfTilesPerRow; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_setVerticesFromCell(unsigned int index, int baseVertex = -1, bool overLayer = true); void priv_updateCell(unsigned int index); void priv_updateUnderCells(); diff --git a/src/SelbaWard/Crosshair.cpp b/src/SelbaWard/Crosshair.cpp index 6a2891a..7c253b4 100644 --- a/src/SelbaWard/Crosshair.cpp +++ b/src/SelbaWard/Crosshair.cpp @@ -138,7 +138,7 @@ sf::Vector2f Crosshair::getPosition() const // PRIVATE -void Crosshair::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Crosshair::draw(sf::RenderTarget& target, const sf::RenderStates& states) const { if (updateVertices(m_vertices, m_window, m_horizontalColor, m_verticalColor)) target.draw(m_vertices, states); diff --git a/src/SelbaWard/Crosshair.hpp b/src/SelbaWard/Crosshair.hpp index 9f0a20a..e58c45a 100644 --- a/src/SelbaWard/Crosshair.hpp +++ b/src/SelbaWard/Crosshair.hpp @@ -35,8 +35,10 @@ #include "Common.hpp" +#include #include #include +#include namespace selbaward { @@ -64,7 +66,7 @@ class Crosshair : public sf::Drawable sf::Color m_verticalColor; mutable sf::VertexArray m_vertices; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; }; } // namespace selbaward diff --git a/src/SelbaWard/ElasticSprite.cpp b/src/SelbaWard/ElasticSprite.cpp index 6877648..ac79044 100644 --- a/src/SelbaWard/ElasticSprite.cpp +++ b/src/SelbaWard/ElasticSprite.cpp @@ -135,9 +135,9 @@ inline sf::Color encodeFloatAsColor(const float f) { return { - static_cast(static_cast(f / 256) & 0xFF), - static_cast(static_cast(f) & 0xFF), - static_cast(static_cast(f * 256) & 0xFF), + static_cast(static_cast(f / 256) & 0xFF), + static_cast(static_cast(f) & 0xFF), + static_cast(static_cast(f * 256) & 0xFF), 0u }; } @@ -305,7 +305,7 @@ sf::Color ElasticSprite::getColor() const const unsigned int totalG{ static_cast(m_vertices[0].color.g) + m_vertices[1].color.g + m_vertices[2].color.g + m_vertices[3].color.g }; const unsigned int totalB{ static_cast(m_vertices[0].color.b) + m_vertices[1].color.b + m_vertices[2].color.b + m_vertices[3].color.b }; const unsigned int totalA{ static_cast(m_vertices[0].color.a) + m_vertices[1].color.a + m_vertices[2].color.a + m_vertices[3].color.a }; - return{ static_cast(totalR / 4), static_cast(totalG / 4), static_cast(totalB / 4), static_cast(totalA / 4) }; + return{ static_cast(totalR / 4), static_cast(totalG / 4), static_cast(totalB / 4), static_cast(totalA / 4) }; } sf::Color ElasticSprite::getVertexColor(const unsigned int vertexIndex) const @@ -413,8 +413,9 @@ sf::FloatRect ElasticSprite::getBaseGlobalBounds() const // PRIVATE -void ElasticSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const +void ElasticSprite::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; if (m_requiresVerticesUpdate) priv_updateVertices(states.transform); states.transform = sf::Transform::Identity; diff --git a/src/SelbaWard/ElasticSprite.hpp b/src/SelbaWard/ElasticSprite.hpp index d926371..b33ecaa 100644 --- a/src/SelbaWard/ElasticSprite.hpp +++ b/src/SelbaWard/ElasticSprite.hpp @@ -110,7 +110,7 @@ class ElasticSprite : public sf::Drawable, public sf::Transformable bool m_textureFlipX; bool m_textureFlipY; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices(sf::Transform Transform) const; sf::Vector2f priv_getVertexBasePosition(const unsigned int vertexIndex) const; }; diff --git a/src/SelbaWard/GallerySprite.cpp b/src/SelbaWard/GallerySprite.cpp index fcc8c11..b9087c1 100644 --- a/src/SelbaWard/GallerySprite.cpp +++ b/src/SelbaWard/GallerySprite.cpp @@ -247,8 +247,9 @@ void GallerySprite::operator-=(const unsigned int exhibits) // PRIVATE -void GallerySprite::draw(sf::RenderTarget& target, sf::RenderStates states) const +void GallerySprite::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = m_pTexture; states.transform *= getTransform(); target.draw(&m_vertices.front(), numberOfVertices, primitiveType, states); @@ -282,7 +283,7 @@ GallerySprite::Exhibit GallerySprite::priv_getExhibit(unsigned int exhibitNumber return Exhibit(); if (exhibitNumber == 0u) - return{ { 0.f, 0.f, static_cast(m_pTexture->getSize().x), static_cast(m_pTexture->getSize().y) }, { 0.f, 0.f } }; + return{ { { 0.f, 0.f }, { static_cast(m_pTexture->getSize().x), static_cast(m_pTexture->getSize().y) } }, { 0.f, 0.f } }; return m_exhibits[exhibitNumber - 1]; } diff --git a/src/SelbaWard/GallerySprite.hpp b/src/SelbaWard/GallerySprite.hpp index 6a58474..1bbc3ce 100644 --- a/src/SelbaWard/GallerySprite.hpp +++ b/src/SelbaWard/GallerySprite.hpp @@ -48,7 +48,7 @@ class GallerySprite : public sf::Drawable, public sf::Transformable sf::FloatRect rectangle; sf::Vector2f anchor; - Exhibit(const sf::FloatRect& newRectangle = { 0.f, 0.f, 0.f, 0.f }, const sf::Vector2f& newAnchor = { 0u, 0u }) : rectangle(newRectangle), anchor(newAnchor) { } + Exhibit(const sf::FloatRect& newRectangle = { { 0.f, 0.f }, { 0.f, 0.f } }, const sf::Vector2f& newAnchor = { 0u, 0u }) : rectangle(newRectangle), anchor(newAnchor) { } }; GallerySprite(); @@ -94,7 +94,7 @@ class GallerySprite : public sf::Drawable, public sf::Transformable unsigned int m_currentExhibit; std::vector m_exhibits; - virtual void draw(sf::RenderTarget&, sf::RenderStates) const; + virtual void draw(sf::RenderTarget&, const sf::RenderStates&) const; void priv_updateVertices(); Exhibit priv_getCurrentExhibit() const; Exhibit priv_getExhibit(unsigned int exhibitNumber) const; diff --git a/src/SelbaWard/Line.cpp b/src/SelbaWard/Line.cpp index 0eab1e1..5f6b796 100644 --- a/src/SelbaWard/Line.cpp +++ b/src/SelbaWard/Line.cpp @@ -211,8 +211,9 @@ sf::FloatRect Line::getTextureRect() const // PRIVATE -void Line::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Line::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = nullptr; if (isThick()) diff --git a/src/SelbaWard/Line.hpp b/src/SelbaWard/Line.hpp index 308ab02..e5e473d 100644 --- a/src/SelbaWard/Line.hpp +++ b/src/SelbaWard/Line.hpp @@ -85,7 +85,7 @@ class Line : public sf::Drawable, public sf::Transformable const sf::Texture* m_texture; sf::FloatRect m_textureRect; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; bool isThick() const; void updateQuad(); }; diff --git a/src/SelbaWard/NinePatch.cpp b/src/SelbaWard/NinePatch.cpp index bdca4b3..482f0f9 100644 --- a/src/SelbaWard/NinePatch.cpp +++ b/src/SelbaWard/NinePatch.cpp @@ -32,6 +32,8 @@ #include "NinePatch.hpp" +#include + namespace { @@ -49,7 +51,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe { if (!foundStart) { - if (image.getPixel(textureRectangle.left + x, textureRectangle.top) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top)) == sf::Color::Black) { foundStart = true; topLeft.x = x - 1.f; @@ -59,7 +61,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(textureRectangle.left + x, textureRectangle.top) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top)) == sf::Color::Black) bottomRight.x = x - 1.f; else break; @@ -71,7 +73,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe { if (!foundStart) { - if (image.getPixel(textureRectangle.left, textureRectangle.top + y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left, textureRectangle.top + y)) == sf::Color::Black) { foundStart = true; topLeft.y = y - 1.f; @@ -81,7 +83,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(textureRectangle.left, textureRectangle.top + y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left, textureRectangle.top + y)) == sf::Color::Black) bottomRight.y = y - 1.f; else break; @@ -98,7 +100,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe { if (!foundStart) { - if (image.getPixel(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y)) == sf::Color::Black) { foundStart = true; contentTopLeft.x = x - 1.f; @@ -108,7 +110,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y)) == sf::Color::Black) contentBottomRight.x = x - 1.f; else break; @@ -120,7 +122,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe { if (!foundStart) { - if (image.getPixel(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y)) == sf::Color::Black) { foundStart = true; contentTopLeft.y = y - 1.f; @@ -130,7 +132,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y)) == sf::Color::Black) contentBottomRight.y = y - 1.f; else break; @@ -153,7 +155,7 @@ NinePatch::NinePatch() , m_scaleBottomRight({ 0.f, 0.f }) , m_contentTopLeft({ 0.f, 0.f }) , m_contentBottomRight({ 0.f, 0.f }) - , m_textureRectangle({ 0, 0, 3, 3 }) + , m_textureRectangle({ { 0, 0 }, { 3, 3 } }) { } @@ -240,8 +242,9 @@ bool NinePatch::isPointInsideTransformedContentArea(const sf::Vector2f point) co // PRIVATE -void NinePatch::draw(sf::RenderTarget& target, sf::RenderStates states) const +void NinePatch::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = m_texture; states.transform *= getTransform(); target.draw(m_vertices.data(), 22u, m_primitiveType, states); diff --git a/src/SelbaWard/NinePatch.hpp b/src/SelbaWard/NinePatch.hpp index ec1d53a..0e30ed8 100644 --- a/src/SelbaWard/NinePatch.hpp +++ b/src/SelbaWard/NinePatch.hpp @@ -71,7 +71,7 @@ class NinePatch : public sf::Drawable, public sf::Transformable sf::Vector2f m_contentBottomRight; sf::IntRect m_textureRectangle; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices(); void priv_updateVerticesPositions(); void priv_updateVerticesTexCoords(); diff --git a/src/SelbaWard/PieChart.cpp b/src/SelbaWard/PieChart.cpp index 8650f3e..2b3fd69 100644 --- a/src/SelbaWard/PieChart.cpp +++ b/src/SelbaWard/PieChart.cpp @@ -138,8 +138,9 @@ sf::FloatRect PieChart::getGlobalBounds() const // PRIVATE -void PieChart::draw(sf::RenderTarget& target, sf::RenderStates states) const +void PieChart::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_vertices.size() > 0) diff --git a/src/SelbaWard/PieChart.hpp b/src/SelbaWard/PieChart.hpp index 50423cc..a0896b6 100644 --- a/src/SelbaWard/PieChart.hpp +++ b/src/SelbaWard/PieChart.hpp @@ -67,7 +67,7 @@ class PieChart : public sf::Drawable, public sf::Transformable std::vector m_vertices; sf::Vector2f m_size; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; }; inline void PieChart::setSize(sf::Vector2f size) diff --git a/src/SelbaWard/PixelDisplay.cpp b/src/SelbaWard/PixelDisplay.cpp index d82beb8..ead3db7 100644 --- a/src/SelbaWard/PixelDisplay.cpp +++ b/src/SelbaWard/PixelDisplay.cpp @@ -521,8 +521,9 @@ sf::Vector2u PixelDisplay::getSizeOfBuffer(const unsigned int index) const // PRIVATE -void PixelDisplay::draw(sf::RenderTarget& target, sf::RenderStates states) const +void PixelDisplay::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = nullptr; states.transform *= getTransform(); target.draw(m_vertices.data(), m_vertices.size(), sf::PrimitiveType::Triangles, states); diff --git a/src/SelbaWard/PixelDisplay.hpp b/src/SelbaWard/PixelDisplay.hpp index 75bc649..484898e 100644 --- a/src/SelbaWard/PixelDisplay.hpp +++ b/src/SelbaWard/PixelDisplay.hpp @@ -66,14 +66,14 @@ class PixelDisplay : public sf::Drawable, public sf::Transformable // manual shifting/scrolling void shiftLeft(unsigned int amount = 1u, unsigned int startIndex = 0u, unsigned int numberOfPixels = 0u); void shiftRight(unsigned int amount = 1u, unsigned int startIndex = 0u, unsigned int numberOfPixels = 0u); - void scrollUp(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollDown(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollLeft(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollRight(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollWrapUp(unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollWrapDown(unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollWrapLeft(unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); - void scrollWrapRight(unsigned int amount = 1u, sf::IntRect selectionRectangle = { 0, 0, 0, 0 }); + void scrollUp(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollDown(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollLeft(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollRight(unsigned int color = 0u, unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollWrapUp(unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollWrapDown(unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollWrapLeft(unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); + void scrollWrapRight(unsigned int amount = 1u, sf::IntRect selectionRectangle = { { 0, 0 }, { 0, 0 } }); // palette void setPalette(const std::vector& palette); @@ -117,7 +117,7 @@ class PixelDisplay : public sf::Drawable, public sf::Transformable }; std::vector m_buffers; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices(); void priv_updatePixels(); void priv_updatePixel(const unsigned int index); diff --git a/src/SelbaWard/Polygon.cpp b/src/SelbaWard/Polygon.cpp index 1b597e3..dcbb491 100644 --- a/src/SelbaWard/Polygon.cpp +++ b/src/SelbaWard/Polygon.cpp @@ -170,12 +170,13 @@ std::vector Polygon::exportTriangulatedPositions() const // PRIVATE -void Polygon::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Polygon::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = nullptr; states.transform *= getTransform(); if (m_outputVertices.size() > 0) - target.draw(m_outputVertices.data(), m_outputVertices.size(), sf::Triangles, states); + target.draw(m_outputVertices.data(), m_outputVertices.size(), sf::PrimitiveType::Triangles, states); } void Polygon::priv_update() diff --git a/src/SelbaWard/Polygon.hpp b/src/SelbaWard/Polygon.hpp index 7a4ca07..512b82f 100644 --- a/src/SelbaWard/Polygon.hpp +++ b/src/SelbaWard/Polygon.hpp @@ -92,7 +92,7 @@ class Polygon : public sf::Drawable, public sf::Transformable const bool m_throwExceptions; - virtual void draw(sf::RenderTarget&, sf::RenderStates) const; + virtual void draw(sf::RenderTarget&, const sf::RenderStates&) const; void priv_update(); void priv_updateOutputVertices(); void priv_triangulate(); diff --git a/src/SelbaWard/ProgressBar.cpp b/src/SelbaWard/ProgressBar.cpp index 5dfb869..c1e4615 100644 --- a/src/SelbaWard/ProgressBar.cpp +++ b/src/SelbaWard/ProgressBar.cpp @@ -195,8 +195,9 @@ sf::Vector2f ProgressBar::getAnchorProgressBottom() const // PRIVATE -void ProgressBar::draw(sf::RenderTarget& target, sf::RenderStates states) const +void ProgressBar::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_showBackground) target.draw(m_backgroundAndFrame, states); diff --git a/src/SelbaWard/ProgressBar.hpp b/src/SelbaWard/ProgressBar.hpp index a36750b..61a62dc 100644 --- a/src/SelbaWard/ProgressBar.hpp +++ b/src/SelbaWard/ProgressBar.hpp @@ -106,7 +106,7 @@ class ProgressBar : public sf::Drawable, public sf::Transformable sf::IntRect m_textureRectangle; sf::IntRect m_backgroundTextureRectangle; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateGraphics(); }; diff --git a/src/SelbaWard/Ring.cpp b/src/SelbaWard/Ring.cpp index bcc367b..91649fd 100644 --- a/src/SelbaWard/Ring.cpp +++ b/src/SelbaWard/Ring.cpp @@ -205,8 +205,9 @@ float Ring::getSectorOffset() const // PRIVATE -void Ring::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Ring::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = m_texture; states.transform *= getTransform(); diff --git a/src/SelbaWard/Ring.hpp b/src/SelbaWard/Ring.hpp index 5c660cd..a0090d9 100644 --- a/src/SelbaWard/Ring.hpp +++ b/src/SelbaWard/Ring.hpp @@ -74,7 +74,7 @@ class Ring : public sf::Drawable, public sf::Transformable const sf::Texture* m_texture; sf::IntRect m_textureRect; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices(); }; diff --git a/src/SelbaWard/SpinningCard.cpp b/src/SelbaWard/SpinningCard.cpp index 46def47..455b788 100644 --- a/src/SelbaWard/SpinningCard.cpp +++ b/src/SelbaWard/SpinningCard.cpp @@ -129,8 +129,9 @@ void SpinningCard::setDepth(float depth) m_depth = depth; } -void SpinningCard::draw(sf::RenderTarget& target, sf::RenderStates states) const +void SpinningCard::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = m_pTexture; target.draw(m_vertices, states); diff --git a/src/SelbaWard/SpinningCard.hpp b/src/SelbaWard/SpinningCard.hpp index 3d607b8..5c968c8 100644 --- a/src/SelbaWard/SpinningCard.hpp +++ b/src/SelbaWard/SpinningCard.hpp @@ -75,7 +75,7 @@ class SpinningCard : public sf::Drawable, public sf::Transformable void setDepth(float depth); private: - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; sf::VertexArray m_vertices; const sf::Texture* m_pTexture; sf::FloatRect m_initial; diff --git a/src/SelbaWard/Spline.cpp b/src/SelbaWard/Spline.cpp index 621dfff..37264bb 100644 --- a/src/SelbaWard/Spline.cpp +++ b/src/SelbaWard/Spline.cpp @@ -180,11 +180,7 @@ Spline::Spline(const std::size_t vertexCount, const sf::Vector2f initialPosition , m_interpolatedVertices() , m_interpolatedVerticesUnitTangents() , m_outputVertices() -#ifdef USE_SFML_PRE_2_4 - , m_primitiveType(sf::PrimitiveType::LinesStrip) -#else // USE_SFML_PRE_2_4 , m_primitiveType(sf::PrimitiveType::LineStrip) -#endif // USE_SFML_PRE_2_4 , m_interpolationSteps{ 0u } , m_useBezier{ false } , m_handlesVertices() @@ -841,8 +837,9 @@ float Spline::getInterpolatedPositionThicknessCorrectionScale(const std::size_t // PRIVATE -void Spline::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Spline::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.texture = nullptr; if (m_outputVertices.size() > 0) target.draw(m_outputVertices.data(), m_outputVertices.size(), (priv_isThick() ? thickPrimitiveType : m_primitiveType), states); diff --git a/src/SelbaWard/Spline.hpp b/src/SelbaWard/Spline.hpp index d599035..b729a14 100644 --- a/src/SelbaWard/Spline.hpp +++ b/src/SelbaWard/Spline.hpp @@ -204,7 +204,7 @@ class Spline : public sf::Drawable std::size_t m_roundedThickStartCapInterpolationLevel; // number of interpolations. 0 is flat (same as no cap), 1 is triangle, 2+ circular. std::size_t m_roundedThickEndCapInterpolationLevel; // number of interpolations. 0 is flat (same as no cap), 1 is triangle, 2+ circular. float m_maxPointLength; // maximum length of point when limited or clipped. ignored when using other corner types including Point. - const bool m_automaticallyUpdateRandomNormalOffset; + bool m_automaticallyUpdateRandomNormalOffset; std::vector m_vertices; sf::Color m_color; @@ -223,7 +223,7 @@ class Spline : public sf::Drawable bool m_lockHandleMirror; bool m_lockHandleAngle; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; bool priv_isValidVertexIndex(std::size_t vertexIndex) const; bool priv_testVertexIndex(std::size_t vertexIndex, const std::string& exceptionMessage) const; bool priv_isThick() const; diff --git a/src/SelbaWard/Sprite3d.cpp b/src/SelbaWard/Sprite3d.cpp index 293daa6..dc2e9d6 100644 --- a/src/SelbaWard/Sprite3d.cpp +++ b/src/SelbaWard/Sprite3d.cpp @@ -147,7 +147,7 @@ Sprite3d::Sprite3d(const sf::Sprite& sprite) this->setColor(sprite.getColor()); this->setOrigin(sprite.getOrigin()); this->setPosition(sprite.getPosition()); - this->setRotation(sprite.getRotation()); + this->setRotation(sprite.getRotation().asDegrees()); this->setScale(sprite.getScale()); } @@ -263,12 +263,12 @@ float Sprite3d::getYaw() const float Sprite3d::getRoll() const { - return this->getRotation(); + return this->getRotation().asDegrees(); } sf::Vector3f Sprite3d::getRotation3d() const { - return{ m_pitch, m_yaw, this->Transformable::getRotation() }; + return{ m_pitch, m_yaw, this->Transformable::getRotation().asDegrees()}; } sf::Vector3f Sprite3d::getOrigin3d() const @@ -297,7 +297,7 @@ void Sprite3d::setYaw(const float yaw) void Sprite3d::setRoll(const float roll) { - this->Transformable::setRotation(roll); + this->Transformable::setRotation(sf::degrees(roll)); } void Sprite3d::setRotation(const float rotation) @@ -473,8 +473,9 @@ float Sprite3d::getDepth() const return m_depth; } -void Sprite3d::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Sprite3d::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; if (m_pTexture != nullptr) { updateTransformedPoints(); diff --git a/src/SelbaWard/Sprite3d.hpp b/src/SelbaWard/Sprite3d.hpp index f2246c0..97e2f50 100644 --- a/src/SelbaWard/Sprite3d.hpp +++ b/src/SelbaWard/Sprite3d.hpp @@ -181,7 +181,7 @@ class Sprite3d : public sf::Drawable, public sf::Transformable void createPointGrid() const; // needs to be const to allow dynamic subdivision - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void updateTransformedPoints() const; void updateVertices() const; void updateGlobalCorners() const; diff --git a/src/SelbaWard/Starfield.cpp b/src/SelbaWard/Starfield.cpp index 1c25b2f..b7fdcab 100644 --- a/src/SelbaWard/Starfield.cpp +++ b/src/SelbaWard/Starfield.cpp @@ -94,7 +94,7 @@ void Starfield::regenerate() { vertex.position = { randomValue(0.f, m_size.x), randomValue(0.f, m_size.y) }; vertex.color = m_color; - vertex.color.a = static_cast(randomAlpha()); + vertex.color.a = static_cast(randomAlpha()); } } @@ -120,7 +120,7 @@ void Starfield::setColor(const sf::Color color) m_color = color; for (auto& vertex : m_vertices) { - const sf::Uint8 alphaDepth{ vertex.color.a }; + const uint8_t alphaDepth{ vertex.color.a }; vertex.color = m_color; vertex.color.a = alphaDepth; } @@ -130,8 +130,9 @@ void Starfield::setColor(const sf::Color color) // PRIVATE -void Starfield::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Starfield::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { + sf::RenderStates states{ inStates }; states.transform *= getTransform(); const unsigned int size{ static_cast(m_vertices.size()) }; if (size > 0) diff --git a/src/SelbaWard/Starfield.hpp b/src/SelbaWard/Starfield.hpp index 86fc053..49c8d86 100644 --- a/src/SelbaWard/Starfield.hpp +++ b/src/SelbaWard/Starfield.hpp @@ -58,7 +58,7 @@ class Starfield : public sf::Drawable, public sf::Transformable sf::Vector2f m_size; sf::Color m_color; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; }; } // namespace selbaward diff --git a/src/SelbaWard/TileMap.hpp b/src/SelbaWard/TileMap.hpp index b550fce..6e8cb9e 100644 --- a/src/SelbaWard/TileMap.hpp +++ b/src/SelbaWard/TileMap.hpp @@ -40,6 +40,7 @@ #include #include +#include namespace selbaward { @@ -120,8 +121,8 @@ class TileMap : public sf::Drawable, public sf::Transformable Deque, Raw } m_levelContainerType; - unsigned long int m_levelWidth; - unsigned long int m_levelSize; + std::size_t m_levelWidth; + std::size_t m_levelSize; const void* m_pLevel; // data @@ -150,7 +151,7 @@ class TileMap : public sf::Drawable, public sf::Transformable mutable sf::RenderTexture m_renderTexture; mutable std::vector m_render; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; + virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; void priv_updateVertices() const; void priv_updateRender() const; void priv_recreateRenderTexture(); diff --git a/src/SelbaWard/TileMap.inl b/src/SelbaWard/TileMap.inl index 2ec41c5..bd5f1e3 100644 --- a/src/SelbaWard/TileMap.inl +++ b/src/SelbaWard/TileMap.inl @@ -76,14 +76,14 @@ void TileMap::update() const sf::Vector2f actualCamera{ priv_getActualCamera() }; const sf::Vector2i levelOffset{ static_cast(std::floor(actualCamera.x)), static_cast(std::floor(actualCamera.y)) }; - const unsigned int height{ m_levelWidth > 0u ? m_levelSize / m_levelWidth : 0u }; + const std::size_t height{ m_levelWidth > 0u ? m_levelSize / m_levelWidth : 0u }; - for (unsigned int y{ 0 }; y < m_gridSize.y; ++y) + for (std::size_t y{ 0 }; y < m_gridSize.y; ++y) { - for (unsigned int x{ 0 }; x < m_gridSize.x; ++x) + for (std::size_t x{ 0 }; x < m_gridSize.x; ++x) { - const unsigned int gridIndex{ y * m_gridSize.x + x }; - const unsigned int levelIndex{ (levelOffset.y + y) * m_levelWidth + levelOffset.x + x }; + const std::size_t gridIndex{ y * m_gridSize.x + x }; + const std::size_t levelIndex{ (levelOffset.y + y) * m_levelWidth + levelOffset.x + x }; if (levelOffset.x + x >= 0 && levelOffset.x + x < m_levelWidth && levelOffset.y + y >= 0 && levelOffset.y + y < height) { @@ -372,7 +372,7 @@ void TileMap::redraw() // PRIVATE template -void TileMap::draw(sf::RenderTarget& target, sf::RenderStates states) const +void TileMap::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const { if (m_redrawRequired) { @@ -381,6 +381,7 @@ void TileMap::draw(sf::RenderTarget& target, sf::RenderStates states) const m_redrawRequired = false; } + sf::RenderStates states{ inStates }; states.texture = &m_renderTexture.getTexture(); states.transform = getTransform(); @@ -473,10 +474,11 @@ void TileMap::priv_updateRender() const template void TileMap::priv_recreateRenderTexture() { + bool createSucceeded{ false }; if (m_gridSize.x < 2 || m_gridSize.y < 2) - m_renderTexture.create(1, 1); + createSucceeded = m_renderTexture.create({ 1u, 1u }); else - m_renderTexture.create((m_gridSize.x - 1) * m_textureTileSize.x, (m_gridSize.y - 1) * m_textureTileSize.y); + createSucceeded = m_renderTexture.create({ (m_gridSize.x - 1) * m_textureTileSize.x, (m_gridSize.y - 1) * m_textureTileSize.y }); m_redrawRequired = true; } From 06fd489d68222bfbc3cb9493f35a0e407a8e26cb Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Wed, 8 Nov 2023 22:19:06 +0000 Subject: [PATCH 04/10] update ConsoleScreen to v2.4.4 fixes the order of the colours in the 16-colour Windows palette. --- src/SelbaWard/ConsoleScreen.cpp | 6 +++--- src/SelbaWard/ConsoleScreen.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SelbaWard/ConsoleScreen.cpp b/src/SelbaWard/ConsoleScreen.cpp index 0f79e94..fc5f842 100644 --- a/src/SelbaWard/ConsoleScreen.cpp +++ b/src/SelbaWard/ConsoleScreen.cpp @@ -216,12 +216,12 @@ void addPalette16ColorWindows(std::vector& palette) addColorToPalette(palette, sf::Color(0, 0, 128)); addColorToPalette(palette, sf::Color(128, 0, 128)); addColorToPalette(palette, sf::Color(0, 128, 128)); - addColorToPalette(palette, sf::Color(128, 128, 128)); addColorToPalette(palette, sf::Color(192, 192, 192)); + addColorToPalette(palette, sf::Color(128, 128, 128)); addColorToPalette(palette, sf::Color(255, 0, 0)); - addColorToPalette(palette, sf::Color(0, 0, 255)); - addColorToPalette(palette, sf::Color(255, 255, 0)); addColorToPalette(palette, sf::Color(0, 255, 0)); + addColorToPalette(palette, sf::Color(255, 255, 0)); + addColorToPalette(palette, sf::Color(0, 0, 255)); addColorToPalette(palette, sf::Color(255, 0, 255)); addColorToPalette(palette, sf::Color(0, 255, 255)); addColorToPalette(palette, sf::Color(255, 255, 255)); diff --git a/src/SelbaWard/ConsoleScreen.hpp b/src/SelbaWard/ConsoleScreen.hpp index 285bd18..78b0edf 100644 --- a/src/SelbaWard/ConsoleScreen.hpp +++ b/src/SelbaWard/ConsoleScreen.hpp @@ -45,7 +45,7 @@ namespace sf namespace selbaward { -// SW Console Screen v2.4.3 +// SW Console Screen v2.4.4 class ConsoleScreen : public sf::Drawable, public sf::Transformable { public: From ee54f65608c3390e63f0ea70b3f48e5cf8cfca8b Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Wed, 8 Nov 2023 22:34:31 +0000 Subject: [PATCH 05/10] update ConsoleScreen to v2.4.5 contracted the texture rectangle slightly (by 0.1 on each side) to reduce chance of texture bleeding. --- src/SelbaWard/ConsoleScreen.cpp | 8 ++++---- src/SelbaWard/ConsoleScreen.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SelbaWard/ConsoleScreen.cpp b/src/SelbaWard/ConsoleScreen.cpp index fc5f842..24d091b 100644 --- a/src/SelbaWard/ConsoleScreen.cpp +++ b/src/SelbaWard/ConsoleScreen.cpp @@ -2510,10 +2510,10 @@ void ConsoleScreen::priv_setVerticesFromCell(unsigned int index, int baseVertex, const float bottom{ offset.y + linearInterpolation(0.f, m_size.y, static_cast(cellY + (cell.attributes.flipY ? 0 : 1)) / m_mode.y) }; sf::Vector2u textureCell{ cellValue % m_numberOfTilesPerRow, cellValue / m_numberOfTilesPerRow }; - const float textureLeft{ static_cast(m_textureOffset.x + textureCell.x * m_tileSize.x) }; - const float textureTop{ static_cast(m_textureOffset.y + (textureCell.y + (!useCursorValue && cell.stretch == StretchType::Bottom ? 0.5f : 0.f)) * m_tileSize.y) }; - const float textureRight{ static_cast(m_textureOffset.x + (textureCell.x + 1) * m_tileSize.x) }; - const float textureBottom{ static_cast(m_textureOffset.y + (textureCell.y + (!useCursorValue && cell.stretch == StretchType::Top ? 0.5f : 1.f)) * m_tileSize.y) }; + const float textureLeft{ 0.1f + static_cast(m_textureOffset.x + textureCell.x * m_tileSize.x) }; + const float textureTop{ 0.1f + static_cast(m_textureOffset.y + (textureCell.y + (!useCursorValue && cell.stretch == StretchType::Bottom ? 0.5f : 0.f)) * m_tileSize.y) }; + const float textureRight{ -0.1f + static_cast(m_textureOffset.x + (textureCell.x + 1) * m_tileSize.x) }; + const float textureBottom{ -0.1f + static_cast(m_textureOffset.y + (textureCell.y + (!useCursorValue && cell.stretch == StretchType::Top ? 0.5f : 1.f)) * m_tileSize.y) }; if (mainLayer) baseVertex = index * 6u; diff --git a/src/SelbaWard/ConsoleScreen.hpp b/src/SelbaWard/ConsoleScreen.hpp index 78b0edf..df56aa6 100644 --- a/src/SelbaWard/ConsoleScreen.hpp +++ b/src/SelbaWard/ConsoleScreen.hpp @@ -45,7 +45,7 @@ namespace sf namespace selbaward { -// SW Console Screen v2.4.4 +// SW Console Screen v2.4.5 class ConsoleScreen : public sf::Drawable, public sf::Transformable { public: From d38279a0a5f060295de4456daf04fa12e8cf650e Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Thu, 23 Jan 2025 22:05:44 +0000 Subject: [PATCH 06/10] update to latest SFML 3 update to latest version of SFML 3, the official release version: 3.0.0. Included: update all years (to 2025), code style change (removed leading "virtual" from all virtual overrides and replaced with trailing "override"), using size.x and size.y instead of width and height, position.x and position.y instead of top and left, as well as size instead of getSize() (of rect), updated drawable version numbers (the patch number) since all have these changes (that don't affect interface), changed draw method from trial version (const ref states to value copied states), removed macro to allow "noexcept" to be absent for older VS versions, removed macro that allowed aiming specific code at specific SFML 2 versions, some extra specificity to enum scope, removal of Exception.hpp as it only included Common.hpp and all drawables already include Common themselves, SpinningCard and Sprite3d update getTexture() code to continue to retrieve a pointers properly, usage of vector.data() instead of pointer to first element, renderTexture's "create" replaced with "resize". note that drawables that have been significantly versioned have not been updated just yet. --- licence.txt | 2 +- src/SelbaWard.hpp | 2 +- src/SelbaWard/BitmapFont.cpp | 10 ++-- src/SelbaWard/BitmapFont.hpp | 4 +- src/SelbaWard/BitmapText.cpp | 39 ++++++------ src/SelbaWard/BitmapText.hpp | 6 +- src/SelbaWard/Common.hpp | 16 +---- src/SelbaWard/ConsoleScreen.cpp | 103 ++++++++++++++++---------------- src/SelbaWard/ConsoleScreen.hpp | 6 +- src/SelbaWard/Crosshair.cpp | 4 +- src/SelbaWard/Crosshair.hpp | 6 +- src/SelbaWard/ElasticSprite.cpp | 41 +++++++------ src/SelbaWard/ElasticSprite.hpp | 6 +- src/SelbaWard/Exception.hpp | 35 ----------- src/SelbaWard/GallerySprite.cpp | 21 ++++--- src/SelbaWard/GallerySprite.hpp | 6 +- src/SelbaWard/Line.cpp | 45 +++++++------- src/SelbaWard/Line.hpp | 6 +- src/SelbaWard/NinePatch.cpp | 41 +++++++------ src/SelbaWard/NinePatch.hpp | 6 +- src/SelbaWard/PaletteEnums.hpp | 2 +- src/SelbaWard/PieChart.cpp | 5 +- src/SelbaWard/PieChart.hpp | 6 +- src/SelbaWard/ProgressBar.cpp | 23 ++++--- src/SelbaWard/ProgressBar.hpp | 6 +- src/SelbaWard/Ring.cpp | 7 +-- src/SelbaWard/Ring.hpp | 6 +- src/SelbaWard/SpinningCard.cpp | 47 ++++++++------- src/SelbaWard/SpinningCard.hpp | 6 +- src/SelbaWard/Sprite3d.cpp | 17 ++---- src/SelbaWard/Sprite3d.hpp | 6 +- src/SelbaWard/Starfield.cpp | 5 +- src/SelbaWard/Starfield.hpp | 6 +- src/SelbaWard/TileMap.hpp | 6 +- src/SelbaWard/TileMap.inl | 9 ++- 35 files changed, 250 insertions(+), 312 deletions(-) delete mode 100644 src/SelbaWard/Exception.hpp diff --git a/licence.txt b/licence.txt index ddf02c2..d8591b9 100644 --- a/licence.txt +++ b/licence.txt @@ -1,6 +1,6 @@ Selba Ward (https://github.com/Hapaxia/SelbaWard) -Copyright (c) 2014-2022 M. J. Silk +Copyright (c) 2014-2025 M. J. Silk This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/src/SelbaWard.hpp b/src/SelbaWard.hpp index d672e45..2764541 100644 --- a/src/SelbaWard.hpp +++ b/src/SelbaWard.hpp @@ -2,7 +2,7 @@ // // Selba Ward (https://github.com/Hapaxia/SelbaWard) // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/SelbaWard/BitmapFont.cpp b/src/SelbaWard/BitmapFont.cpp index 01e3bd3..643f52c 100644 --- a/src/SelbaWard/BitmapFont.cpp +++ b/src/SelbaWard/BitmapFont.cpp @@ -5,7 +5,7 @@ // // BitmapFont // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -116,8 +116,8 @@ void BitmapFont::setTextureRect(const sf::IntRect& textureRect, const unsigned i m_glyphs[glyphIndex].useDefaultTextureRect = false;; m_glyphs[glyphIndex].textureRect = textureRect; - m_glyphs[glyphIndex].width = textureRect.width; - m_glyphs[glyphIndex].baseline = textureRect.height - 1; + m_glyphs[glyphIndex].width = textureRect.size.x; + m_glyphs[glyphIndex].baseline = textureRect.size.y - 1; m_glyphs[glyphIndex].startX = 0; } @@ -379,8 +379,8 @@ const BitmapFont::Glyph BitmapFont::priv_getGlyphWithDefaultTextureRect(unsigned Glyph defaultGlyph; defaultGlyph.useDefaultTextureRect = false; defaultGlyph.textureRect = m_defaultTextureRect; - defaultGlyph.textureRect.left = m_defaultTextureRect.width * (glyphIndex % m_numberOfTilesPerRow); - defaultGlyph.textureRect.top = m_defaultTextureRect.height * (glyphIndex / m_numberOfTilesPerRow); + defaultGlyph.textureRect.position.x = m_defaultTextureRect.size.x * (glyphIndex % m_numberOfTilesPerRow); + defaultGlyph.textureRect.position.y = m_defaultTextureRect.size.y * (glyphIndex / m_numberOfTilesPerRow); defaultGlyph.width = m_glyphs[glyphIndex].width; defaultGlyph.baseline = m_glyphs[glyphIndex].baseline; defaultGlyph.startX = m_glyphs[glyphIndex].startX; diff --git a/src/SelbaWard/BitmapFont.hpp b/src/SelbaWard/BitmapFont.hpp index 2b28ea4..729950c 100644 --- a/src/SelbaWard/BitmapFont.hpp +++ b/src/SelbaWard/BitmapFont.hpp @@ -5,7 +5,7 @@ // // BitmapFont // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -41,7 +41,7 @@ namespace selbaward { -// SW Bitmap Font v1.1.1 +// SW Bitmap Font v1.1.2 class BitmapFont { public: diff --git a/src/SelbaWard/BitmapText.cpp b/src/SelbaWard/BitmapText.cpp index 6ce62a1..937ef74 100644 --- a/src/SelbaWard/BitmapText.cpp +++ b/src/SelbaWard/BitmapText.cpp @@ -5,7 +5,7 @@ // // BitmapText // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -118,12 +118,11 @@ sf::FloatRect BitmapText::getLocalBounds() const // PRIVATE -void BitmapText::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void BitmapText::draw(sf::RenderTarget& target, sf::RenderStates states) const { if (m_vertices.getVertexCount() == 0) return; - sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = m_pBitmapFont->getTexture(); target.draw(m_vertices, states); @@ -151,31 +150,31 @@ void BitmapText::priv_updateVertices() BitmapFont::Glyph glyph = m_pBitmapFont->getGlyph(glyphNumber); - const sf::Vector2f glyphOffset{ 0.f - glyph.startX, (glyph.baseline < 0) ? (0.f - glyph.baseline - glyph.textureRect.height) : (0.f - glyph.baseline) }; + const sf::Vector2f glyphOffset{ 0.f - glyph.startX, (glyph.baseline < 0) ? (0.f - glyph.baseline - glyph.textureRect.size.y) : (0.f - glyph.baseline) }; const sf::Vector2f glyphPosition{ penPosition + glyphOffset }; m_vertices[(character * 6u) + 0u].position = glyphPosition; - m_vertices[(character * 6u) + 1u].position = glyphPosition + sf::Vector2f(0, static_cast(glyph.textureRect.height)); - m_vertices[(character * 6u) + 2u].position = glyphPosition + sf::Vector2f(static_cast(glyph.textureRect.width), 0); - m_vertices[(character * 6u) + 3u].position = glyphPosition + sf::Vector2f(static_cast(glyph.textureRect.width), static_cast(glyph.textureRect.height)); + m_vertices[(character * 6u) + 1u].position = glyphPosition + sf::Vector2f(0, static_cast(glyph.textureRect.size.y)); + m_vertices[(character * 6u) + 2u].position = glyphPosition + sf::Vector2f(static_cast(glyph.textureRect.size.x), 0); + m_vertices[(character * 6u) + 3u].position = glyphPosition + sf::Vector2f(static_cast(glyph.textureRect.size.x), static_cast(glyph.textureRect.size.y)); m_vertices[(character * 6u) + 0u].texCoords = sf::Vector2f( - static_cast(glyph.textureRect.left), - static_cast(glyph.textureRect.top)); + static_cast(glyph.textureRect.position.x), + static_cast(glyph.textureRect.position.y)); m_vertices[(character * 6u) + 1u].texCoords = sf::Vector2f( - static_cast(glyph.textureRect.left), - static_cast(glyph.textureRect.top + glyph.textureRect.height)); + static_cast(glyph.textureRect.position.x), + static_cast(glyph.textureRect.position.y + glyph.textureRect.size.y)); m_vertices[(character * 6u) + 2u].texCoords = sf::Vector2f( - static_cast(glyph.textureRect.left + glyph.textureRect.width), - static_cast(glyph.textureRect.top)); + static_cast(glyph.textureRect.position.x + glyph.textureRect.size.x), + static_cast(glyph.textureRect.position.y)); m_vertices[(character * 6u) + 3u].texCoords = sf::Vector2f( - static_cast(glyph.textureRect.left + glyph.textureRect.width), - static_cast(glyph.textureRect.top + glyph.textureRect.height)); + static_cast(glyph.textureRect.position.x + glyph.textureRect.size.x), + static_cast(glyph.textureRect.position.y + glyph.textureRect.size.y)); m_vertices[(character * 6u) + 4u] = m_vertices[(character * 6u) + 2u]; m_vertices[(character * 6u) + 5u] = m_vertices[(character * 6u) + 1u]; - penPosition += sf::Vector2f((glyph.width > 0) ? (0.f + m_tracking + kerning + glyph.width) : (0.f + m_tracking + kerning + glyph.width + glyph.textureRect.width - glyph.startX), 0); + penPosition += sf::Vector2f((glyph.width > 0) ? (0.f + m_tracking + kerning + glyph.width) : (0.f + m_tracking + kerning + glyph.width + glyph.textureRect.size.x - glyph.startX), 0); minX = std::min(minX, m_vertices[(character * 6u) + 0u].position.x); maxX = std::max(maxX, m_vertices[(character * 6u) + 3u].position.x); @@ -185,10 +184,10 @@ void BitmapText::priv_updateVertices() priv_updateColor(); - m_bounds.left = minX; - m_bounds.top = minY; - m_bounds.width = maxX - minX; - m_bounds.height = maxY - minY; + m_bounds.position.x = minX; + m_bounds.position.y = minY; + m_bounds.size.x = maxX - minX; + m_bounds.size.y = maxY - minY; } void BitmapText::priv_updateColor() diff --git a/src/SelbaWard/BitmapText.hpp b/src/SelbaWard/BitmapText.hpp index a3d52fa..6b350a5 100644 --- a/src/SelbaWard/BitmapText.hpp +++ b/src/SelbaWard/BitmapText.hpp @@ -5,7 +5,7 @@ // // BitmapText // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,7 @@ namespace selbaward { -// SW Bitmap Text v1.1.3 +// SW Bitmap Text v1.1.4 class BitmapText : public sf::Drawable, public sf::Transformable { public: @@ -67,7 +67,7 @@ class BitmapText : public sf::Drawable, public sf::Transformable int m_tracking; sf::FloatRect m_bounds; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices(); void priv_updateColor(); }; diff --git a/src/SelbaWard/Common.hpp b/src/SelbaWard/Common.hpp index c7ce274..ba59521 100644 --- a/src/SelbaWard/Common.hpp +++ b/src/SelbaWard/Common.hpp @@ -2,7 +2,7 @@ // // Selba Ward (https://github.com/Hapaxia/SelbaWard) // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -33,12 +33,6 @@ #include #include -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define SELBAWARD_NOEXCEPT -#else -#define SELBAWARD_NOEXCEPT noexcept -#endif - namespace selbaward { @@ -49,7 +43,7 @@ class Exception : public std::exception m_errorMessage("[Selba Ward] " + errorMessage) { } - virtual const char* what() const SELBAWARD_NOEXCEPT override + const char* what() const noexcept override { return m_errorMessage.c_str(); } @@ -73,10 +67,4 @@ namespace sw = selbaward; // create shortcut namespace #include #include -#if (SFML_VERSION_MAJOR == 2) - #if (SFML_VERSION_MINOR < 4) - #define USE_SFML_PRE_2_4 - #endif -#endif - #endif // SELBAWARD_COMMON_HPP diff --git a/src/SelbaWard/ConsoleScreen.cpp b/src/SelbaWard/ConsoleScreen.cpp index 24d091b..d59f055 100644 --- a/src/SelbaWard/ConsoleScreen.cpp +++ b/src/SelbaWard/ConsoleScreen.cpp @@ -5,7 +5,7 @@ // // Console Screen v2 // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -1617,21 +1617,21 @@ void ConsoleScreen::scrollUp(unsigned int amount, sf::IntRect selectionRectangle return; } - std::vector topRow(selectionRectangle.width); + std::vector topRow(selectionRectangle.size.x); for (unsigned int repeat{ 0 }; repeat < amount; ++repeat) // lazy way of scrolling multiple times - loop scrolling (entirely by 1 each time) { - for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.height); ++y) + for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.size.y); ++y) { - for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.width); ++x) + for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.size.x); ++x) { if (m_do.wrapOnManualScroll && y == 0) - topRow[x] = m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })]; - if (y < static_cast(selectionRectangle.height) - 1) - m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })] = m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y + 1 })]; + topRow[x] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y })]; + if (y < static_cast(selectionRectangle.size.y) - 1) + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y })] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y + 1 })]; else if (m_do.wrapOnManualScroll) - m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })] = topRow[x]; + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y })] = topRow[x]; else - priv_clearCell(priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y }), true, true); + priv_clearCell(priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y }), true, true); } } } @@ -1652,22 +1652,22 @@ void ConsoleScreen::scrollDown(unsigned int amount, sf::IntRect selectionRectang return; } - std::vector bottomRow(selectionRectangle.width); + std::vector bottomRow(selectionRectangle.size.x); for (unsigned int repeat{ 0 }; repeat < amount; ++repeat) // lazy way of scrolling multiple times - loop scrolling (entirely by 1 each time) { - for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.height); ++y) + for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.size.y); ++y) { - for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.width); ++x) + for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.size.x); ++x) { - const unsigned cellY{ selectionRectangle.top + selectionRectangle.height - y - 1 }; + const unsigned cellY{ selectionRectangle.position.x + selectionRectangle.size.y - y - 1 }; if (m_do.wrapOnManualScroll && y == 0) - bottomRow[x] = m_cells[priv_cellIndex({ selectionRectangle.left + x, cellY })]; - if (cellY > static_cast(selectionRectangle.top)) - m_cells[priv_cellIndex({ selectionRectangle.left + x, cellY })] = m_cells[priv_cellIndex({ selectionRectangle.left + x, cellY - 1 })]; + bottomRow[x] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x, cellY })]; + if (cellY > static_cast(selectionRectangle.position.y)) + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, cellY })] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x, cellY - 1 })]; else if (m_do.wrapOnManualScroll) - m_cells[priv_cellIndex({ selectionRectangle.left + x, cellY })] = bottomRow[x]; + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, cellY })] = bottomRow[x]; else - priv_clearCell(priv_cellIndex({ selectionRectangle.left + x, cellY }), true, true); + priv_clearCell(priv_cellIndex({ selectionRectangle.position.x + x, cellY }), true, true); } } } @@ -1688,21 +1688,21 @@ void ConsoleScreen::scrollLeft(unsigned int amount, sf::IntRect selectionRectang return; } - std::vector leftColumn(selectionRectangle.height); + std::vector leftColumn(selectionRectangle.size.y); for (unsigned int repeat{ 0 }; repeat < amount; ++repeat) // lazy way of scrolling multiple times - loop scrolling (entirely by 1 each time) { - for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.width); ++x) + for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.size.x); ++x) { - for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.height); ++y) + for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.size.y); ++y) { if (m_do.wrapOnManualScroll && x == 0) - leftColumn[y] = m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })]; - if (x < static_cast(selectionRectangle.width) - 1) - m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })] = m_cells[priv_cellIndex({ selectionRectangle.left + x + 1, selectionRectangle.top + y })]; + leftColumn[y] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y })]; + if (x < static_cast(selectionRectangle.size.x) - 1) + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y })] = m_cells[priv_cellIndex({ selectionRectangle.position.x + x + 1, selectionRectangle.position.y + y })]; else if (m_do.wrapOnManualScroll) - m_cells[priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y })] = leftColumn[y]; + m_cells[priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y})] = leftColumn[y]; else - priv_clearCell(priv_cellIndex({ selectionRectangle.left + x, selectionRectangle.top + y }), true, true); + priv_clearCell(priv_cellIndex({ selectionRectangle.position.x + x, selectionRectangle.position.y + y }), true, true); } } } @@ -1723,22 +1723,22 @@ void ConsoleScreen::scrollRight(unsigned int amount, sf::IntRect selectionRectan return; } - std::vector rightColumn(selectionRectangle.height); + std::vector rightColumn(selectionRectangle.size.y); for (unsigned int repeat{ 0 }; repeat < amount; ++repeat) // lazy way of scrolling multiple times - loop scrolling (entirely by 1 each time) { - for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.height); ++y) + for (unsigned int y{ 0 }; y < static_cast(selectionRectangle.size.y); ++y) { - for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.width); ++x) + for (unsigned int x{ 0 }; x < static_cast(selectionRectangle.size.x); ++x) { - const unsigned cellX{ selectionRectangle.left + selectionRectangle.width - x - 1 }; + const unsigned cellX{ selectionRectangle.position.x + selectionRectangle.size.x - x - 1 }; if (m_do.wrapOnManualScroll && x == 0) - rightColumn[y] = m_cells[priv_cellIndex({ cellX, selectionRectangle.top + y, })]; - if (cellX > static_cast(selectionRectangle.left)) - m_cells[priv_cellIndex({ cellX, selectionRectangle.top + y })] = m_cells[priv_cellIndex({ cellX - 1, selectionRectangle.top + y })]; + rightColumn[y] = m_cells[priv_cellIndex({ cellX, selectionRectangle.position.y + y, })]; + if (cellX > static_cast(selectionRectangle.position.x)) + m_cells[priv_cellIndex({ cellX, selectionRectangle.position.y + y })] = m_cells[priv_cellIndex({ cellX - 1, selectionRectangle.position.y + y })]; else if (m_do.wrapOnManualScroll) - m_cells[priv_cellIndex({ cellX, selectionRectangle.top + y })] = rightColumn[y]; + m_cells[priv_cellIndex({ cellX, selectionRectangle.position.y + y })] = rightColumn[y]; else - priv_clearCell(priv_cellIndex({ cellX, selectionRectangle.top + y }), true, true); + priv_clearCell(priv_cellIndex({ cellX, selectionRectangle.position.y + y }), true, true); } } } @@ -2405,9 +2405,8 @@ ConsoleScreen::Cell& ConsoleScreen::bufferCell(const unsigned int bufferIndex, c // PRIVATE -void ConsoleScreen::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void ConsoleScreen::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_do.showBackround && m_backgroundDisplay.size() > 0) @@ -2781,12 +2780,12 @@ void ConsoleScreen::priv_scroll() void ConsoleScreen::priv_copyToBufferFromSelectionRectangle(Buffer& buffer, const sf::IntRect& selectionRectangle) { - if (selectionRectangle.left >= static_cast(m_mode.x) || - selectionRectangle.top >= static_cast(m_mode.y) || - selectionRectangle.width <= 0 || - selectionRectangle.height <= 0 || - (selectionRectangle.left + selectionRectangle.width) < 0 || - (selectionRectangle.top + selectionRectangle.height) < 0) + if (selectionRectangle.position.x >= static_cast(m_mode.x) || + selectionRectangle.position.y >= static_cast(m_mode.y) || + selectionRectangle.size.x <= 0 || + selectionRectangle.size.y <= 0 || + (selectionRectangle.position.x + selectionRectangle.size.x) < 0 || + (selectionRectangle.position.y + selectionRectangle.size.y) < 0) { if (m_do.throwExceptions) throw Exception(exceptionPrefix + "Cannot copy selection.\nSelection does not contain any cells."); @@ -2796,11 +2795,11 @@ void ConsoleScreen::priv_copyToBufferFromSelectionRectangle(Buffer& buffer, cons buffer.width = 0u; buffer.cells.clear(); - for (int y{ 0 }; y < selectionRectangle.height; ++y) + for (int y{ 0 }; y < selectionRectangle.size.y; ++y) { - for (int x{ 0 }; x < selectionRectangle.width; ++x) + for (int x{ 0 }; x < selectionRectangle.size.x; ++x) { - const sf::Vector2i location{ x + selectionRectangle.left, y + selectionRectangle.top }; + const sf::Vector2i location{ x + selectionRectangle.position.x, y + selectionRectangle.position.y }; if (location.x < 0 || location.y < 0) continue; const sf::Vector2u cellLocation{ static_cast(location.x), static_cast(location.y) }; @@ -2832,12 +2831,12 @@ void ConsoleScreen::priv_pasteOffsettedBuffer(Buffer& buffer, const sf::Vector2i bool ConsoleScreen::priv_isSelectionRectangleContainedInScreen(const sf::IntRect& selectionRectangle) { - return (selectionRectangle.left >= 0 && - selectionRectangle.top >= 0 && - selectionRectangle.width >= 0 && - selectionRectangle.height >= 0 && - static_cast(selectionRectangle.left + selectionRectangle.width) <= m_mode.x && - static_cast(selectionRectangle.top + selectionRectangle.height) <= m_mode.y); + return (selectionRectangle.position.x >= 0 && + selectionRectangle.position.y >= 0 && + selectionRectangle.size.x >= 0 && + selectionRectangle.size.y >= 0 && + static_cast(selectionRectangle.position.x + selectionRectangle.size.x) <= m_mode.x && + static_cast(selectionRectangle.position.y + selectionRectangle.size.y) <= m_mode.y); } unsigned int ConsoleScreen::priv_getPrintIndex(sf::Vector2u location) const diff --git a/src/SelbaWard/ConsoleScreen.hpp b/src/SelbaWard/ConsoleScreen.hpp index df56aa6..9aa6eaf 100644 --- a/src/SelbaWard/ConsoleScreen.hpp +++ b/src/SelbaWard/ConsoleScreen.hpp @@ -5,7 +5,7 @@ // // Console Screen v2 // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -45,7 +45,7 @@ namespace sf namespace selbaward { -// SW Console Screen v2.4.5 +// SW Console Screen v2.4.6 class ConsoleScreen : public sf::Drawable, public sf::Transformable { public: @@ -531,7 +531,7 @@ class ConsoleScreen : public sf::Drawable, public sf::Transformable sf::Vector2u m_tileSize; unsigned int m_numberOfTilesPerRow; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_setVerticesFromCell(unsigned int index, int baseVertex = -1, bool overLayer = true); void priv_updateCell(unsigned int index); void priv_updateUnderCells(); diff --git a/src/SelbaWard/Crosshair.cpp b/src/SelbaWard/Crosshair.cpp index 7c253b4..eed1444 100644 --- a/src/SelbaWard/Crosshair.cpp +++ b/src/SelbaWard/Crosshair.cpp @@ -5,7 +5,7 @@ // // Crosshair // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -138,7 +138,7 @@ sf::Vector2f Crosshair::getPosition() const // PRIVATE -void Crosshair::draw(sf::RenderTarget& target, const sf::RenderStates& states) const +void Crosshair::draw(sf::RenderTarget& target, sf::RenderStates states) const { if (updateVertices(m_vertices, m_window, m_horizontalColor, m_verticalColor)) target.draw(m_vertices, states); diff --git a/src/SelbaWard/Crosshair.hpp b/src/SelbaWard/Crosshair.hpp index e58c45a..d8d8b75 100644 --- a/src/SelbaWard/Crosshair.hpp +++ b/src/SelbaWard/Crosshair.hpp @@ -5,7 +5,7 @@ // // Crosshair // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -43,7 +43,7 @@ namespace selbaward { -// SW Crosshair v1.0.1 +// SW Crosshair v1.0.2 class Crosshair : public sf::Drawable { public: @@ -66,7 +66,7 @@ class Crosshair : public sf::Drawable sf::Color m_verticalColor; mutable sf::VertexArray m_vertices; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; }; } // namespace selbaward diff --git a/src/SelbaWard/ElasticSprite.cpp b/src/SelbaWard/ElasticSprite.cpp index ac79044..6fe92fc 100644 --- a/src/SelbaWard/ElasticSprite.cpp +++ b/src/SelbaWard/ElasticSprite.cpp @@ -5,7 +5,7 @@ // // Elastic Sprite // -// Copyright(c) 2017-2023 M.J.Silk +// Copyright(c) 2017-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -106,7 +106,7 @@ const std::string perspectiveFragmentShaderCode void loadShader() { if (!areShadersLoaded && - bilinearShader.loadFromMemory(bilinearFragmentShaderCode, sf::Shader::Fragment) && + bilinearShader.loadFromMemory(bilinearFragmentShaderCode, sf::Shader::Type::Fragment) && perspectiveShader.loadFromMemory(perspectiveVertexShaderCode, perspectiveFragmentShaderCode)) areShadersLoaded = true; } @@ -413,9 +413,8 @@ sf::FloatRect ElasticSprite::getBaseGlobalBounds() const // PRIVATE -void ElasticSprite::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void ElasticSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; if (m_requiresVerticesUpdate) priv_updateVertices(states.transform); states.transform = sf::Transform::Identity; @@ -460,10 +459,10 @@ void ElasticSprite::draw(sf::RenderTarget& target, const sf::RenderStates& inSta { bilinearShader.setUniform("texture", *m_pTexture); const sf::Vector2f textureSize(m_pTexture->getSize()); - bilinearShader.setUniform("textureRectLeftRatio", m_actualTextureRect.left / textureSize.x); - bilinearShader.setUniform("textureRectTopRatio", m_actualTextureRect.top / textureSize.y); - bilinearShader.setUniform("textureRectWidthRatio", m_actualTextureRect.width / textureSize.x); - bilinearShader.setUniform("textureRectHeightRatio", m_actualTextureRect.height / textureSize.y); + bilinearShader.setUniform("textureRectLeftRatio", m_actualTextureRect.position.x / textureSize.x); + bilinearShader.setUniform("textureRectTopRatio", m_actualTextureRect.position.y / textureSize.y); + bilinearShader.setUniform("textureRectWidthRatio", m_actualTextureRect.size.x / textureSize.x); + bilinearShader.setUniform("textureRectHeightRatio", m_actualTextureRect.size.y / textureSize.y); } bilinearShader.setUniform("renderTargetHeight", static_cast(target.getSize().y)); bilinearShader.setUniform("v0", sf::Glsl::Vec2(target.mapCoordsToPixel(m_vertices[0].position))); @@ -493,13 +492,13 @@ void ElasticSprite::priv_updateVertices(sf::Transform transform) const if (m_textureFlipX) { - m_actualTextureRect.left += m_actualTextureRect.width; - m_actualTextureRect.width = -m_actualTextureRect.width; + m_actualTextureRect.position.x += m_actualTextureRect.size.x; + m_actualTextureRect.size.x = -m_actualTextureRect.size.x; } if (m_textureFlipY) { - m_actualTextureRect.top += m_actualTextureRect.height; - m_actualTextureRect.height = -m_actualTextureRect.height; + m_actualTextureRect.position.y += m_actualTextureRect.size.y; + m_actualTextureRect.size.y = -m_actualTextureRect.size.y; } if (m_useShader && m_usePerspectiveInterpolation && m_pTexture != nullptr) @@ -515,15 +514,15 @@ void ElasticSprite::priv_updateVertices(sf::Transform transform) const m_weights[3] = (distanceToIntersection3 + distanceToIntersection1) / distanceToIntersection1; const sf::Vector2f textureSize(m_pTexture->getSize()); - m_vertices[0].texCoords = { m_weights[0] * (m_actualTextureRect.left / textureSize.x), m_weights[0] * (m_actualTextureRect.top / textureSize.y) }; - m_vertices[1].texCoords = { m_weights[1] * (m_actualTextureRect.left / textureSize.x), m_weights[1] * ((m_actualTextureRect.top + m_actualTextureRect.height) / textureSize.y) }; - m_vertices[2].texCoords = { m_weights[2] * ((m_actualTextureRect.left + m_actualTextureRect.width) / textureSize.x), m_weights[2] * ((m_actualTextureRect.top + m_actualTextureRect.height) / textureSize.y) }; - m_vertices[3].texCoords = { m_weights[3] * ((m_actualTextureRect.left + m_actualTextureRect.width) / textureSize.x), m_weights[3] * (m_actualTextureRect.top / textureSize.y) }; + m_vertices[0].texCoords = { m_weights[0] * (m_actualTextureRect.position.x / textureSize.x), m_weights[0] * (m_actualTextureRect.position.y / textureSize.y) }; + m_vertices[1].texCoords = { m_weights[1] * (m_actualTextureRect.position.x / textureSize.x), m_weights[1] * ((m_actualTextureRect.position.y + m_actualTextureRect.size.y) / textureSize.y) }; + m_vertices[2].texCoords = { m_weights[2] * ((m_actualTextureRect.position.x + m_actualTextureRect.size.x) / textureSize.x), m_weights[2] * ((m_actualTextureRect.position.y + m_actualTextureRect.size.y) / textureSize.y) }; + m_vertices[3].texCoords = { m_weights[3] * ((m_actualTextureRect.position.x + m_actualTextureRect.size.x) / textureSize.x), m_weights[3] * (m_actualTextureRect.position.y / textureSize.y) }; } else { - m_vertices[0].texCoords = { m_actualTextureRect.left, m_actualTextureRect.top }; - m_vertices[2].texCoords = { m_actualTextureRect.left + m_actualTextureRect.width, m_actualTextureRect.top + m_actualTextureRect.height }; + m_vertices[0].texCoords = { m_actualTextureRect.position.x, m_actualTextureRect.position.y }; + m_vertices[2].texCoords = { m_actualTextureRect.position.x + m_actualTextureRect.size.x, m_actualTextureRect.position.y + m_actualTextureRect.size.y }; m_vertices[1].texCoords = { m_vertices[0].texCoords.x, m_vertices[2].texCoords.y }; m_vertices[3].texCoords = { m_vertices[2].texCoords.x, m_vertices[0].texCoords.y }; } @@ -537,11 +536,11 @@ sf::Vector2f ElasticSprite::priv_getVertexBasePosition(const unsigned int vertex switch (vertexIndex) { case 1u: - return sf::Vector2f(0.f, m_baseTextureRect.height); + return sf::Vector2f(0.f, m_baseTextureRect.size.y); case 2u: - return sf::Vector2f(m_baseTextureRect.width, m_baseTextureRect.height); + return sf::Vector2f(m_baseTextureRect.size.x, m_baseTextureRect.size.y); case 3u: - return sf::Vector2f(m_baseTextureRect.width, 0.f); + return sf::Vector2f(m_baseTextureRect.size.x, 0.f); case 0u: default: return { 0.f, 0.f }; diff --git a/src/SelbaWard/ElasticSprite.hpp b/src/SelbaWard/ElasticSprite.hpp index b33ecaa..bf7fdff 100644 --- a/src/SelbaWard/ElasticSprite.hpp +++ b/src/SelbaWard/ElasticSprite.hpp @@ -5,7 +5,7 @@ // // Elastic Sprite // -// Copyright(c) 2017-2023 M.J.Silk +// Copyright(c) 2017-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -49,7 +49,7 @@ class Vector2; namespace selbaward { -// SW Elastic Sprite v1.3.1 +// SW Elastic Sprite v1.3.2 class ElasticSprite : public sf::Drawable, public sf::Transformable { public: @@ -110,7 +110,7 @@ class ElasticSprite : public sf::Drawable, public sf::Transformable bool m_textureFlipX; bool m_textureFlipY; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices(sf::Transform Transform) const; sf::Vector2f priv_getVertexBasePosition(const unsigned int vertexIndex) const; }; diff --git a/src/SelbaWard/Exception.hpp b/src/SelbaWard/Exception.hpp deleted file mode 100644 index 1a98ca0..0000000 --- a/src/SelbaWard/Exception.hpp +++ /dev/null @@ -1,35 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// Selba Ward (https://github.com/Hapaxia/SelbaWard) -// -// Copyright(c) 2015-2023 M.J.Silk -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions : -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software.If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -// M.J.Silk -// MJSilk2@gmail.com -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef SELBAWARD_EXCEPTION_HPP -#define SELBAWARD_EXCEPTION_HPP - -#include "Common.hpp" - -#endif // SELBAWARD_EXCEPTION_HPP diff --git a/src/SelbaWard/GallerySprite.cpp b/src/SelbaWard/GallerySprite.cpp index b9087c1..7315f6f 100644 --- a/src/SelbaWard/GallerySprite.cpp +++ b/src/SelbaWard/GallerySprite.cpp @@ -5,7 +5,7 @@ // // Gallery Sprite // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -99,7 +99,7 @@ sf::Vector2f GallerySprite::getSize() const sf::Vector2f GallerySprite::getSize(const unsigned int exhibitNumber) const { const sf::FloatRect& exhibitRectangle{ priv_getExhibit(exhibitNumber).rectangle }; - return{ exhibitRectangle.width, exhibitRectangle.height }; + return{ exhibitRectangle.size.x, exhibitRectangle.size.y }; } void GallerySprite::setScaleFromTargetSize(const sf::Vector2f& targetSize) @@ -247,9 +247,8 @@ void GallerySprite::operator-=(const unsigned int exhibits) // PRIVATE -void GallerySprite::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void GallerySprite::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.texture = m_pTexture; states.transform *= getTransform(); target.draw(&m_vertices.front(), numberOfVertices, primitiveType, states); @@ -258,18 +257,18 @@ void GallerySprite::draw(sf::RenderTarget& target, const sf::RenderStates& inSta void GallerySprite::priv_updateVertices() { const Exhibit exhibit{ priv_getCurrentExhibit() }; - m_vertices[0].position = { -exhibit.anchor.x, exhibit.rectangle.height - exhibit.anchor.y }; + m_vertices[0].position = { -exhibit.anchor.x, exhibit.rectangle.size.y - exhibit.anchor.y }; m_vertices[1].position = -exhibit.anchor; - m_vertices[2].position = { exhibit.rectangle.width - exhibit.anchor.x, exhibit.rectangle.height - exhibit.anchor.y }; - m_vertices[3].position = { exhibit.rectangle.width - exhibit.anchor.x, -exhibit.anchor.y }; + m_vertices[2].position = { exhibit.rectangle.size.x - exhibit.anchor.x, exhibit.rectangle.size.y - exhibit.anchor.y }; + m_vertices[3].position = { exhibit.rectangle.size.x - exhibit.anchor.x, -exhibit.anchor.y }; if (m_pTexture == nullptr) return; - m_vertices[0].texCoords = { exhibit.rectangle.left, exhibit.rectangle.top + exhibit.rectangle.height }; - m_vertices[1].texCoords = { exhibit.rectangle.left, exhibit.rectangle.top }; - m_vertices[2].texCoords = { exhibit.rectangle.left + exhibit.rectangle.width, exhibit.rectangle.top + exhibit.rectangle.height }; - m_vertices[3].texCoords = { exhibit.rectangle.left + exhibit.rectangle.width, exhibit.rectangle.top }; + m_vertices[0].texCoords = { exhibit.rectangle.position.x, exhibit.rectangle.position.y + exhibit.rectangle.size.y }; + m_vertices[1].texCoords = { exhibit.rectangle.position.x, exhibit.rectangle.position.y }; + m_vertices[2].texCoords = { exhibit.rectangle.position.x + exhibit.rectangle.size.x, exhibit.rectangle.position.y + exhibit.rectangle.size.y }; + m_vertices[3].texCoords = { exhibit.rectangle.position.x + exhibit.rectangle.size.x, exhibit.rectangle.position.y }; } GallerySprite::Exhibit GallerySprite::priv_getCurrentExhibit() const diff --git a/src/SelbaWard/GallerySprite.hpp b/src/SelbaWard/GallerySprite.hpp index 1bbc3ce..e646e2b 100644 --- a/src/SelbaWard/GallerySprite.hpp +++ b/src/SelbaWard/GallerySprite.hpp @@ -5,7 +5,7 @@ // // Gallery Sprite // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -39,7 +39,7 @@ namespace selbaward { -// Gallery Sprite v1.1.2 +// Gallery Sprite v1.1.3 class GallerySprite : public sf::Drawable, public sf::Transformable { public: @@ -94,7 +94,7 @@ class GallerySprite : public sf::Drawable, public sf::Transformable unsigned int m_currentExhibit; std::vector m_exhibits; - virtual void draw(sf::RenderTarget&, const sf::RenderStates&) const; + void draw(sf::RenderTarget&, sf::RenderStates) const override; void priv_updateVertices(); Exhibit priv_getCurrentExhibit() const; Exhibit priv_getExhibit(unsigned int exhibitNumber) const; diff --git a/src/SelbaWard/Line.cpp b/src/SelbaWard/Line.cpp index 5f6b796..f7f5e5d 100644 --- a/src/SelbaWard/Line.cpp +++ b/src/SelbaWard/Line.cpp @@ -5,7 +5,7 @@ // // Line // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -104,17 +104,17 @@ sf::FloatRect Line::getLocalBounds() const minY = std::min(minY, m_quad[v].position.y); maxY = std::max(maxY, m_quad[v].position.y); } - box.left = minX; - box.top = minY; - box.width = maxX - minX; - box.height = maxY - minY; + box.position.x = minX; + box.position.y = minY; + box.size.x = maxX - minX; + box.size.y = maxY - minY; } else { - box.left = std::min(m_vertices[0].position.x, m_vertices[1].position.x); - box.top = std::min(m_vertices[0].position.y, m_vertices[1].position.y); - box.width = std::max(m_vertices[0].position.x, m_vertices[1].position.x) - box.left; - box.height = std::max(m_vertices[0].position.y, m_vertices[1].position.y) - box.top; + box.position.x = std::min(m_vertices[0].position.x, m_vertices[1].position.x); + box.position.y = std::min(m_vertices[0].position.y, m_vertices[1].position.y); + box.size.x = std::max(m_vertices[0].position.x, m_vertices[1].position.x) - box.position.x; + box.size.y = std::max(m_vertices[0].position.y, m_vertices[1].position.y) - box.position.y; } return box; } @@ -137,19 +137,19 @@ sf::FloatRect Line::getGlobalBounds() const minY = std::min(minY, transformedPosition.y); maxY = std::max(maxY, transformedPosition.y); } - box.left = minX; - box.top = minY; - box.width = maxX - minX; - box.height = maxY - minY; + box.position.x = minX; + box.position.y = minY; + box.size.x = maxX - minX; + box.size.y = maxY - minY; } else { const sf::Vector2f transformedStartPosition{ getTransform().transformPoint(m_vertices[0].position) }; const sf::Vector2f transformedEndPosition{ getTransform().transformPoint(m_vertices[1].position) }; - box.left = std::min(transformedStartPosition.x, transformedEndPosition.x); - box.top = std::min(transformedStartPosition.y, transformedEndPosition.y); - box.width = std::max(transformedStartPosition.x, transformedEndPosition.x) - box.left; - box.height = std::max(transformedStartPosition.y, transformedEndPosition.y) - box.top; + box.position.x = std::min(transformedStartPosition.x, transformedEndPosition.x); + box.position.y = std::min(transformedStartPosition.y, transformedEndPosition.y); + box.size.x = std::max(transformedStartPosition.x, transformedEndPosition.x) - box.position.x; + box.size.y = std::max(transformedStartPosition.y, transformedEndPosition.y) - box.position.y; } return box; } @@ -211,9 +211,8 @@ sf::FloatRect Line::getTextureRect() const // PRIVATE -void Line::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Line::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = nullptr; if (isThick()) @@ -244,10 +243,10 @@ void Line::updateQuad() m_quad[2u].position = m_vertices[1u].position + normalVector; m_quad[3u].position = m_vertices[1u].position - normalVector; - m_quad[0u].texCoords = { m_textureRect.left, m_textureRect.top }; - m_quad[1u].texCoords = { m_textureRect.left, m_textureRect.top + m_textureRect.height }; - m_quad[2u].texCoords = { m_textureRect.left + m_textureRect.width, m_textureRect.top }; - m_quad[3u].texCoords = { m_textureRect.left + m_textureRect.width, m_textureRect.top + m_textureRect.height }; + m_quad[0u].texCoords = { m_textureRect.position.x, m_textureRect.position.y }; + m_quad[1u].texCoords = { m_textureRect.position.x, m_textureRect.position.y + m_textureRect.size.y }; + m_quad[2u].texCoords = { m_textureRect.position.x + m_textureRect.size.x, m_textureRect.position.x }; + m_quad[3u].texCoords = { m_textureRect.position.x + m_textureRect.size.x, m_textureRect.position.x + m_textureRect.size.y }; } } // selbaward diff --git a/src/SelbaWard/Line.hpp b/src/SelbaWard/Line.hpp index e5e473d..c454f4e 100644 --- a/src/SelbaWard/Line.hpp +++ b/src/SelbaWard/Line.hpp @@ -5,7 +5,7 @@ // // Line // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -41,7 +41,7 @@ namespace selbaward { -// SW Line v1.2.3 +// SW Line v1.2.4 class Line : public sf::Drawable, public sf::Transformable { public: @@ -85,7 +85,7 @@ class Line : public sf::Drawable, public sf::Transformable const sf::Texture* m_texture; sf::FloatRect m_textureRect; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; bool isThick() const; void updateQuad(); }; diff --git a/src/SelbaWard/NinePatch.cpp b/src/SelbaWard/NinePatch.cpp index 482f0f9..f33ac24 100644 --- a/src/SelbaWard/NinePatch.cpp +++ b/src/SelbaWard/NinePatch.cpp @@ -5,7 +5,7 @@ // // NinePatch // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -45,13 +45,13 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe // scale positions topLeft = { 0.f, 0.f }; - bottomRight = { textureRectangle.width - 2.f, textureRectangle.height - 2.f }; + bottomRight = { textureRectangle.size.x - 2.f, textureRectangle.size.y - 2.f }; bool foundStart{ false }, foundEnd{ false }; - for (unsigned int x{ 1u }; x < static_cast(textureRectangle.width); ++x) + for (unsigned int x{ 1u }; x < static_cast(textureRectangle.size.x); ++x) { if (!foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + x, textureRectangle.position.y)) == sf::Color::Black) { foundStart = true; topLeft.x = x - 1.f; @@ -61,7 +61,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + x, textureRectangle.position.y)) == sf::Color::Black) bottomRight.x = x - 1.f; else break; @@ -69,11 +69,11 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } foundStart = false; foundEnd = false; - for (unsigned int y{ 1u }; y < static_cast(textureRectangle.height); ++y) + for (unsigned int y{ 1u }; y < static_cast(textureRectangle.size.y); ++y) { if (!foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left, textureRectangle.top + y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x, textureRectangle.position.y + y)) == sf::Color::Black) { foundStart = true; topLeft.y = y - 1.f; @@ -83,7 +83,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left, textureRectangle.top + y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x, textureRectangle.position.y + y)) == sf::Color::Black) bottomRight.y = y - 1.f; else break; @@ -92,15 +92,15 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe // content area contentTopLeft = { 0.f, 0.f }; - contentBottomRight = { textureRectangle.width - 2.f, textureRectangle.height - 2.f }; + contentBottomRight = { textureRectangle.size.x - 2.f, textureRectangle.size.y - 2.f }; foundStart = false; foundEnd = false; - const sf::Vector2u textureBottomRightPixel(textureRectangle.width - 1u, textureRectangle.height - 1u); - for (unsigned int x{ 1u }; x < static_cast(textureRectangle.width); ++x) + const sf::Vector2u textureBottomRightPixel(textureRectangle.size.x - 1u, textureRectangle.size.y - 1u); + for (unsigned int x{ 1u }; x < static_cast(textureRectangle.size.x); ++x) { if (!foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + x, textureRectangle.position.y + textureBottomRightPixel.y)) == sf::Color::Black) { foundStart = true; contentTopLeft.x = x - 1.f; @@ -110,7 +110,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + x, textureRectangle.top + textureBottomRightPixel.y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + x, textureRectangle.position.y + textureBottomRightPixel.y)) == sf::Color::Black) contentBottomRight.x = x - 1.f; else break; @@ -118,11 +118,11 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } foundStart = false; foundEnd = false; - for (unsigned int y{ 1u }; y < static_cast(textureRectangle.height); ++y) + for (unsigned int y{ 1u }; y < static_cast(textureRectangle.size.y); ++y) { if (!foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + textureBottomRightPixel.x, textureRectangle.position.y + y)) == sf::Color::Black) { foundStart = true; contentTopLeft.y = y - 1.f; @@ -132,7 +132,7 @@ void extractScalePositionsAndContentAreaFromTexture(const sf::Texture* const pTe } if (foundStart) { - if (image.getPixel(sf::Vector2u(textureRectangle.left + textureBottomRightPixel.x, textureRectangle.top + y)) == sf::Color::Black) + if (image.getPixel(sf::Vector2u(textureRectangle.position.x + textureBottomRightPixel.x, textureRectangle.position.y + y)) == sf::Color::Black) contentBottomRight.y = y - 1.f; else break; @@ -165,7 +165,7 @@ void NinePatch::setTexture(const sf::Texture& texture, const bool resetSize, con if (resetRect) m_textureRectangle = { { 0, 0 }, sf::Vector2i(m_texture->getSize()) }; //m_trimmedSize = sf::Vector2f(m_texture->getSize()) - trimAmount * 2.f; - m_trimmedSize = sf::Vector2f{ static_cast(m_textureRectangle.width), static_cast(m_textureRectangle.height) } -trimAmount * 2.f; + m_trimmedSize = sf::Vector2f{ static_cast(m_textureRectangle.size.x), static_cast(m_textureRectangle.size.y) } -trimAmount * 2.f; if (resetSize) m_size = m_trimmedSize; extractScalePositionsAndContentAreaFromTexture(m_texture, m_textureRectangle, m_scaleTopLeft, m_scaleBottomRight, m_contentTopLeft, m_contentBottomRight); @@ -191,7 +191,7 @@ void NinePatch::resetSize() void NinePatch::setTextureRect(const sf::IntRect textureRectangle, const bool resetSize) { m_textureRectangle = textureRectangle; - m_trimmedSize = sf::Vector2f{ static_cast(m_textureRectangle.width), static_cast(m_textureRectangle.height) } -trimAmount * 2.f; + m_trimmedSize = sf::Vector2f{ static_cast(m_textureRectangle.size.x), static_cast(m_textureRectangle.size.y) } -trimAmount * 2.f; if (resetSize) m_size = m_trimmedSize; if (m_texture != nullptr) @@ -242,9 +242,8 @@ bool NinePatch::isPointInsideTransformedContentArea(const sf::Vector2f point) co // PRIVATE -void NinePatch::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void NinePatch::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.texture = m_texture; states.transform *= getTransform(); target.draw(m_vertices.data(), 22u, m_primitiveType, states); @@ -330,7 +329,7 @@ void NinePatch::priv_updateVerticesTexCoords() m_vertices[21u].texCoords = { x3, y3 }; // offset trim and texture rectangle - const sf::Vector2f textureRectangleOffset{ static_cast(m_textureRectangle.left), static_cast(m_textureRectangle.top) }; + const sf::Vector2f textureRectangleOffset{ static_cast(m_textureRectangle.position.x), static_cast(m_textureRectangle.position.y) }; for (auto& vertex : m_vertices) vertex.texCoords += textureRectangleOffset + trimAmount; } diff --git a/src/SelbaWard/NinePatch.hpp b/src/SelbaWard/NinePatch.hpp index 0e30ed8..e66024c 100644 --- a/src/SelbaWard/NinePatch.hpp +++ b/src/SelbaWard/NinePatch.hpp @@ -5,7 +5,7 @@ // // NinePatch // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,7 @@ namespace selbaward { -// SW Nine Patch v1.4.3 +// SW Nine Patch v1.4.4 class NinePatch : public sf::Drawable, public sf::Transformable { public: @@ -71,7 +71,7 @@ class NinePatch : public sf::Drawable, public sf::Transformable sf::Vector2f m_contentBottomRight; sf::IntRect m_textureRectangle; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices(); void priv_updateVerticesPositions(); void priv_updateVerticesTexCoords(); diff --git a/src/SelbaWard/PaletteEnums.hpp b/src/SelbaWard/PaletteEnums.hpp index 80ca425..4ca0f9a 100644 --- a/src/SelbaWard/PaletteEnums.hpp +++ b/src/SelbaWard/PaletteEnums.hpp @@ -5,7 +5,7 @@ // // Palette Enums // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages diff --git a/src/SelbaWard/PieChart.cpp b/src/SelbaWard/PieChart.cpp index 2b3fd69..1ca56d9 100644 --- a/src/SelbaWard/PieChart.cpp +++ b/src/SelbaWard/PieChart.cpp @@ -5,7 +5,7 @@ // // Pie Chart // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -138,9 +138,8 @@ sf::FloatRect PieChart::getGlobalBounds() const // PRIVATE -void PieChart::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void PieChart::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_vertices.size() > 0) diff --git a/src/SelbaWard/PieChart.hpp b/src/SelbaWard/PieChart.hpp index a0896b6..64c49cd 100644 --- a/src/SelbaWard/PieChart.hpp +++ b/src/SelbaWard/PieChart.hpp @@ -5,7 +5,7 @@ // // Pie Chart // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ namespace selbaward { -// SW Pie Chart v1.0.3 +// SW Pie Chart v1.0.4 class PieChart : public sf::Drawable, public sf::Transformable { public: @@ -67,7 +67,7 @@ class PieChart : public sf::Drawable, public sf::Transformable std::vector m_vertices; sf::Vector2f m_size; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; }; inline void PieChart::setSize(sf::Vector2f size) diff --git a/src/SelbaWard/ProgressBar.cpp b/src/SelbaWard/ProgressBar.cpp index c1e4615..e0d67e0 100644 --- a/src/SelbaWard/ProgressBar.cpp +++ b/src/SelbaWard/ProgressBar.cpp @@ -5,7 +5,7 @@ // // Progress Bar // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -110,8 +110,8 @@ void ProgressBar::setTexture(const sf::Texture& texture, const bool resetRect) m_texture = &texture; if (resetRect) { - m_textureRectangle.width = m_texture->getSize().x; - m_textureRectangle.height = m_texture->getSize().y; + m_textureRectangle.size.x = m_texture->getSize().x; + m_textureRectangle.size.y = m_texture->getSize().y; } priv_updateGraphics(); } @@ -133,8 +133,8 @@ void ProgressBar::setBackgroundTexture(const sf::Texture& backgroundTexture, con m_backgroundTexture = &backgroundTexture; if (resetRect) { - m_backgroundTextureRectangle.width = m_backgroundTexture->getSize().x; - m_backgroundTextureRectangle.height = m_backgroundTexture->getSize().y; + m_backgroundTextureRectangle.size.x = m_backgroundTexture->getSize().x; + m_backgroundTextureRectangle.size.y = m_backgroundTexture->getSize().y; } priv_updateGraphics(); } @@ -195,9 +195,8 @@ sf::Vector2f ProgressBar::getAnchorProgressBottom() const // PRIVATE -void ProgressBar::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void ProgressBar::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); if (m_showBackground) target.draw(m_backgroundAndFrame, states); @@ -220,11 +219,11 @@ void ProgressBar::priv_updateGraphics() m_bar[2u].position = { width, 0.f }; m_bar[3u].position = { width, m_size.y }; sf::FloatRect textureRect{ m_textureRectangle }; - textureRect.width = textureRect.width * m_amount; - m_bar[0u].texCoords = { textureRect.left, textureRect.top }; - m_bar[1u].texCoords = { textureRect.left, textureRect.top + textureRect.height }; - m_bar[2u].texCoords = { textureRect.left + textureRect.width, textureRect.top }; - m_bar[3u].texCoords = { textureRect.left + textureRect.width, textureRect.top + textureRect.height }; + textureRect.size.x = textureRect.size.x * m_amount; + m_bar[0u].texCoords = { textureRect.position.x, textureRect.position.y }; + m_bar[1u].texCoords = { textureRect.position.x, textureRect.position.y + textureRect.size.y }; + m_bar[2u].texCoords = { textureRect.position.x + textureRect.size.x, textureRect.position.y }; + m_bar[3u].texCoords = { textureRect.position.x + textureRect.size.x, textureRect.position.y + textureRect.size.y }; for (auto& vertex : m_bar) vertex.color = m_color; } diff --git a/src/SelbaWard/ProgressBar.hpp b/src/SelbaWard/ProgressBar.hpp index 61a62dc..92ef179 100644 --- a/src/SelbaWard/ProgressBar.hpp +++ b/src/SelbaWard/ProgressBar.hpp @@ -5,7 +5,7 @@ // // Progress Bar // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -41,7 +41,7 @@ namespace selbaward { -// SW Progress Bar 1.1.2 +// SW Progress Bar 1.1.3 class ProgressBar : public sf::Drawable, public sf::Transformable { public: @@ -106,7 +106,7 @@ class ProgressBar : public sf::Drawable, public sf::Transformable sf::IntRect m_textureRectangle; sf::IntRect m_backgroundTextureRectangle; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateGraphics(); }; diff --git a/src/SelbaWard/Ring.cpp b/src/SelbaWard/Ring.cpp index 91649fd..a21a36b 100644 --- a/src/SelbaWard/Ring.cpp +++ b/src/SelbaWard/Ring.cpp @@ -5,7 +5,7 @@ // // Ring // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -205,9 +205,8 @@ float Ring::getSectorOffset() const // PRIVATE -void Ring::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Ring::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.texture = m_texture; states.transform *= getTransform(); @@ -229,7 +228,7 @@ void Ring::priv_updateVertices() it->position = { m_radius + std::sin(angle) * m_radius * (isInnerPoint ? m_hole : 1.f), m_radius - std::cos(angle) * m_radius * (isInnerPoint ? m_hole : 1.f), }; it->color = m_color; const sf::Vector2f scaledPosition{ it->position / (m_radius * 2.f) }; - it->texCoords = { scaledPosition.x * m_textureRect.width + m_textureRect.left, scaledPosition.y * m_textureRect.height + m_textureRect.top };; + it->texCoords = { scaledPosition.x * m_textureRect.size.x + m_textureRect.position.x, scaledPosition.y * m_textureRect.size.y + m_textureRect.position.y };; } } diff --git a/src/SelbaWard/Ring.hpp b/src/SelbaWard/Ring.hpp index a0090d9..b70d20f 100644 --- a/src/SelbaWard/Ring.hpp +++ b/src/SelbaWard/Ring.hpp @@ -5,7 +5,7 @@ // // Ring // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ namespace selbaward { -// SW Ring v1.1.3 +// SW Ring v1.1.4 class Ring : public sf::Drawable, public sf::Transformable { public: @@ -74,7 +74,7 @@ class Ring : public sf::Drawable, public sf::Transformable const sf::Texture* m_texture; sf::IntRect m_textureRect; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices(); }; diff --git a/src/SelbaWard/SpinningCard.cpp b/src/SelbaWard/SpinningCard.cpp index 455b788..4d447a1 100644 --- a/src/SelbaWard/SpinningCard.cpp +++ b/src/SelbaWard/SpinningCard.cpp @@ -5,7 +5,7 @@ // // SpinningCard // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -32,6 +32,8 @@ #include "SpinningCard.hpp" +#include + #include namespace selbaward @@ -64,18 +66,18 @@ SpinningCard::SpinningCard(const sf::Sprite& sprite) m_vertices[i].position = sprite.getPosition() - sprite.getOrigin(); // top-left // ...then, add offsets to individual vertices - m_vertices[0].position += sf::Vector2f(static_cast(m_initial.width) / 2, static_cast(m_initial.height) / 2); // centre - m_vertices[2].position += sf::Vector2f(m_initial.width, 0.f); // top-right - m_vertices[3].position += sf::Vector2f(m_initial.width, m_initial.height); // bottom-right - m_vertices[4].position += sf::Vector2f(0.f, m_initial.height); // bottom-left + m_vertices[0].position += sf::Vector2f(static_cast(m_initial.size.x) / 2, static_cast(m_initial.size.y) / 2); // centre + m_vertices[2].position += sf::Vector2f(m_initial.size.x, 0.f); // top-right + m_vertices[3].position += sf::Vector2f(m_initial.size.x, m_initial.size.y); // bottom-right + m_vertices[4].position += sf::Vector2f(0.f, m_initial.size.y); // bottom-left // set texture coordinates to the same as the sprite's (using the same method for texCoords as position above) for (unsigned int i{ 0 }; i < 5; ++i) - m_vertices[i].texCoords = sf::Vector2f(static_cast(sprite.getTextureRect().left), static_cast(sprite.getTextureRect().top)); // top-left - m_vertices[0].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().width) / 2, static_cast(sprite.getTextureRect().height) / 2); // centre - m_vertices[2].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().width), 0.f); // top-right - m_vertices[3].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().width), static_cast(sprite.getTextureRect().height)); // bottom-right - m_vertices[4].texCoords += sf::Vector2f(0.f, static_cast(sprite.getTextureRect().height)); // bottom-left + m_vertices[i].texCoords = sf::Vector2f(static_cast(sprite.getTextureRect().position.x), static_cast(sprite.getTextureRect().position.x)); // top-left + m_vertices[0].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().size.x) / 2, static_cast(sprite.getTextureRect().size.y) / 2); // centre + m_vertices[2].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().size.x), 0.f); // top-right + m_vertices[3].texCoords += sf::Vector2f(static_cast(sprite.getTextureRect().size.x), static_cast(sprite.getTextureRect().size.y)); // bottom-right + m_vertices[4].texCoords += sf::Vector2f(0.f, static_cast(sprite.getTextureRect().size.y)); // bottom-left // set colours of vertices to match sprite's colour for (unsigned int i{ 0 }; i < 5; ++i) @@ -85,7 +87,7 @@ SpinningCard::SpinningCard(const sf::Sprite& sprite) m_vertices[5] = m_vertices[1]; // store a pointer to the sprite's texture - m_pTexture = sprite.getTexture(); + m_pTexture = &sprite.getTexture(); } void SpinningCard::spin(float angleInDegrees) @@ -96,11 +98,11 @@ void SpinningCard::spin(float angleInDegrees) void SpinningCard::spinRadians(float angleInRadians) { angleInRadians -= m_pi / 2; - m_vertices[0].position = sf::Vector2f(m_initial.left + m_initial.width / 2, m_initial.top + m_initial.height / 2); - m_vertices[1].position = sf::Vector2f(m_initial.left + (std::sin(angleInRadians) + 1) * m_initial.width / 2, m_initial.top - std::cos(angleInRadians) * m_depth * m_initial.height / 2); - m_vertices[2].position = sf::Vector2f(m_initial.left + (std::sin(angleInRadians + m_pi) + 1) * m_initial.width / 2, m_initial.top - std::cos(angleInRadians + m_pi) * m_depth * m_initial.height / 2); - m_vertices[3].position = sf::Vector2f(m_initial.left + (std::sin(angleInRadians + m_pi) + 1) * m_initial.width / 2, m_initial.top + (std::cos(angleInRadians + m_pi) * m_depth + 2) * m_initial.height / 2); - m_vertices[4].position = sf::Vector2f(m_initial.left + (std::sin(angleInRadians) + 1) * m_initial.width / 2, m_initial.top + (std::cos(angleInRadians) * m_depth + 2) * m_initial.height / 2); + m_vertices[0].position = sf::Vector2f(m_initial.position.x + m_initial.size.x / 2, m_initial.position.y + m_initial.size.y / 2); + m_vertices[1].position = sf::Vector2f(m_initial.position.x + (std::sin(angleInRadians) + 1) * m_initial.size.x / 2, m_initial.position.y - std::cos(angleInRadians) * m_depth * m_initial.size.y / 2); + m_vertices[2].position = sf::Vector2f(m_initial.position.x + (std::sin(angleInRadians + m_pi) + 1) * m_initial.size.x / 2, m_initial.position.y - std::cos(angleInRadians + m_pi) * m_depth * m_initial.size.y / 2); + m_vertices[3].position = sf::Vector2f(m_initial.position.x + (std::sin(angleInRadians + m_pi) + 1) * m_initial.size.x / 2, m_initial.position.y + (std::cos(angleInRadians + m_pi) * m_depth + 2) * m_initial.size.y / 2); + m_vertices[4].position = sf::Vector2f(m_initial.position.x + (std::sin(angleInRadians) + 1) * m_initial.size.x / 2, m_initial.position.y + (std::cos(angleInRadians) * m_depth + 2) * m_initial.size.y / 2); // weld last vertex to second vertex (to complete the solid) m_vertices[5] = m_vertices[1]; @@ -114,11 +116,11 @@ void SpinningCard::spinVertically(float angleInDegrees) void SpinningCard::spinVerticallyRadians(float angleInRadians) { angleInRadians -= m_pi / 2; - m_vertices[0].position = sf::Vector2f(m_initial.left + m_initial.width / 2, m_initial.top + m_initial.height / 2); - m_vertices[1].position = sf::Vector2f(m_initial.left - std::cos(angleInRadians) * m_depth * m_initial.width / 2, m_initial.top + (std::sin(angleInRadians) + 1) * m_initial.height / 2); - m_vertices[4].position = sf::Vector2f(m_initial.left - std::cos(angleInRadians + m_pi) * m_depth * m_initial.width / 2, m_initial.top + (std::sin(angleInRadians + m_pi) + 1) * m_initial.height / 2); - m_vertices[3].position = sf::Vector2f(m_initial.left + (std::cos(angleInRadians + m_pi) * m_depth + 2) * m_initial.width / 2, m_initial.top + (std::sin(angleInRadians + m_pi) + 1) * m_initial.height / 2); - m_vertices[2].position = sf::Vector2f(m_initial.left + (std::cos(angleInRadians) * m_depth + 2) * m_initial.width / 2, m_initial.top + (std::sin(angleInRadians) + 1) * m_initial.height / 2); + m_vertices[0].position = sf::Vector2f(m_initial.position.x + m_initial.size.x / 2, m_initial.position.y + m_initial.size.y / 2); + m_vertices[1].position = sf::Vector2f(m_initial.position.x - std::cos(angleInRadians) * m_depth * m_initial.size.x / 2, m_initial.position.y + (std::sin(angleInRadians) + 1) * m_initial.size.y / 2); + m_vertices[4].position = sf::Vector2f(m_initial.position.x - std::cos(angleInRadians + m_pi) * m_depth * m_initial.size.x / 2, m_initial.position.y + (std::sin(angleInRadians + m_pi) + 1) * m_initial.size.y / 2); + m_vertices[3].position = sf::Vector2f(m_initial.position.x + (std::cos(angleInRadians + m_pi) * m_depth + 2) * m_initial.size.x / 2, m_initial.position.y + (std::sin(angleInRadians + m_pi) + 1) * m_initial.size.y / 2); + m_vertices[2].position = sf::Vector2f(m_initial.position.x + (std::cos(angleInRadians) * m_depth + 2) * m_initial.size.x / 2, m_initial.position.y + (std::sin(angleInRadians) + 1) * m_initial.size.y / 2); // weld last vertex to second vertex (to complete the solid) m_vertices[5] = m_vertices[1]; @@ -129,9 +131,8 @@ void SpinningCard::setDepth(float depth) m_depth = depth; } -void SpinningCard::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void SpinningCard::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); states.texture = m_pTexture; target.draw(m_vertices, states); diff --git a/src/SelbaWard/SpinningCard.hpp b/src/SelbaWard/SpinningCard.hpp index 5c968c8..982568d 100644 --- a/src/SelbaWard/SpinningCard.hpp +++ b/src/SelbaWard/SpinningCard.hpp @@ -5,7 +5,7 @@ // // Spinning Card // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -52,7 +52,7 @@ namespace selbaward { -// SpinningCard (v1.2.3) +// SpinningCard v1.2.4 class SpinningCard : public sf::Drawable, public sf::Transformable { public: @@ -75,7 +75,7 @@ class SpinningCard : public sf::Drawable, public sf::Transformable void setDepth(float depth); private: - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; sf::VertexArray m_vertices; const sf::Texture* m_pTexture; sf::FloatRect m_initial; diff --git a/src/SelbaWard/Sprite3d.cpp b/src/SelbaWard/Sprite3d.cpp index dc2e9d6..482c1f2 100644 --- a/src/SelbaWard/Sprite3d.cpp +++ b/src/SelbaWard/Sprite3d.cpp @@ -5,7 +5,7 @@ // // Sprite3d // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -142,7 +142,7 @@ Sprite3d::Sprite3d(const sf::Texture& texture, const sf::IntRect& textureRect, c Sprite3d::Sprite3d(const sf::Sprite& sprite) : Sprite3d() { - setTexture(*sprite.getTexture()); + setTexture(sprite.getTexture()); setTextureRect(sprite.getTextureRect()); this->setColor(sprite.getColor()); this->setOrigin(sprite.getOrigin()); @@ -165,9 +165,9 @@ const sf::Sprite Sprite3d::getSprite() const void Sprite3d::setTextureRect(const sf::IntRect& textureRectangle) { - m_textureOffset = sf::Vector2i(textureRectangle.left, textureRectangle.top); + m_textureOffset = sf::Vector2i(textureRectangle.position.x, textureRectangle.position.y); m_backTextureOffset = m_textureOffset; - m_size = sf::Vector2i(textureRectangle.width, textureRectangle.height); + m_size = sf::Vector2i(textureRectangle.size.x, textureRectangle.size.y); createPointGrid(); updateTransformedPoints(); updateVertices(); @@ -473,9 +473,8 @@ float Sprite3d::getDepth() const return m_depth; } -void Sprite3d::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Sprite3d::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; if (m_pTexture != nullptr) { updateTransformedPoints(); @@ -487,11 +486,7 @@ void Sprite3d::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) else states.texture = m_pTexture; -#ifdef USE_SFML_PRE_2_4 - target.draw(&m_vertices[0], m_vertices.size(), sf::PrimitiveType::TrianglesStrip, states); -#else // USE_SFML_PRE_2_4 - target.draw(&m_vertices[0], m_vertices.size(), sf::PrimitiveType::TriangleStrip, states); -#endif // USE_SFML_PRE_2_4 + target.draw(m_vertices.data(), m_vertices.size(), sf::PrimitiveType::TriangleStrip, states); } } diff --git a/src/SelbaWard/Sprite3d.hpp b/src/SelbaWard/Sprite3d.hpp index 97e2f50..674f950 100644 --- a/src/SelbaWard/Sprite3d.hpp +++ b/src/SelbaWard/Sprite3d.hpp @@ -5,7 +5,7 @@ // // Sprite3d // -// Copyright(c) 2015-2023 M.J.Silk +// Copyright(c) 2015-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -44,7 +44,7 @@ namespace selbaward { -// Sprite3d version 1.2.2 +// Sprite3d version 1.2.3 class Sprite3d : public sf::Drawable, public sf::Transformable { public: @@ -181,7 +181,7 @@ class Sprite3d : public sf::Drawable, public sf::Transformable void createPointGrid() const; // needs to be const to allow dynamic subdivision - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void updateTransformedPoints() const; void updateVertices() const; void updateGlobalCorners() const; diff --git a/src/SelbaWard/Starfield.cpp b/src/SelbaWard/Starfield.cpp index b7fdcab..a469c40 100644 --- a/src/SelbaWard/Starfield.cpp +++ b/src/SelbaWard/Starfield.cpp @@ -5,7 +5,7 @@ // // Starfield // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -130,9 +130,8 @@ void Starfield::setColor(const sf::Color color) // PRIVATE -void Starfield::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Starfield::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.transform *= getTransform(); const unsigned int size{ static_cast(m_vertices.size()) }; if (size > 0) diff --git a/src/SelbaWard/Starfield.hpp b/src/SelbaWard/Starfield.hpp index 49c8d86..d279776 100644 --- a/src/SelbaWard/Starfield.hpp +++ b/src/SelbaWard/Starfield.hpp @@ -5,7 +5,7 @@ // // Starfield // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ namespace selbaward { -// SW Starfield v1.1.1 +// SW Starfield v1.1.2 class Starfield : public sf::Drawable, public sf::Transformable { public: @@ -58,7 +58,7 @@ class Starfield : public sf::Drawable, public sf::Transformable sf::Vector2f m_size; sf::Color m_color; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; }; } // namespace selbaward diff --git a/src/SelbaWard/TileMap.hpp b/src/SelbaWard/TileMap.hpp index 6e8cb9e..f646622 100644 --- a/src/SelbaWard/TileMap.hpp +++ b/src/SelbaWard/TileMap.hpp @@ -5,7 +5,7 @@ // // Tile Map // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -45,7 +45,7 @@ namespace selbaward { -// SW Tile Map v2.0.3 +// SW Tile Map v2.0.4 template class TileMap : public sf::Drawable, public sf::Transformable { @@ -151,7 +151,7 @@ class TileMap : public sf::Drawable, public sf::Transformable mutable sf::RenderTexture m_renderTexture; mutable std::vector m_render; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices() const; void priv_updateRender() const; void priv_recreateRenderTexture(); diff --git a/src/SelbaWard/TileMap.inl b/src/SelbaWard/TileMap.inl index bd5f1e3..614ce41 100644 --- a/src/SelbaWard/TileMap.inl +++ b/src/SelbaWard/TileMap.inl @@ -5,7 +5,7 @@ // // Tile Map // -// Copyright(c) 2016-2023 M.J.Silk +// Copyright(c) 2016-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -372,7 +372,7 @@ void TileMap::redraw() // PRIVATE template -void TileMap::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void TileMap::draw(sf::RenderTarget& target, sf::RenderStates states) const { if (m_redrawRequired) { @@ -381,7 +381,6 @@ void TileMap::draw(sf::RenderTarget& target, const sf::RenderStates& inStates m_redrawRequired = false; } - sf::RenderStates states{ inStates }; states.texture = &m_renderTexture.getTexture(); states.transform = getTransform(); @@ -476,9 +475,9 @@ void TileMap::priv_recreateRenderTexture() { bool createSucceeded{ false }; if (m_gridSize.x < 2 || m_gridSize.y < 2) - createSucceeded = m_renderTexture.create({ 1u, 1u }); + createSucceeded = m_renderTexture.resize({ 1u, 1u }); else - createSucceeded = m_renderTexture.create({ (m_gridSize.x - 1) * m_textureTileSize.x, (m_gridSize.y - 1) * m_textureTileSize.y }); + createSucceeded = m_renderTexture.resize({ (m_gridSize.x - 1) * m_textureTileSize.x, (m_gridSize.y - 1) * m_textureTileSize.y }); m_redrawRequired = true; } From 8eb511ae4b330ba02bfd34844a55d71fdb9fc04d Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Thu, 23 Jan 2025 22:19:22 +0000 Subject: [PATCH 07/10] Update readme.md --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index 8d9230c..52a817a 100644 --- a/readme.md +++ b/readme.md @@ -12,6 +12,10 @@ Contents: **Bitmap Text**, **Console Screen**, **Crosshair**, **Elastic Sprite** Feedback and suggestions for new objects always welcome... +--- +**IMPORTANT NOTE: The main branch is now targetted for SFML 3. If you are still using SFML 2, you can use the sfml2 branch.** +--- + [Selba Ward thread on the SFML forum][SFMLForumSelbaWard] [Wiki]: https://github.com/Hapaxia/SelbaWard/wiki From 50b4908c7641c88055460d29c9a7d310c586c76e Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Thu, 23 Jan 2025 22:34:01 +0000 Subject: [PATCH 08/10] update Spline to v1.7 updated Spline to version 1.7: added copy constructor, added ability to export all positions at once, fixed draw method by removing leading "virtual" and adding trailing "override", changed pointer to front() to just data(), updated year (to 2025) in header. --- src/SelbaWard/Spline.cpp | 134 +++++++++++++++++++++++++++++++++++---- src/SelbaWard/Spline.hpp | 18 ++++-- 2 files changed, 135 insertions(+), 17 deletions(-) diff --git a/src/SelbaWard/Spline.cpp b/src/SelbaWard/Spline.cpp index 37264bb..aad514b 100644 --- a/src/SelbaWard/Spline.cpp +++ b/src/SelbaWard/Spline.cpp @@ -5,7 +5,7 @@ // // Spline // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -180,7 +180,11 @@ Spline::Spline(const std::size_t vertexCount, const sf::Vector2f initialPosition , m_interpolatedVertices() , m_interpolatedVerticesUnitTangents() , m_outputVertices() +#ifdef USE_SFML_PRE_2_4 + , m_primitiveType(sf::PrimitiveType::LinesStrip) +#else // USE_SFML_PRE_2_4 , m_primitiveType(sf::PrimitiveType::LineStrip) +#endif // USE_SFML_PRE_2_4 , m_interpolationSteps{ 0u } , m_useBezier{ false } , m_handlesVertices() @@ -199,6 +203,69 @@ Spline::Spline(std::initializer_list list) m_vertices[index++].position = position; } +Spline::Spline(const Spline& spline) + : m_throwExceptions{ spline.m_throwExceptions } + , m_isClosed{ spline.m_isClosed } + , m_isRandomNormalOffsetsActivated{ spline.m_isRandomNormalOffsetsActivated } + , m_thickCornerType{ spline.m_thickCornerType } + , m_thickStartCapType{ spline.m_thickStartCapType } + , m_thickEndCapType{ spline.m_thickEndCapType } + , m_roundedThickCornerInterpolationLevel{ spline.m_roundedThickCornerInterpolationLevel } + , m_roundedThickStartCapInterpolationLevel{ spline.m_roundedThickStartCapInterpolationLevel } + , m_roundedThickEndCapInterpolationLevel{ spline.m_roundedThickEndCapInterpolationLevel } + , m_maxPointLength{ spline.m_maxPointLength } + , m_automaticallyUpdateRandomNormalOffset{ spline.m_automaticallyUpdateRandomNormalOffset } + //, m_vertices(vertexCount, Vertex(initialPosition)) + , m_color{ spline.m_color } + , m_thickness{ spline.m_thickness } + , m_randomNormalOffsetRange{ spline.m_randomNormalOffsetRange } + //, m_interpolatedVertices() + //, m_interpolatedVerticesUnitTangents() + //, m_outputVertices() + , m_primitiveType{ spline.m_primitiveType } + , m_interpolationSteps{ spline.m_interpolationSteps } + , m_useBezier{ spline.m_useBezier } + //, m_handlesVertices() + , m_showHandles{ spline.m_showHandles } + , m_lockHandleMirror{ spline.m_lockHandleMirror } + , m_lockHandleAngle{ spline.m_lockHandleAngle } +{ + m_vertices = spline.m_vertices; + m_interpolatedVertices = spline.m_interpolatedVertices; + m_interpolatedVerticesUnitTangents = spline.m_interpolatedVerticesUnitTangents; + m_outputVertices = spline.m_outputVertices; + m_handlesVertices = spline.m_handlesVertices; +} + +Spline& Spline::operator=(const Spline& spline) +{ + m_throwExceptions = spline.m_throwExceptions; + m_isClosed = spline.m_isClosed; + m_isRandomNormalOffsetsActivated = spline.m_isRandomNormalOffsetsActivated; + m_thickCornerType = spline.m_thickCornerType; + m_thickStartCapType = spline.m_thickStartCapType; + m_thickEndCapType = spline.m_thickEndCapType; + m_roundedThickCornerInterpolationLevel = spline.m_roundedThickCornerInterpolationLevel; + m_roundedThickStartCapInterpolationLevel = spline.m_roundedThickStartCapInterpolationLevel; + m_roundedThickEndCapInterpolationLevel = spline.m_roundedThickEndCapInterpolationLevel; + m_maxPointLength = spline.m_maxPointLength; + m_vertices = spline.m_vertices; + m_color = spline.m_color; + m_thickness = spline.m_thickness; + m_randomNormalOffsetRange = spline.m_randomNormalOffsetRange; + m_interpolatedVerticesUnitTangents = spline.m_interpolatedVerticesUnitTangents; + m_outputVertices = spline.m_outputVertices; + m_primitiveType = spline.m_primitiveType; + m_interpolationSteps = spline.m_interpolationSteps; + m_useBezier = spline.m_useBezier; + m_handlesVertices = spline.m_handlesVertices; + m_showHandles = spline.m_showHandles; + m_lockHandleMirror = spline.m_lockHandleMirror; + m_lockHandleAngle = spline.m_lockHandleAngle; + + return *this; +} + float Spline::getLength() const { if (m_vertices.size() < 2) @@ -276,7 +343,7 @@ void Spline::update() } if (m_isClosed) { - + m_interpolatedVertices.back().position = m_vertices.front().position; m_interpolatedVertices.back().color = m_color; } @@ -484,6 +551,27 @@ void Spline::rotate(const float angle, const sf::Vector2f origin) } } +void Spline::scale(const float scale, const sf::Vector2f origin, const bool scaleThickness, const bool scaleHandles) +{ + for (auto& vertex : m_vertices) + { + vertex.position = ((vertex.position - origin) * scale) + origin; + if (scaleHandles) + { + vertex.frontHandle *= scale; + vertex.backHandle *= scale; + } + } + if (scaleThickness) + m_thickness *= scale; +} + +void Spline::move(const sf::Vector2f offset) +{ + for (auto& vertex : m_vertices) + vertex.position += offset; +} + void Spline::setRandomNormalOffsetsActivated(const bool randomNormalOffsetsActivated) { m_isRandomNormalOffsetsActivated = randomNormalOffsetsActivated; @@ -787,7 +875,7 @@ sf::Vector2f Spline::getInterpolatedPosition(const std::size_t interpolationOffs std::size_t Spline::getInterpolatedPositionCount() const { - return ((m_isClosed) ? (m_vertices.size() * priv_getNumberOfPointsPerVertex()) : ((m_vertices.size() - 1u) * priv_getNumberOfPointsPerVertex() + 1u)); + return ((m_isClosed) ? (m_vertices.size() * priv_getNumberOfPointsPerVertex() + 1u) : ((m_vertices.size() - 1u) * priv_getNumberOfPointsPerVertex() + 1u)); } sf::Vector2f Spline::getInterpolatedPositionTangent(const std::size_t interpolationOffset, const std::size_t index) const @@ -833,18 +921,37 @@ float Spline::getInterpolatedPositionThicknessCorrectionScale(const std::size_t return sideOffsetLength * 2 / getInterpolatedPositionThickness(interpolationOffset, index); } +std::vector Spline::exportAllPositions() const +{ + std::vector positions(m_vertices.size()); + for (std::size_t i{ 0u }; i < positions.size(); ++i) + positions[i] = m_vertices[i].position; + if (m_isClosed) + positions.push_back(m_vertices[0u].position); + return positions; +} + +std::vector Spline::exportAllInterpolatedPositions() const +{ + std::vector positions(m_interpolatedVertices.size()); + for (std::size_t i{ 0u }; i < positions.size(); ++i) + positions[i] = m_interpolatedVertices[i].position; + if (m_isClosed) + positions.push_back(m_vertices[0u].position); + return positions; +} + // PRIVATE -void Spline::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Spline::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.texture = nullptr; if (m_outputVertices.size() > 0) target.draw(m_outputVertices.data(), m_outputVertices.size(), (priv_isThick() ? thickPrimitiveType : m_primitiveType), states); if (m_showHandles && m_handlesVertices.size() > 1) - target.draw(&m_handlesVertices.front(), m_handlesVertices.size(), sf::PrimitiveType::Lines, states); + target.draw(m_handlesVertices.data(), m_handlesVertices.size(), sf::PrimitiveType::Lines, states); } bool Spline::priv_isValidVertexIndex(const std::size_t vertexIndex) const @@ -908,6 +1015,9 @@ void Spline::priv_updateOutputVertices() else if (m_isClosed) nextVertex = m_vertices.begin(); + const sf::Color color{ m_color * linearInterpolation(currentVertex->color, nextVertex->color, vertexRatio) }; + m_outputVertices[outputIndex].color = color; + sf::Vector2f tangentUnit{ *(m_interpolatedVerticesUnitTangents.begin() + (it - begin)) }; if (m_isClosed || it != last) { @@ -1047,7 +1157,7 @@ void Spline::priv_updateOutputVertices() capOffset = tangentUnit * halfWidth; } - const sf::Vector2f forwardLine{ ((it != last) ? (it + 1)->position - it->position : (m_isClosed ? (begin + 1)->position - begin->position : it->position - (it - 1)->position )) }; + const sf::Vector2f forwardLine{ ((it != last) ? (it + 1)->position - it->position : (m_isClosed ? (begin + 1)->position - begin->position : it->position - (it - 1)->position)) }; const sf::Vector2f forwardUnit{ forwardLine / vectorLength(forwardLine) }; const sf::Vector2f backwardLine{ ((it != begin) ? it->position - (it - 1)->position : (m_isClosed ? it->position - (last)->position : (it + 1)->position - it->position)) }; const sf::Vector2f backwardUnit{ backwardLine / vectorLength(backwardLine) }; @@ -1071,7 +1181,7 @@ void Spline::priv_updateOutputVertices() itThick->color = color; itThick++->position = isClockwise ? insidePoint : outsidePoint; } - break; + break; case ThickCornerType::PointClip: case ThickCornerType::PointLimit: case ThickCornerType::Bevel: @@ -1148,7 +1258,7 @@ void Spline::priv_updateOutputVertices() } } } - break; + break; case ThickCornerType::Round: { if (it == begin) @@ -1199,7 +1309,7 @@ void Spline::priv_updateOutputVertices() } } } - break; + break; } } if (m_isClosed) @@ -1208,7 +1318,7 @@ void Spline::priv_updateOutputVertices() m_outputVertices.begin()->position = (itThick - 2)->position; (m_outputVertices.begin() + 1)->position = (itThick - 1)->position; } - + if (!m_isClosed && (m_thickEndCapType == ThickCapType::Round)) { std::vector::iterator vertex{ m_vertices.end() - 1u }; @@ -1230,7 +1340,7 @@ void Spline::priv_updateOutputVertices() itThick++->position = vertex->position - vector; } } - + } } diff --git a/src/SelbaWard/Spline.hpp b/src/SelbaWard/Spline.hpp index b729a14..39e6ab7 100644 --- a/src/SelbaWard/Spline.hpp +++ b/src/SelbaWard/Spline.hpp @@ -5,7 +5,7 @@ // // Spline // -// Copyright(c) 2014-2023 M.J.Silk +// Copyright(c) 2014-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ namespace selbaward { -// SW Spline v1.6.2 +// SW Spline v1.7.0 class Spline : public sf::Drawable { public: @@ -70,6 +70,9 @@ class Spline : public sf::Drawable Spline(std::size_t vertexCount = 0u, sf::Vector2f initialPosition = { 0.f, 0.f }); Spline(std::initializer_list list); // pass vertices' positions (sf::Vector2f) to the constructor (sets size automatically) + Spline(const Spline& spline); + Spline& operator=(const Spline& spline); + void update(); void updateOutputVertices(); @@ -92,6 +95,8 @@ class Spline : public sf::Drawable bool getClosed() const; void rotate(float rotation, sf::Vector2f origin); + void scale(float scale, sf::Vector2f origin, bool scaleThickness = true, bool scaleHandles = true); + void move(sf::Vector2f offset); void setRandomNormalOffsetsActivated(bool randomNormalOffsetsActivated); bool getRandomNormalOffsetsActivated() const; @@ -130,7 +135,7 @@ class Spline : public sf::Drawable void removeVertex(std::size_t index); void removeVertices(std::size_t index, std::size_t numberOfVertices = 0u); // if numberOfVertices is zero (the default), removes all vertices from specified index until the end void reverseVertices(); - + void setPosition(std::size_t index, sf::Vector2f position = { 0.f, 0.f }); void setPositions(std::size_t index, std::size_t numberOfVertices = 0u, sf::Vector2f position = { 0.f, 0.f }); // if numberOfVertices is zero (the default), sets positions of all vertices from specified index until the end void setPositions(const std::vector& positions, std::size_t index = 0u); @@ -187,6 +192,9 @@ class Spline : public sf::Drawable float getInterpolatedPositionThicknessCorrectionScale(std::size_t interpolationOffset, std::size_t index = 0u) const; // index is control vertex offset std::size_t getInterpolatedPositionCount() const; + std::vector exportAllPositions() const; + std::vector exportAllInterpolatedPositions() const; + @@ -204,7 +212,7 @@ class Spline : public sf::Drawable std::size_t m_roundedThickStartCapInterpolationLevel; // number of interpolations. 0 is flat (same as no cap), 1 is triangle, 2+ circular. std::size_t m_roundedThickEndCapInterpolationLevel; // number of interpolations. 0 is flat (same as no cap), 1 is triangle, 2+ circular. float m_maxPointLength; // maximum length of point when limited or clipped. ignored when using other corner types including Point. - bool m_automaticallyUpdateRandomNormalOffset; + const bool m_automaticallyUpdateRandomNormalOffset; std::vector m_vertices; sf::Color m_color; @@ -223,7 +231,7 @@ class Spline : public sf::Drawable bool m_lockHandleMirror; bool m_lockHandleAngle; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; bool priv_isValidVertexIndex(std::size_t vertexIndex) const; bool priv_testVertexIndex(std::size_t vertexIndex, const std::string& exceptionMessage) const; bool priv_isThick() const; From 21a8b713257fd5b2983efebda6331d93cb7696a4 Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Thu, 23 Jan 2025 22:52:21 +0000 Subject: [PATCH 09/10] update PixelDisplay to v1.0.2 update year (to 2025) modified SFML 2 code to SFML 3 code. --- src/SelbaWard/PixelDisplay.cpp | 187 ++++++++++++++++----------------- src/SelbaWard/PixelDisplay.hpp | 6 +- 2 files changed, 96 insertions(+), 97 deletions(-) diff --git a/src/SelbaWard/PixelDisplay.cpp b/src/SelbaWard/PixelDisplay.cpp index ead3db7..09ddb67 100644 --- a/src/SelbaWard/PixelDisplay.cpp +++ b/src/SelbaWard/PixelDisplay.cpp @@ -5,7 +5,7 @@ // // Pixel Display // -// Copyright(c) 2019-2023 M.J.Silk +// Copyright(c) 2019-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -203,19 +203,19 @@ void PixelDisplay::shiftRight(const unsigned int amount, const unsigned int star void PixelDisplay::scrollUp(const unsigned int color, const unsigned int amount, sf::IntRect selectionRectangle) { assert(color < m_palette.size()); - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - for (unsigned int x{ 0u }; x < rectangle.width; ++x) + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) { - const unsigned int index{ (rectangle.top + y) * m_resolution.x + rectangle.left + x }; - m_pixels[index] = (y == rectangle.height - 1u) ? color : m_pixels[index + m_resolution.x]; + const unsigned int index{ (rectangle.position.y + y) * m_resolution.x + rectangle.position.x + x }; + m_pixels[index] = (y == rectangle.size.y - 1u) ? color : m_pixels[index + m_resolution.x]; } } priv_updatePixels(); @@ -224,19 +224,19 @@ void PixelDisplay::scrollUp(const unsigned int color, const unsigned int amount, void PixelDisplay::scrollDown(const unsigned int color, const unsigned int amount, sf::IntRect selectionRectangle) { assert(color < m_palette.size()); - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - for (unsigned int x{ 0u }; x < rectangle.width; ++x) + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) { - const unsigned int index{ (rectangle.top + rectangle.height - y - 1u) * m_resolution.x + rectangle.left + x }; - m_pixels[index] = (y == rectangle.height - 1u) ? color : m_pixels[index - m_resolution.x]; + const unsigned int index{ (rectangle.position.y + rectangle.size.y - y - 1u) * m_resolution.x + rectangle.position.x + x }; + m_pixels[index] = (y == rectangle.size.y - 1u) ? color : m_pixels[index - m_resolution.x]; } } priv_updatePixels(); @@ -245,18 +245,18 @@ void PixelDisplay::scrollDown(const unsigned int color, const unsigned int amoun void PixelDisplay::scrollLeft(const unsigned int color, const unsigned int amount, sf::IntRect selectionRectangle) { assert(color < m_palette.size()); - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - const unsigned int firstPixelIndex{ (rectangle.top + y) * m_resolution.x + rectangle.left }; - shiftVectorDown(m_pixels, amount, firstPixelIndex, rectangle.width); - m_pixels[firstPixelIndex + rectangle.width - 1u] = color; + const unsigned int firstPixelIndex{ (rectangle.position.y + y) * m_resolution.x + rectangle.position.x }; + shiftVectorDown(m_pixels, amount, firstPixelIndex, rectangle.size.x); + m_pixels[firstPixelIndex + rectangle.size.x - 1u] = color; } priv_updatePixels(); } @@ -264,17 +264,17 @@ void PixelDisplay::scrollLeft(const unsigned int color, const unsigned int amoun void PixelDisplay::scrollRight(const unsigned int color, const unsigned int amount, sf::IntRect selectionRectangle) { assert(color < m_palette.size()); - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - const unsigned int firstPixelIndex{ (rectangle.top + y) * m_resolution.x + rectangle.left }; - shiftVectorUp(m_pixels, amount, firstPixelIndex, rectangle.width); + const unsigned int firstPixelIndex{ (rectangle.position.y + y) * m_resolution.x + rectangle.position.x }; + shiftVectorUp(m_pixels, amount, firstPixelIndex, rectangle.size.x); m_pixels[firstPixelIndex] = color; } priv_updatePixels(); @@ -282,22 +282,22 @@ void PixelDisplay::scrollRight(const unsigned int color, const unsigned int amou void PixelDisplay::scrollWrapUp(const unsigned int amount, sf::IntRect selectionRectangle) { - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - std::vector tempRow(rectangle.width); - for (unsigned int x{ 0u }; x < rectangle.width; ++x) - tempRow[x] = m_pixels[rectangle.top * m_resolution.x + rectangle.left + x]; - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + std::vector tempRow(rectangle.size.x); + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) + tempRow[x] = m_pixels[rectangle.position.y * m_resolution.x + rectangle.position.x + x]; + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - for (unsigned int x{ 0u }; x < rectangle.width; ++x) + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) { - const unsigned int index{ (rectangle.top + y) * m_resolution.x + rectangle.left + x }; - m_pixels[index] = (y == rectangle.height - 1u) ? tempRow[x] : m_pixels[index + m_resolution.x]; + const unsigned int index{ (rectangle.position.y + y) * m_resolution.x + rectangle.position.x + x }; + m_pixels[index] = (y == rectangle.size.y - 1u) ? tempRow[x] : m_pixels[index + m_resolution.x]; } } priv_updatePixels(); @@ -305,22 +305,22 @@ void PixelDisplay::scrollWrapUp(const unsigned int amount, sf::IntRect selection void PixelDisplay::scrollWrapDown(const unsigned int amount, sf::IntRect selectionRectangle) { - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - std::vector tempRow(rectangle.width); - for (unsigned int x{ 0u }; x < rectangle.width; ++x) - tempRow[x] = m_pixels[(rectangle.top + rectangle.height - 1u) * m_resolution.x + rectangle.left + x]; - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + std::vector tempRow(rectangle.size.x); + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) + tempRow[x] = m_pixels[(rectangle.position.y + rectangle.size.y - 1u) * m_resolution.x + rectangle.position.x + x]; + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { - for (unsigned int x{ 0u }; x < rectangle.width; ++x) + for (unsigned int x{ 0u }; x < rectangle.size.x; ++x) { - const unsigned int index{ (rectangle.top + rectangle.height - y - 1u) * m_resolution.x + rectangle.left + x }; - m_pixels[index] = (y == rectangle.height - 1u) ? tempRow[x] : m_pixels[index - m_resolution.x]; + const unsigned int index{ (rectangle.position.y + rectangle.size.y - y - 1u) * m_resolution.x + rectangle.position.x + x }; + m_pixels[index] = (y == rectangle.size.y - 1u) ? tempRow[x] : m_pixels[index - m_resolution.x]; } } priv_updatePixels(); @@ -328,28 +328,28 @@ void PixelDisplay::scrollWrapDown(const unsigned int amount, sf::IntRect selecti void PixelDisplay::scrollWrapLeft(const unsigned int amount, sf::IntRect selectionRectangle) { - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) - shiftVectorWrapDown(m_pixels, amount, (rectangle.top + y) * m_resolution.x + rectangle.left, rectangle.width); + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) + shiftVectorWrapDown(m_pixels, amount, (rectangle.position.y + y) * m_resolution.x + rectangle.position.x, rectangle.size.x); priv_updatePixels(); } void PixelDisplay::scrollWrapRight(const unsigned int amount, sf::IntRect selectionRectangle) { - assert(selectionRectangle.left < static_cast(m_resolution.x)); - assert(selectionRectangle.top < static_cast(m_resolution.y)); - if (selectionRectangle.width == 0u) - selectionRectangle.width = m_resolution.x - selectionRectangle.left; - if (selectionRectangle.height == 0u) - selectionRectangle.height = m_resolution.y - selectionRectangle.top; - for (unsigned int y{ 0u }; y < static_cast(selectionRectangle.height); ++y) - shiftVectorWrapUp(m_pixels, amount, (selectionRectangle.top + y) * m_resolution.x + selectionRectangle.left, selectionRectangle.width); + assert(selectionRectangle.position.x < static_cast(m_resolution.x)); + assert(selectionRectangle.position.y < static_cast(m_resolution.y)); + if (selectionRectangle.size.x == 0u) + selectionRectangle.size.x = m_resolution.x - selectionRectangle.position.x; + if (selectionRectangle.size.y == 0u) + selectionRectangle.size.y = m_resolution.y - selectionRectangle.position.y; + for (unsigned int y{ 0u }; y < static_cast(selectionRectangle.size.y); ++y) + shiftVectorWrapUp(m_pixels, amount, (selectionRectangle.position.y + y) * m_resolution.x + selectionRectangle.position.x, selectionRectangle.size.x); priv_updatePixels(); } @@ -521,9 +521,8 @@ sf::Vector2u PixelDisplay::getSizeOfBuffer(const unsigned int index) const // PRIVATE -void PixelDisplay::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void PixelDisplay::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; states.texture = nullptr; states.transform *= getTransform(); target.draw(m_vertices.data(), m_vertices.size(), sf::PrimitiveType::Triangles, states); @@ -575,13 +574,13 @@ unsigned int PixelDisplay::priv_getRandomColor() const void PixelDisplay::priv_copyToBufferFromSelectionRectangle(Buffer& buffer, const sf::IntRect& selectionRectangle) { assert(priv_isSelectionRectangleFullyContained(selectionRectangle)); - buffer.width = selectionRectangle.width; - buffer.pixels.resize(selectionRectangle.width * selectionRectangle.height); + buffer.width = selectionRectangle.size.x; + buffer.pixels.resize(selectionRectangle.size.x * selectionRectangle.size.y); sf::Rect rectangle(selectionRectangle); - for (unsigned int y{ 0u }; y < rectangle.height; ++y) + for (unsigned int y{ 0u }; y < rectangle.size.y; ++y) { for (unsigned int x{ 0u }; x < buffer.width; ++x) - buffer.pixels[y * buffer.width + x] = m_pixels[x + rectangle.left, y + rectangle.top]; + buffer.pixels[y * buffer.width + x] = m_pixels[(y + rectangle.position.y) * buffer.width + (x + rectangle.position.x)]; } } @@ -600,12 +599,12 @@ void PixelDisplay::priv_pasteOffsetBuffer(const Buffer& buffer, const sf::Vector bool PixelDisplay::priv_isSelectionRectangleFullyContained(const sf::IntRect& selectionRectangle) { - return (selectionRectangle.left >= 0 && - selectionRectangle.top >= 0 && - selectionRectangle.width >= 0 && - selectionRectangle.height >= 0 && - static_cast(selectionRectangle.left + selectionRectangle.width) <= m_resolution.x && - static_cast(selectionRectangle.top + selectionRectangle.height) <= m_resolution.y); + return (selectionRectangle.position.x >= 0 && + selectionRectangle.position.y >= 0 && + selectionRectangle.size.x >= 0 && + selectionRectangle.size.y >= 0 && + static_cast(selectionRectangle.position.x + selectionRectangle.size.x) <= m_resolution.x && + static_cast(selectionRectangle.position.y + selectionRectangle.size.y) <= m_resolution.y); } } // namespace selbaward diff --git a/src/SelbaWard/PixelDisplay.hpp b/src/SelbaWard/PixelDisplay.hpp index 484898e..241bd26 100644 --- a/src/SelbaWard/PixelDisplay.hpp +++ b/src/SelbaWard/PixelDisplay.hpp @@ -5,7 +5,7 @@ // // Pixel Display // -// Copyright(c) 2019-2023 M.J.Silk +// Copyright(c) 2019-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ namespace selbaward { -// SW PixelDisplay v1.0.1 +// SW PixelDisplay v1.0.2 class PixelDisplay : public sf::Drawable, public sf::Transformable { public: @@ -117,7 +117,7 @@ class PixelDisplay : public sf::Drawable, public sf::Transformable }; std::vector m_buffers; - virtual void draw(sf::RenderTarget& target, const sf::RenderStates& states) const; + void draw(sf::RenderTarget& target, sf::RenderStates states) const override; void priv_updateVertices(); void priv_updatePixels(); void priv_updatePixel(const unsigned int index); From 8a3718f4c4925e15e411b778b338a7ea615190f7 Mon Sep 17 00:00:00 2001 From: Hapaxia Date: Thu, 23 Jan 2025 22:59:34 +0000 Subject: [PATCH 10/10] update Polygon to v1.4 update Polygon to version 1.4: allow constructor to take vertex positions from initializer list, allow a Polygon to be constructed from another polygon (constructor or assigned), allow direct access to a Polygon's vertex, allow ability to switch direction of vertices, allow ability to set colour and texture co-ordinates for each vertex, allow the usage of a texture, adds ability to change the triangle limit, adds automatic wireframe, adds ability to get information such as its perimeter or area, adds a point-in-polygon test, adds local and global bounds, adds ability to get "centroid" and "centre of mass" (different things), allows the exporting of vertex positions or wireframe vertices, allow holes. --- src/SelbaWard/Polygon.cpp | 972 ++++++++++++++++++++++++++++++-------- src/SelbaWard/Polygon.hpp | 81 +++- 2 files changed, 860 insertions(+), 193 deletions(-) diff --git a/src/SelbaWard/Polygon.cpp b/src/SelbaWard/Polygon.cpp index dcbb491..7749971 100644 --- a/src/SelbaWard/Polygon.cpp +++ b/src/SelbaWard/Polygon.cpp @@ -5,7 +5,7 @@ // // Polygon // -// Copyright(c) 2022-2023 M.J.Silk +// Copyright(c) 2022-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -33,24 +33,65 @@ #include "Polygon.hpp" #include +#include +#include +#include namespace { +constexpr bool doThrowExceptions{ true }; + const std::string exceptionPrefix{ "Polygon: " }; +inline float crossProduct(const sf::Vector2f& a, const sf::Vector2f& b) +{ + return (a.x * b.y) - (a.y * b.x); +} + +inline float lengthSquared(const sf::Vector2f& v) +{ + return (v.x * v.x) + (v.y * v.y); +} + +inline float length(const sf::Vector2f& v) +{ + return std::sqrt(lengthSquared(v)); +} + inline bool isSecondVectorAntiClockwiseOfFirstVector(const sf::Vector2f& first, const sf::Vector2f& second) { return (first.x * second.y) < (first.y * second.x); } -inline bool pointIsInsideTriangle(const std::vector& points, sf::Vector2f point) +inline bool pointIsInsideTriangle(const std::vector& points, const sf::Vector2f point) +{ + long double point1X{ static_cast(points[0].x) }; + long double point1Y{ static_cast(points[0].y) }; + long double point2X{ static_cast(points[1].x) }; + long double point2Y{ static_cast(points[1].y) }; + long double point3X{ static_cast(points[2].x) }; + long double point3Y{ static_cast(points[2].y) }; + long double pointX{ static_cast(point.x) }; + long double pointY{ static_cast(point.y) }; + + long double denominatorMultiplier{ 1.l / ((point2Y - point3Y) * (point1X - point3X) + (point3X - point2X) * (point1Y - point3Y)) }; + long double a{ ((point2Y - point3Y) * (pointX - point3X) + (point3X - point2X) * (pointY - point3Y)) * denominatorMultiplier }; + long double b{ ((point3Y - point1Y) * (pointX - point3X) + (point1X - point3X) * (pointY - point3Y)) * denominatorMultiplier }; + long double c{ 1.l - a - b }; + return a >= 0.l && a <= 1.l && b >= 0.l && b <= 1.l && c >= 0.l && c <= 1.l; +} + +inline float areaOfTriangle(const std::vector& points) { - float denominatorMultiplier{ 1.f / ((points[1u].y - points[2u].y) * (points[0u].x - points[2u].x) + (points[2u].x - points[1u].x) * (points[0u].y - points[2u].y)) }; - float a{ ((points[1u].y - points[2u].y) * (point.x - points[2u].x) + (points[2u].x - points[1u].x) * (point.y - points[2u].y)) * denominatorMultiplier }; - float b{ ((points[2u].y - points[0u].y) * (point.x - points[2u].x) + (points[0u].x - points[2u].x) * (point.y - points[2u].y)) * denominatorMultiplier }; - float c{ 1.f - a - b }; - return a >= 0.f && a <= 1.f && b >= 0.f && b <= 1.f && c >= 0.f && c <= 1.f; + const sf::Vector2f a{ points[0u] }; + const sf::Vector2f b{ points[1u] }; + const sf::Vector2f c{ points[2u] }; + const float ab{ length(b - a) }; + const float bc{ length(c - b) }; + const float ca{ length(a - c) }; + const float halfPerimeter{ (ab + bc + ca) / 2.f }; + return std::sqrt(halfPerimeter * (halfPerimeter - ab) * (halfPerimeter - bc) * (halfPerimeter - ca)); } } // namespace @@ -59,14 +100,66 @@ namespace selbaward { Polygon::Polygon() - : m_outputVertices() - , m_vertices() + : m_texture{ nullptr } + , m_vertices{} + , m_triangles{} + , m_outputVertices{} + , m_holeStartIndices{} , m_color{ sf::Color::White } + , m_showWireframe{ false } + , m_wireframeVertices{} + , m_wireframeColor{ sf::Color::White } , m_triangulationMethod{ TriangulationMethod::BasicEarClip } , m_meshRefinementMethod{ MeshRefinementMethod::None } - , m_throwExceptions{ true } + , m_triangleLimit{ 10000u } + , m_reverseDirection{ false } +{ + +} + +Polygon::Polygon(std::initializer_list list) + : Polygon() +{ + m_vertices.resize(list.size()); + std::size_t index{ 0u }; + for (auto& position : list) + m_vertices[index++].position = position; +} + +Polygon::Polygon(const Polygon& other) + : m_texture{ other.m_texture } + , m_vertices{ other.m_vertices } + , m_triangles{ other.m_triangles } + , m_outputVertices{ other.m_outputVertices } + , m_holeStartIndices{ other.m_holeStartIndices } + , m_color{ other.m_color } + , m_showWireframe{ other.m_showWireframe } + , m_wireframeVertices{ other.m_wireframeVertices } + , m_wireframeColor{ other.m_wireframeColor } + , m_triangulationMethod{ other.m_triangulationMethod } + , m_meshRefinementMethod{ other.m_meshRefinementMethod } + , m_triangleLimit{ other.m_triangleLimit } + , m_reverseDirection{ other.m_reverseDirection } { +} +Polygon& Polygon::operator=(const Polygon& other) +{ + m_texture = other.m_texture; + m_vertices = other.m_vertices; + m_triangles = other.m_triangles; + m_outputVertices = other.m_outputVertices; + m_holeStartIndices = other.m_holeStartIndices; + m_color = other.m_color; + m_showWireframe = other.m_showWireframe; + m_wireframeVertices = other.m_wireframeVertices; + m_wireframeColor = other.m_wireframeColor; + m_triangulationMethod = other.m_triangulationMethod; + m_meshRefinementMethod = other.m_meshRefinementMethod; + m_triangleLimit = other.m_triangleLimit; + m_reverseDirection = other.m_reverseDirection; + + return *this; } void Polygon::update() @@ -104,6 +197,16 @@ Polygon::MeshRefinementMethod Polygon::getMeshRefinementMethod() const return m_meshRefinementMethod; } +void Polygon::setReverseDirection(const bool reverseDirection) +{ + m_reverseDirection = reverseDirection; +} + +bool Polygon::getReverseDirection() const +{ + return m_reverseDirection; +} + void Polygon::reserveVertices(const std::size_t numberOfVertices) { if (numberOfVertices == 0) @@ -139,6 +242,221 @@ sf::Vector2f Polygon::getVertexPosition(const std::size_t index) const return m_vertices[index].position; } +void Polygon::setVertexColor(const std::size_t index, const sf::Color color) +{ + if (!priv_testVertexIndex(index, "Cannot set vertex colour.")) + return; + + m_vertices[index].color = color; +} + +sf::Color Polygon::getVertexColor(const std::size_t index) const +{ + if (!priv_testVertexIndex(index, "Cannot get vertex colour.")) + return sf::Color{}; + + return m_vertices[index].color; +} + +void Polygon::setVertexTexCoords(std::size_t index, sf::Vector2f texCoords) +{ + if (!priv_testVertexIndex(index, "Cannot set vertex texcoords.")) + return; + + m_vertices[index].texCoords = texCoords; +} + +sf::Vector2f Polygon::getVertexTexCoords(std::size_t index) const +{ + if (!priv_testVertexIndex(index, "Cannot get vertex texcoords.")) + return{ 0.f, 0.f }; + + return m_vertices[index].texCoords; +} + +void Polygon::setTexture(const sf::Texture& texture) +{ + m_texture = &texture; +} + +void Polygon::setTexture() +{ + m_texture = nullptr; +} + +void Polygon::setTriangleLimit(const std::size_t triangleLimit) +{ + m_triangleLimit = triangleLimit; +} + +std::size_t Polygon::getTriangleLimit() const +{ + return m_triangleLimit; +} + +void Polygon::setShowWireframe(bool showWireframe) +{ + m_showWireframe = showWireframe; +} + +bool Polygon::getShowWireframe() const +{ + return m_showWireframe; +} + +void Polygon::setWireframeColor(sf::Color wireframeColor) +{ + m_wireframeColor = wireframeColor; +} + +sf::Color Polygon::getWireframeColor() const +{ + return m_wireframeColor; +} + +float Polygon::getPerimeter() const +{ + const std::size_t numberOfVertices{ m_vertices.size() }; + float perimeter{ 0.f }; + const bool hasHoles{ !m_holeStartIndices.empty() }; + for (std::size_t i{ 0u }; i < numberOfVertices; ++i) + { + std::size_t nextI{ i + 1u }; + + const auto holeIt{ std::find(m_holeStartIndices.begin(), m_holeStartIndices.end(), nextI) }; + if (hasHoles && (holeIt != m_holeStartIndices.end())) + { + if (holeIt == m_holeStartIndices.begin()) + nextI = 0u; + else + nextI = *(holeIt - 1u); + } + + if ((nextI + 1u) > numberOfVertices) + nextI = 0u; + + perimeter += length(m_vertices[(nextI < numberOfVertices) ? nextI : 0u].position - m_vertices[i].position); + } + return perimeter; +} + +float Polygon::getArea() const +{ + float area{ 0.f }; + for (auto& triangle : m_triangles) + area += areaOfTriangle({ m_vertices[triangle[0u]].position, m_vertices[triangle[1u]].position, m_vertices[triangle[2u]].position }); + return area; +} + +bool Polygon::isPointInside(const sf::Vector2f point) const +{ + for (const auto& triangle : m_triangles) + { + if (pointIsInsideTriangle({ m_vertices[triangle[0u]].position, m_vertices[triangle[1u]].position, m_vertices[triangle[2u]].position }, point)) + return true; + } + return false; +} + +sf::FloatRect Polygon::getLocalBounds() const +{ + if (m_vertices.empty()) + return {}; + + const std::size_t numberOfVertices{ getHoleStartIndex(0u) }; + sf::Vector2f topLeft{ m_vertices[0u].position }; + sf::Vector2f bottomRight{ topLeft }; + for (std::size_t i{ 1u }; i < numberOfVertices; ++i) + { + const sf::Vector2f position{ m_vertices[i].position }; + topLeft.x = std::min(topLeft.x, position.x); + topLeft.y = std::min(topLeft.y, position.y); + bottomRight.x = std::max(bottomRight.x, position.x); + bottomRight.y = std::max(bottomRight.y, position.y); + } + return { topLeft, bottomRight - topLeft }; +} + +sf::FloatRect Polygon::getGlobalBounds() const +{ + return getTransform().transformRect(getLocalBounds()); +} + +sf::Vector2f Polygon::getCentroid() const +{ + const std::size_t numberOfVerticesToUse{ getHoleStartIndex(0u) }; + sf::Vector2f total{ 0.f, 0.f }; + for (std::size_t i{ 0u }; i < numberOfVerticesToUse; ++i) + total += m_vertices[i].position; + return total / static_cast(numberOfVerticesToUse); +} + +sf::Vector2f Polygon::getCenterOfMass() const +{ + float totalArea{ 0.f }; + sf::Vector2f total{ 0.f, 0.f }; + for (const auto& triangle : m_triangles) + { + const sf::Vector2f point1{ m_vertices[triangle[0u]].position }; + const sf::Vector2f point2{ m_vertices[triangle[1u]].position }; + const sf::Vector2f point3{ m_vertices[triangle[2u]].position }; + const sf::Vector2f current{ point1 + point2 + point3 }; + const float area{ areaOfTriangle({ point1, point2, point3 }) }; + total += (current * area); + totalArea += area; + } + //const float numberOfTriangles{ static_cast(m_triangles.size()) }; + //return (total / (numberOfTriangles * 3u)) / (totalArea / numberOfTriangles); + /* + c = (t / 3n) / (a / n) + = n(t / 3n) / a + = (nt / 3n) / a + = (t / 3) / a + = t / 3a + */ + return total / (totalArea * 3.f); +} + +void Polygon::addHoleStartIndex(const std::size_t index) +{ + m_holeStartIndices.push_back(index); +} + +void Polygon::clearHoleStartIndices() +{ + m_holeStartIndices.clear(); +} + +void Polygon::setHoleStartIndices(const std::vector& indices) +{ + m_holeStartIndices = indices; +} + +void Polygon::setNumberOfHoles(std::size_t numberOfHoles) +{ + m_holeStartIndices.resize(numberOfHoles); +} + +void Polygon::setHoleStartIndex(const std::size_t holeIndex, const std::size_t holeStartIndex) +{ + if (!priv_testHoleIndex(holeIndex, "Cannot set hole start index.")) + return; + + m_holeStartIndices[holeIndex] = holeStartIndex; +} + +std::size_t Polygon::getNumberOfHoles() const +{ + return m_holeStartIndices.size(); +} + +std::size_t Polygon::getHoleStartIndex(const std::size_t holeIndex) const +{ + if (holeIndex >= m_holeStartIndices.size()) + return m_vertices.size(); + return m_holeStartIndices[holeIndex]; +} + void Polygon::reverseVertices() { std::reverse(m_vertices.begin(), m_vertices.end()); @@ -151,6 +469,35 @@ void Polygon::importVertexPositions(const std::vector& positions) m_vertices[i].position = positions[i]; } +std::vector Polygon::exportVertexPositions() const +{ + const std::size_t numberOfVertices{ m_vertices.size() }; + std::vector positions(numberOfVertices); + for (std::size_t i{ 0u }; i < numberOfVertices; ++i) + positions[i] = m_vertices[i].position; + return positions; +} + +std::vector Polygon::exportVertexPositionsOuterOnly() const +{ + const std::size_t numberOfVertices{ getHoleStartIndex(0u) }; + std::vector positions(numberOfVertices); + for (std::size_t i{ 0u }; i < numberOfVertices; ++i) + positions[i] = m_vertices[i].position; + return positions; +} + +std::vector Polygon::exportVertexPositionsHoleOnly(std::size_t holeIndex) const +{ + const std::size_t startIndex{ getHoleStartIndex(holeIndex) }; + const std::size_t endIndex{ getHoleStartIndex(holeIndex + 1u) }; + const std::size_t numberOfVertices{ endIndex - startIndex }; + std::vector positions(numberOfVertices); + for (std::size_t i{ 0u }; i < numberOfVertices; ++i) + positions[i] = m_vertices[startIndex + i].position; + return positions; +} + std::vector Polygon::exportTriangulatedPositions() const { std::vector positions(m_triangles.size() * 3u); @@ -163,6 +510,14 @@ std::vector Polygon::exportTriangulatedPositions() const return positions; } +std::vector Polygon::exportWireframePositions() const +{ + std::vector positions(m_wireframeVertices.size()); + for (std::size_t i{ 0u }; i < m_wireframeVertices.size(); ++i) + positions[i] = m_wireframeVertices[i].position; + return positions; +} + @@ -170,13 +525,17 @@ std::vector Polygon::exportTriangulatedPositions() const // PRIVATE -void Polygon::draw(sf::RenderTarget& target, const sf::RenderStates& inStates) const +void Polygon::draw(sf::RenderTarget& target, sf::RenderStates states) const { - sf::RenderStates states{ inStates }; - states.texture = nullptr; + states.texture = m_texture; states.transform *= getTransform(); - if (m_outputVertices.size() > 0) + if (!m_outputVertices.empty()) target.draw(m_outputVertices.data(), m_outputVertices.size(), sf::PrimitiveType::Triangles, states); + if (m_showWireframe && !m_wireframeVertices.empty()) + { + states.texture = nullptr; + target.draw(m_wireframeVertices.data(), m_wireframeVertices.size(), sf::PrimitiveType::Lines, states); + } } void Polygon::priv_update() @@ -194,9 +553,12 @@ void Polygon::priv_updateOutputVertices() for (std::size_t v{ 0u }; v < 3u; ++v) { m_outputVertices[baseIndex + v].position = m_vertices[m_triangles[t][v]].position; - m_outputVertices[baseIndex + v].color = m_color; + m_outputVertices[baseIndex + v].color = m_color * m_vertices[m_triangles[t][v]].color; + m_outputVertices[baseIndex + v].texCoords = m_vertices[m_triangles[t][v]].texCoords; } } + + priv_buildWireframe(); } void Polygon::priv_triangulate() @@ -208,280 +570,472 @@ void Polygon::priv_triangulate() case TriangulationMethod::BasicEarClip: priv_triangulateBasicEarClip(); break; + case TriangulationMethod::EarClip: + priv_triangulateEarClip(); + break; } } -void Polygon::priv_triangulateBasicEarClip() +void Polygon::priv_triangulateEarClip() { - constexpr std::size_t stopAfterThisNumberOfTrianglesHaveBeenCreated{ 100u }; - // ear clipping method // polygon points must be anti-clockwise + // hole points must be clockwise // number of triangles will always be (number of points - 2) - // avoid movement in memory when resizing - m_triangles.clear(); - m_triangles.reserve(m_vertices.size() - 2u); + // vertexNumbers is the order of the vertices (can re-use vertices) + // this is a single stream of vertices creating the polygon (after the holes are added, this becomes a single polygon) + std::vector vertexNumbers(m_vertices.size()); + std::size_t vertexNumbersSize{ vertexNumbers.size() }; + for (std::size_t i{ 0u }; i < vertexNumbersSize; ++i) + vertexNumbers[i] = i; - // indices for each of the vertices/points - std::vector indices(m_vertices.size()); - const size_t indicesSize{ indices.size() }; + if (!m_holeStartIndices.empty()) + { + std::sort(m_holeStartIndices.begin(), m_holeStartIndices.end()); + vertexNumbersSize = m_holeStartIndices[0u]; + } + const std::vector holeVertexNumbers(vertexNumbers.begin() + vertexNumbersSize, vertexNumbers.end()); + const std::size_t holeVertexNumbersSize{ holeVertexNumbers.size() }; + vertexNumbers.erase(vertexNumbers.begin() + vertexNumbersSize, vertexNumbers.end()); + // now, vertexNumbers is polygon vertex numbers (including any hole already cut in - later on) and holeVertexNumbers is the hole vertex numbers (all of them - no need to remove or rearrange this) + + // indices is the list of indices of the vertex numbers in order + // each index is treated as a separate vertex, even if it's technically the same vertex as another (same vertex numbers) + std::vector indices(vertexNumbersSize); + std::size_t indicesSize{ indices.size() }; for (std::size_t i{ 0u }; i < indicesSize; ++i) indices[i] = i; // points lists (to keep track of their state) + // note that these store indices - their numbers refer to which index to access: e.g. m_vertices[vertexNumbers[indices[reflex]]] std::vector reflex; std::vector convex; std::vector ear; - reflex.reserve(m_vertices.size() - 3u); // impossible for vertices to be reflex without enough convex (need at least 3 convex to make a polygon) - convex.reserve(m_vertices.size()); - ear.reserve(m_vertices.size()); - - // analyse points - for (std::size_t i{ 0u }; i < indicesSize; ++i) - { - const std::size_t prev{ (i > 0u) ? (i - 1u) : (indicesSize - 1u) }; - const std::size_t next{ (i < (indicesSize - 1u)) ? (i + 1u) : 0u }; - - const sf::Vector2f prevLine{ m_vertices[indices[i]].position - m_vertices[indices[prev]].position }; - const sf::Vector2f nextLine{ m_vertices[indices[next]].position - m_vertices[indices[i]].position }; - if (isSecondVectorAntiClockwiseOfFirstVector(prevLine, nextLine)) + std::function isEar = + [&](const std::size_t i, const std::size_t p, const std::size_t n, const std::size_t current) { - convex.push_back(i); bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indicesSize; ++other) + for (std::size_t other{ 0u }; other < vertexNumbers.size(); ++other) { - if ((other == i) || (other == prev) || (other == next)) + if ((vertexNumbers[other] == vertexNumbers[i]) || (vertexNumbers[other] == vertexNumbers[p]) || (vertexNumbers[other] == vertexNumbers[n]) || (vertexNumbers[other] == vertexNumbers[current])) continue; - if (pointIsInsideTriangle({ m_vertices[indices[prev]].position, m_vertices[indices[i]].position, m_vertices[indices[next]].position }, m_vertices[indices[other]].position)) + if (pointIsInsideTriangle({ m_vertices[vertexNumbers[p]].position, m_vertices[vertexNumbers[i]].position, m_vertices[vertexNumbers[n]].position }, m_vertices[vertexNumbers[other]].position)) { aPointIsInside = true; break; } } - if (!aPointIsInside) - ear.push_back(indices[i]); - } - else - { - reflex.push_back(indices[i]); - } - } - - // process - while (indices.size() > 3u) - { - std::size_t currentPoint{ ear.front() }; - std::vector::iterator currentIt{ std::find(indices.begin(), indices.end(), currentPoint) }; - std::size_t current{ static_cast(std::distance(indices.begin(), currentIt)) }; - std::size_t prev{ (current > 0u) ? (current - 1u) : (indices.size() - 1u) }; - std::size_t next{ (current < (indices.size() - 1u)) ? (current + 1u) : 0u }; - - TriangleIndices triangle{ indices[prev], indices[current], indices[next] }; - m_triangles.push_back(triangle); - + return !aPointIsInside; + }; + std::function isEarAnalysis = + [&](const std::size_t i, const std::size_t p, const std::size_t n) + { + return isEar(i, p, n, i); + }; - std::vector::iterator earPrevIt{ std::find(ear.begin(), ear.end(), indices[prev]) }; - if (earPrevIt != ear.end()) + std::function retest = + [&](const std::size_t i, const std::size_t p, const std::size_t n, const std::size_t current) { - // if ear, re-test for ear only (might not still be one) + std::vector::iterator reflexIt{ std::find(reflex.begin(), reflex.end(), indices[i]) }; + if (reflexIt != reflex.end()) + { + // if reflex, re-test + const sf::Vector2f pLine{ m_vertices[vertexNumbers[indices[i]]].position - m_vertices[vertexNumbers[indices[p]]].position }; + const sf::Vector2f nLine{ m_vertices[vertexNumbers[indices[n]]].position - m_vertices[vertexNumbers[indices[i]]].position }; - std::size_t i{ prev }; + if (m_reverseDirection != isSecondVectorAntiClockwiseOfFirstVector(pLine, nLine)) + { + reflex.erase(reflexIt); + convex.push_back(indices[i]); + } + } - const std::size_t p{ (i > 0u) ? (i - 1u) : (indices.size() - 1u) }; - const std::size_t n{ next }; + std::vector::iterator convexIt{ std::find(convex.begin(), convex.end(), indices[i]) }; + if (convexIt != convex.end()) + { + // if convex, re-test for ear only (must still be convex) + const bool isNowEar{ isEar(indices[i], indices[p], indices[n], indices[current]) }; + const std::vector::iterator it{ std::find(ear.begin(), ear.end(), indices[i]) }; + if (isNowEar && (it == ear.end())) + ear.push_back(indices[i]); + else if (!isNowEar && (it != ear.end())) + ear.erase(it); + } + }; - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) + std::function analysePoints = + [&]() + { + for (std::size_t i{ 0u }; i < indicesSize; ++i) { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; + const std::size_t prev{ (i > 0u) ? (i - 1u) : (indicesSize - 1u) }; + const std::size_t next{ (i < (indicesSize - 1u)) ? (i + 1u) : 0u }; - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) + const sf::Vector2f prevLine{ m_vertices[vertexNumbers[indices[i]]].position - m_vertices[vertexNumbers[indices[prev]]].position }; + const sf::Vector2f nextLine{ m_vertices[vertexNumbers[indices[next]]].position - m_vertices[vertexNumbers[indices[i]]].position }; + + if (m_reverseDirection != !isSecondVectorAntiClockwiseOfFirstVector(prevLine, nextLine)) + reflex.push_back(indices[i]); + else { - aPointIsInside = true; - break; + convex.push_back(indices[i]); + if (isEarAnalysis(indices[i], indices[prev], indices[next])) + ear.push_back(indices[i]); } } - if (aPointIsInside) - ear.erase(earPrevIt); + }; + + reflex.reserve(m_vertices.size() - 3u); // impossible for vertices to be reflex without enough convex (need at least 3 convex to make a polygon) + convex.reserve(m_vertices.size()); // any number (up to all) of the vertices may be convex although at least 3 are required + ear.reserve(m_vertices.size() - 2u); // with one ear per vertex, the final ear requires 3 vertices + + analysePoints(); + + if (!m_holeStartIndices.empty()) + { + struct Hole + { + std::size_t start; + std::size_t length; + float maxX; + }; + std::vector holeInfo(m_holeStartIndices.size()); + + for (std::size_t h{ 0u }; h < holeInfo.size(); ++h) + { + holeInfo[h].start = m_holeStartIndices[h] - vertexNumbersSize; + if (h < (holeInfo.size() - 1u)) + holeInfo[h].length = m_holeStartIndices[h + 1u] - m_holeStartIndices[h]; + else + holeInfo[h].length = holeVertexNumbersSize - (m_holeStartIndices[h] - vertexNumbersSize); + holeInfo[h].maxX = m_vertices[holeVertexNumbers[holeInfo[h].start]].position.x; + for (std::size_t v{ 1u }; v < holeInfo[h].length; ++v) + holeInfo[h].maxX = std::max(holeInfo[h].maxX, m_vertices[holeVertexNumbers[holeInfo[h].start + v]].position.x); } + // sort order from the furthest right so that first hole is furthest right + std::sort(holeInfo.begin(), holeInfo.end(), [](const Hole& left, const Hole& right) { return left.maxX > right.maxX; }); + float vertexMinX{ m_vertices[0u].position.x }; + float vertexMaxX{ m_vertices[0u].position.x }; + for (std::size_t v{ 1u }; v < m_vertices.size(); ++v) + { + vertexMinX = std::min(vertexMinX, m_vertices[v].position.x); + vertexMaxX = std::max(vertexMaxX, m_vertices[v].position.x); + } + const float maxWidth{ vertexMaxX - vertexMinX }; + + const sf::Vector2f rayVector{ 1.f, 0.f }; - std::vector::iterator earNextIt{ std::find(ear.begin(), ear.end(), indices[next]) }; - if (earNextIt != ear.end()) + for (std::size_t h{ 0u }; h < holeInfo.size(); ++h) { - // if ear, re-test for ear only (might not still be one) + const std::size_t holeStart{ holeInfo[h].start }; + const std::size_t holeLength{ holeInfo[h].length }; - std::size_t i{ next }; + // choose where the cut appears + std::size_t cutPolygonVertexNumber; + std::size_t cutHoleVertexNumber; + std::size_t cutHoleHoleIndex{ holeStart }; - const std::size_t p{ prev }; - const std::size_t n{ (i < (indices.size() - 1u)) ? (i + 1u) : 0u }; - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) - { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) + // hole vertex (the easy bit) + float furthestRight{ m_vertices[holeVertexNumbers[holeStart]].position.x }; + for (std::size_t v{ 1u }; v < holeLength; ++v) + { + const float currentRight{ m_vertices[holeVertexNumbers[holeStart + v]].position.x }; + if (currentRight > furthestRight) { - aPointIsInside = true; - break; + furthestRight = currentRight; + cutHoleHoleIndex = holeStart + v; } } - if (aPointIsInside) - ear.erase(earNextIt); - } + cutHoleVertexNumber = holeVertexNumbers[cutHoleHoleIndex]; - std::vector::iterator convexPrevIt{ std::find(convex.begin(), convex.end(), indices[prev]) }; - if (convexPrevIt != convex.end()) - { - // if convex, re-test for ear only (must still be convex) + // polygon vertex (the hard bit) + const sf::Vector2f rayOrigin{ m_vertices[cutHoleVertexNumber].position }; + sf::Vector2f pointOfIntersection{ 0.f, 0.f }; - if (std::find(ear.begin(), ear.end(), indices[prev]) == ear.end()) + // find closest edge (to the right) + std::size_t candidateIndex{ 0u }; + float distance{ maxWidth }; + bool isEndIndex{ false }; + for (std::size_t v{ 0u }; v < vertexNumbersSize; ++v) { - std::size_t i{ prev }; + const std::size_t edgeStartIndex{ v }; + const std::size_t edgeEndIndex{ (v < (vertexNumbersSize - 1u)) ? v + 1u : 0u }; - const std::size_t p{ (i > 0u) ? (i - 1u) : (indices.size() - 1u) }; - const std::size_t n{ next }; + const sf::Vector2f edgeStart{ m_vertices[vertexNumbers[edgeStartIndex]].position }; + const sf::Vector2f edgeEnd{ m_vertices[vertexNumbers[edgeEndIndex]].position }; + const sf::Vector2f edgeVector{ edgeEnd - edgeStart }; - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) - { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; + if (((edgeStart.x < rayOrigin.x) && (edgeEnd.x < rayOrigin.x)) || (edgeStart.y < rayOrigin.y) || (edgeEnd.y > rayOrigin.y)) + continue; + + // calculate distance (of intersection of edge) + const float d{ crossProduct((edgeStart - rayOrigin), edgeVector) / crossProduct(rayVector, edgeVector) }; - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) + if (d < distance) + { + distance = d; + if (edgeStart.x > edgeEnd.x) + candidateIndex = edgeStartIndex; + else { - aPointIsInside = true; - break; + candidateIndex = edgeEndIndex; + isEndIndex = true; } + pointOfIntersection = { rayOrigin.x + d, rayOrigin.y }; } - if (!aPointIsInside) - ear.push_back(indices[i]); } - } - - - - std::vector::iterator convexNextIt{ std::find(convex.begin(), convex.end(), indices[next]) }; - if (convexNextIt != convex.end()) - { - // if convex, re-test for ear only (must still be convex) - if (std::find(ear.begin(), ear.end(), indices[next]) == ear.end()) + const std::size_t candidateVertexNumber{ vertexNumbers[candidateIndex] }; + std::vector insideTriangle; + for (auto& r : reflex) { - std::size_t i{ next }; + if ((candidateIndex == r) || (vertexNumbers[r] >= vertexNumbersSize)) + continue; - const std::size_t p{ prev }; - const std::size_t n{ (i < (indices.size() - 1u)) ? (i + 1u) : 0u }; + if (pointIsInsideTriangle({ m_vertices[candidateVertexNumber].position, rayOrigin, pointOfIntersection }, m_vertices[vertexNumbers[r]].position)) + insideTriangle.push_back(r); + } - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) + if (insideTriangle.empty()) + cutPolygonVertexNumber = vertexNumbers[candidateIndex]; + else + { + // choose the closest point to the ray origin within the triangle formed by the ray to intersection and the candidate vertex + float distanceSquared{ maxWidth * maxWidth }; + for (auto& inside : insideTriangle) { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; - - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) + const float thisLengthSquared{ lengthSquared(m_vertices[vertexNumbers[inside]].position - rayOrigin) }; + if (thisLengthSquared < distanceSquared) { - aPointIsInside = true; - break; + distanceSquared = thisLengthSquared; + cutPolygonVertexNumber = vertexNumbers[inside]; + isEndIndex = false; } } - if (!aPointIsInside) - ear.push_back(indices[i]); } + + + + // automatically insert vertices for the cut + const std::size_t holeIndexOffsetCut{ cutHoleHoleIndex - holeStart }; + // prepare vertices to insert around the cut + std::vector holeInsertVertices(holeLength + 2u); + holeInsertVertices[0u] = cutPolygonVertexNumber; + for (std::size_t i{ 0u }; i <= holeLength; ++i) + holeInsertVertices[i + 1u] = holeVertexNumbers[holeStart + ((holeIndexOffsetCut + i) % holeLength)]; + // then add them around the cut + if (isEndIndex) + { + vertexNumbers.insert(std::find(vertexNumbers.begin(), vertexNumbers.end(), cutPolygonVertexNumber), holeInsertVertices.begin(), holeInsertVertices.end()); + } + else + { + std::vector::reverse_iterator vnRIt{ std::find(vertexNumbers.rbegin(), vertexNumbers.rend(), cutPolygonVertexNumber) }; + std::vector::iterator vnIt{ (vnRIt + 1u).base() }; + //vertexNumbers.insert(std::find(vertexNumbers.rbegin(), vertexNumbers.rend(), cutPolygonVertexNumber).base() + 1u, holeInsertVertices.begin(), holeInsertVertices.end()); + vertexNumbers.insert(vnIt, holeInsertVertices.begin(), holeInsertVertices.end()); + } + + // indices for each of the vertex numbers (allowing re-using of vertices - needed for cutting polygon) + vertexNumbersSize = vertexNumbers.size(); + indices.resize(vertexNumbersSize); + indicesSize = indices.size(); + for (std::size_t i{ 0u }; i < indicesSize; ++i) + indices[i] = i; + + + + //clear lists to allow re-analysis of entire new arrangement + reflex.clear(); + convex.clear(); + ear.clear(); + + // re-analyse points + analysePoints(); } + } + + + + // avoid movement in memory when resizing + m_triangles.clear(); + m_triangles.reserve(m_vertices.size() - 2u); - std::vector::iterator reflexPrevIt{ std::find(reflex.begin(), reflex.end(), indices[prev]) }; - if (reflexPrevIt != reflex.end()) + // process + while (indices.size() > 3u) + { + if (ear.empty()) { - // if reflex, re-test - std::size_t i{ prev }; + if (doThrowExceptions) + throw Exception("Polygon - ERROR: 0001"); + else + return; + } + + + std::size_t currentPoint{ ear.front() }; + std::vector::iterator currentIt{ std::find(indices.begin(), indices.end(), currentPoint) }; + std::size_t current{ static_cast(std::distance(indices.begin(), currentIt)) }; + std::size_t prev{ (current > 0u) ? (current - 1u) : (indices.size() - 1u) }; + std::size_t next{ (current < (indices.size() - 1u)) ? (current + 1u) : 0u }; + + TriangleIndices triangle{ vertexNumbers[indices[prev]], vertexNumbers[indices[current]], vertexNumbers[indices[next]] }; + m_triangles.push_back(triangle); + + retest(prev, ((prev > 0u) ? (prev - 1u) : (indices.size() - 1u)), next, current); + retest(next, prev, ((next < (indices.size() - 1u)) ? (next + 1u) : 0u), current); + + // remove current (the one we clipped) + convex.erase(std::find(convex.begin(), convex.end(), indices[current])); + ear.erase(std::find(ear.begin(), ear.end(), indices[current])); + indices.erase(currentIt); + + if (m_triangles.size() == m_triangleLimit) + break; + } + + // 3 vertices remaining; add final triangle + if (m_triangles.size() < m_triangleLimit) + { + TriangleIndices triangle{ vertexNumbers[indices[0u]], vertexNumbers[indices[1u]], vertexNumbers[indices[2u]] }; + m_triangles.push_back(triangle); + } +} + +void Polygon::priv_triangulateBasicEarClip() +{ + // ear clipping method + // polygon points must be anti-clockwise + // number of triangles will always be (number of points - 2) + + // avoid movement in memory when resizing + m_triangles.clear(); + m_triangles.reserve(m_vertices.size() - 2u); - const std::size_t p{ (i > 0u) ? (i - 1u) : (indices.size() - 1u) }; - const std::size_t n{ next }; + // indices for each of the vertices/points + std::vector indices(m_vertices.size()); + const size_t indicesSize{ indices.size() }; + for (std::size_t i{ 0u }; i < indicesSize; ++i) + indices[i] = i; - const sf::Vector2f pLine{ m_vertices[indices[i]].position - m_vertices[indices[p]].position }; - const sf::Vector2f nLine{ m_vertices[indices[n]].position - m_vertices[indices[i]].position }; + // points lists (to keep track of their state) + std::vector reflex; + std::vector convex; + std::vector ear; + reflex.reserve(m_vertices.size() - 3u); // impossible for vertices to be reflex without enough convex (need at least 3 convex to make a polygon) + convex.reserve(m_vertices.size()); + ear.reserve(m_vertices.size() - 2u); // with one ear per vertex, the final ear requires 3 vertices - if (isSecondVectorAntiClockwiseOfFirstVector(pLine, nLine)) + std::function isEar = + [&](const std::size_t i, const std::size_t p, const std::size_t n, const std::size_t current) + { + bool aPointIsInside{ false }; + for (std::size_t other{ 0u }; other < indices.size(); ++other) { - reflex.erase(reflexPrevIt); + if ((other == i) || (other == p) || (other == n) || (other == current)) + continue; - convex.push_back(indices[i]); - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) + if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; - - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) - { - aPointIsInside = true; - break; - } + aPointIsInside = true; + break; } - if (!aPointIsInside) - ear.push_back(indices[i]); } - } + return !aPointIsInside; + }; - std::vector::iterator reflexNextIt{ std::find(reflex.begin(), reflex.end(), indices[next]) }; - if (reflexNextIt != reflex.end()) + std::function isEarAnalysis = + [&](const std::size_t i, const std::size_t p, const std::size_t n) { - // if reflex, re-test - std::size_t i{ next }; - - const std::size_t p{ prev }; - const std::size_t n{ (i < (indices.size() - 1u)) ? (i + 1u) : 0u }; + return isEar(i, p, n, i); + }; - const sf::Vector2f pLine{ m_vertices[indices[i]].position - m_vertices[indices[p]].position }; - const sf::Vector2f nLine{ m_vertices[indices[n]].position - m_vertices[indices[i]].position }; - - if (isSecondVectorAntiClockwiseOfFirstVector(pLine, nLine)) + std::function retest = + [&](const std::size_t i, const std::size_t p, const std::size_t n, const std::size_t current) + { + std::vector::iterator reflexIt{ std::find(reflex.begin(), reflex.end(), indices[i]) }; + if (reflexIt != reflex.end()) { - reflex.erase(reflexNextIt); + // if reflex, re-test + const sf::Vector2f pLine{ m_vertices[indices[i]].position - m_vertices[indices[p]].position }; + const sf::Vector2f nLine{ m_vertices[indices[n]].position - m_vertices[indices[i]].position }; - convex.push_back(indices[i]); - bool aPointIsInside{ false }; - for (std::size_t other{ 0u }; other < indices.size(); ++other) + if (m_reverseDirection != isSecondVectorAntiClockwiseOfFirstVector(pLine, nLine)) { - if ((other == i) || (other == p) || (other == n) || (other == current)) - continue; - - if (pointIsInsideTriangle({ m_vertices[indices[p]].position, m_vertices[indices[i]].position, m_vertices[indices[n]].position }, m_vertices[indices[other]].position)) - { - aPointIsInside = true; - break; - } + reflex.erase(reflexIt); + convex.push_back(indices[i]); } - if (!aPointIsInside) + } + + std::vector::iterator convexIt{ std::find(convex.begin(), convex.end(), indices[i]) }; + if (convexIt != convex.end()) + { + // if convex, re-test for ear only (must still be convex) + const bool isNowEar{ isEar(i, p, n, current) }; + const std::vector::iterator it{ std::find(ear.begin(), ear.end(), indices[i]) }; + if (isNowEar && (it == ear.end())) ear.push_back(indices[i]); + else if (!isNowEar && (it != ear.end())) + ear.erase(it); } + }; + + // analyse points + for (std::size_t i{ 0u }; i < indicesSize; ++i) + { + const std::size_t prev{ (i > 0u) ? (i - 1u) : (indicesSize - 1u) }; + const std::size_t next{ (i < (indicesSize - 1u)) ? (i + 1u) : 0u }; + + const sf::Vector2f prevLine{ m_vertices[indices[i]].position - m_vertices[indices[prev]].position }; + const sf::Vector2f nextLine{ m_vertices[indices[next]].position - m_vertices[indices[i]].position }; + + if (m_reverseDirection != !isSecondVectorAntiClockwiseOfFirstVector(prevLine, nextLine)) + reflex.push_back(indices[i]); + else + { + convex.push_back(i); + if (isEarAnalysis(i, prev, next)) + ear.push_back(indices[i]); } + } + + // process + while (indices.size() > 3u) + { + std::size_t currentPoint{ ear.front() }; + std::vector::iterator currentIt{ std::find(indices.begin(), indices.end(), currentPoint) }; + std::size_t current{ static_cast(std::distance(indices.begin(), currentIt)) }; + std::size_t prev{ (current > 0u) ? (current - 1u) : (indices.size() - 1u) }; + std::size_t next{ (current < (indices.size() - 1u)) ? (current + 1u) : 0u }; + + TriangleIndices triangle{ indices[prev], indices[current], indices[next] }; + m_triangles.push_back(triangle); + retest(prev, ((prev > 0u) ? (prev - 1u) : (indices.size() - 1u)), next, current); + retest(next, prev, ((next < (indices.size() - 1u)) ? (next + 1u) : 0u), current); + + // remove current (the one we clipped) convex.erase(std::find(convex.begin(), convex.end(), indices[current])); - if (std::find(ear.begin(), ear.end(), indices[current]) != ear.end()) - ear.erase(std::find(ear.begin(), ear.end(), indices[current])); + ear.erase(std::find(ear.begin(), ear.end(), indices[current])); indices.erase(currentIt); - ///* - if (m_triangles.size() == stopAfterThisNumberOfTrianglesHaveBeenCreated) + if (m_triangles.size() == m_triangleLimit) break; - //*/ } - if (m_triangles.size() < stopAfterThisNumberOfTrianglesHaveBeenCreated) + if (m_triangles.size() < m_triangleLimit) { TriangleIndices triangle{ indices[0u], indices[1u], indices[2u] }; m_triangles.push_back(triangle); @@ -493,15 +1047,55 @@ bool Polygon::priv_isValidVertexIndex(const std::size_t vertexIndex) const return vertexIndex < m_vertices.size(); } +bool Polygon::priv_isValidHoleIndex(const std::size_t holeIndex) const +{ + return holeIndex < m_holeStartIndices.size(); +} + bool Polygon::priv_testVertexIndex(const std::size_t vertexIndex, const std::string& exceptionMessage) const { if (!priv_isValidVertexIndex(vertexIndex)) { - if (m_throwExceptions) + if (doThrowExceptions) throw Exception(exceptionPrefix + exceptionMessage + " Vertex index (" + std::to_string(vertexIndex) + ") out of range"); return false; } return true; } +bool Polygon::priv_testHoleIndex(std::size_t holeIndex, const std::string& exceptionMessage) const +{ + if (!priv_isValidHoleIndex(holeIndex)) + { + if (doThrowExceptions) + throw Exception(exceptionPrefix + exceptionMessage + " Hole index (" + std::to_string(holeIndex) + ") out of range"); + return false; + } + return true; +} + +void Polygon::priv_buildWireframe() +{ + if (!m_showWireframe) + { + m_wireframeVertices.clear(); + return; + } + + m_wireframeVertices.resize(m_triangles.size() * 6u); + + for (std::size_t t{ 0u }; t < m_triangles.size(); ++t) + { + const std::size_t baseTriangleIndex{ t * 6u }; + for (std::size_t l{ 0u }; l < 3u; ++l) + { + const std::size_t baseLineIndex{ l * 2u }; + m_wireframeVertices[baseTriangleIndex + baseLineIndex + 0u].position = m_vertices[m_triangles[t][l]].position; + m_wireframeVertices[baseTriangleIndex + baseLineIndex + 1u].position = m_vertices[m_triangles[t][(l < 2u) ? l + 1u : 0u]].position; + m_wireframeVertices[baseTriangleIndex + baseLineIndex + 0u].color = m_wireframeColor; + m_wireframeVertices[baseTriangleIndex + baseLineIndex + 1u].color = m_wireframeColor; + } + } +} + } // namespace selbaward diff --git a/src/SelbaWard/Polygon.hpp b/src/SelbaWard/Polygon.hpp index 512b82f..e01719b 100644 --- a/src/SelbaWard/Polygon.hpp +++ b/src/SelbaWard/Polygon.hpp @@ -5,7 +5,7 @@ // // Polygon // -// Copyright(c) 2022-2023 M.J.Silk +// Copyright(c) 2022-2025 M.J.Silk // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -39,13 +39,14 @@ namespace selbaward { -// SW Polygon v1.1 +// SW Polygon v1.4.0 class Polygon : public sf::Drawable, public sf::Transformable { public: enum class TriangulationMethod { BasicEarClip, + EarClip, }; enum class MeshRefinementMethod { @@ -53,8 +54,14 @@ class Polygon : public sf::Drawable, public sf::Transformable }; Polygon(); + Polygon(std::initializer_list list); // pass vertices' positions (sf::Vector2f) to the constructor (sets size automatically) + Polygon(const Polygon& polygon); + Polygon& operator=(const Polygon& polygon); + void update(); + sf::Vertex& operator[] (std::size_t index); // direct access to the polygon's vertices (sf::Vertex) using the [] operator. no checks are performed. using with an invalid index results in undefined behaviour + void setColor(sf::Color color); sf::Color getColor(); @@ -63,6 +70,9 @@ class Polygon : public sf::Drawable, public sf::Transformable void setMeshRefinementMethod(MeshRefinementMethod meshRefinementMethod); MeshRefinementMethod getMeshRefinementMethod() const; + void setReverseDirection(bool reverseDirection); + bool getReverseDirection() const; + void reserveVertices(std::size_t numberOfVertices); void setNumberOfVertices(std::size_t numberOfVertices); @@ -71,10 +81,55 @@ class Polygon : public sf::Drawable, public sf::Transformable void setVertexPosition(std::size_t index, sf::Vector2f position); sf::Vector2f getVertexPosition(std::size_t index) const; + void setVertexColor(std::size_t index, sf::Color color); + sf::Color getVertexColor(std::size_t index) const; + + void setVertexTexCoords(std::size_t index, sf::Vector2f texCoords); + sf::Vector2f getVertexTexCoords(std::size_t index) const; + + void setTexture(const sf::Texture& texture); // activate texture (ignored for wireframe) + void setTexture(); // de-activate/reset ("un-set") texture + + void setTriangleLimit(std::size_t triangleLimit); + std::size_t getTriangleLimit() const; + + void setShowWireframe(bool showWireframe); + bool getShowWireframe() const; + + void setWireframeColor(sf::Color wireframeColor); + sf::Color getWireframeColor() const; + + float getPerimeter() const; + float getArea() const; + + bool isPointInside(sf::Vector2f point) const; + + sf::FloatRect getLocalBounds() const; + sf::FloatRect getGlobalBounds() const; + + sf::Vector2f getCentroid() const; // ignores holes - gives decent representation (averaged points of outer) + sf::Vector2f getCenterOfMass() const; // uses each point of each triangle, weighted by triangle area - represents actual "centre of mass" + void reverseVertices(); void importVertexPositions(const std::vector& position); + std::vector exportVertexPositions() const; + std::vector exportVertexPositionsOuterOnly() const; + std::vector exportVertexPositionsHoleOnly(std::size_t holeIndex) const; std::vector exportTriangulatedPositions() const; + std::vector exportWireframePositions() const; + + // holes must not overlap and must be specified in opposite direction to outer polygon + void addHoleStartIndex(std::size_t index); + void clearHoleStartIndices(); + void setHoleStartIndices(const std::vector& indices); + void setNumberOfHoles(std::size_t numberOfHoles); + void setHoleStartIndex(std::size_t holeIndex, std::size_t holeStartIndex); + std::size_t getNumberOfHoles() const; + std::size_t getHoleStartIndex(std::size_t holeIndex) const; // hole index indentifies the hole. returned value is the vertex index of the start of that hole. "number of vertices" is returned if there are no holes or hole does not exist. + + + @@ -82,24 +137,42 @@ class Polygon : public sf::Drawable, public sf::Transformable private: using TriangleIndices = std::array; + const sf::Texture* m_texture; + std::vector m_vertices; std::vector m_triangles; std::vector m_outputVertices; + std::vector m_holeStartIndices; sf::Color m_color; + bool m_showWireframe; + std::vector m_wireframeVertices; + sf::Color m_wireframeColor; + TriangulationMethod m_triangulationMethod; MeshRefinementMethod m_meshRefinementMethod; - const bool m_throwExceptions; + std::size_t m_triangleLimit; + + bool m_reverseDirection; - virtual void draw(sf::RenderTarget&, const sf::RenderStates&) const; + void draw(sf::RenderTarget&, sf::RenderStates) const override final; void priv_update(); void priv_updateOutputVertices(); void priv_triangulate(); + void priv_triangulateEarClip(); void priv_triangulateBasicEarClip(); bool priv_isValidVertexIndex(std::size_t vertexIndex) const; + bool priv_isValidHoleIndex(std::size_t holeIndex) const; bool priv_testVertexIndex(std::size_t vertexIndex, const std::string& exceptionMessage) const; + bool priv_testHoleIndex(std::size_t holeIndex, const std::string& exceptionMessage) const; + void priv_buildWireframe(); }; +inline sf::Vertex& Polygon::operator[] (const std::size_t index) +{ + return m_vertices[index]; +} + } // namespace selbaward #endif // SELBAWARD_POLYGON_HPP