Simplify sf::Sprite implementation and reduce branches

This commit is contained in:
vittorioromeo 2024-06-12 23:23:06 +02:00 committed by Vittorio Romeo
parent 2f54312481
commit 51efe50ec4
3 changed files with 44 additions and 51 deletions

View File

@ -211,22 +211,16 @@ private:
void draw(RenderTarget& target, RenderStates states) const override; void draw(RenderTarget& target, RenderStates states) const override;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Update the vertices' positions /// \brief Update the vertices' positions and texture coordinates
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void updatePositions(); void updateVertices();
////////////////////////////////////////////////////////////
/// \brief Update the vertices' texture coordinates
///
////////////////////////////////////////////////////////////
void updateTexCoords();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::array<Vertex, 4> m_vertices; //!< Vertices defining the sprite's geometry std::array<Vertex, 4> m_vertices; //!< Vertices defining the sprite's geometry
const Texture* m_texture{}; //!< Texture of the sprite const Texture* m_texture; //!< Texture of the sprite
IntRect m_textureRect; //!< Rectangle defining the area of the source texture to display IntRect m_textureRect; //!< Rectangle defining the area of the source texture to display
}; };
@ -271,9 +265,9 @@ private:
/// ///
/// // Create a sprite /// // Create a sprite
/// sf::Sprite sprite(texture); /// sf::Sprite sprite(texture);
/// sprite.setTextureRect(sf::IntRect({10, 10}, {50, 30})); /// sprite.setTextureRect({{10, 10}, {50, 30}});
/// sprite.setColor(sf::Color(255, 255, 255, 200)); /// sprite.setColor({255, 255, 255, 200});
/// sprite.setPosition({100, 25}); /// sprite.setPosition({100.f, 25.f});
/// ///
/// // Draw it /// // Draw it
/// window.draw(sprite); /// window.draw(sprite);

View File

@ -30,25 +30,20 @@
#include <SFML/Graphics/Texture.hpp> #include <SFML/Graphics/Texture.hpp>
#include <cmath> #include <cmath>
#include <cstdlib>
namespace sf namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture) Sprite::Sprite(const Texture& texture) : Sprite(texture, IntRect({0, 0}, Vector2i(texture.getSize())))
{ {
setTexture(texture, true);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture, const IntRect& rectangle) Sprite::Sprite(const Texture& texture, const IntRect& rectangle) : m_texture(&texture), m_textureRect(rectangle)
{ {
// Compute the texture area updateVertices();
setTextureRect(rectangle);
// Assign texture
setTexture(texture, false);
} }
@ -57,9 +52,7 @@ void Sprite::setTexture(const Texture& texture, bool resetRect)
{ {
// Recompute the texture area if requested // Recompute the texture area if requested
if (resetRect) if (resetRect)
{
setTextureRect(IntRect({0, 0}, Vector2i(texture.getSize()))); setTextureRect(IntRect({0, 0}, Vector2i(texture.getSize())));
}
// Assign the new texture // Assign the new texture
m_texture = &texture; m_texture = &texture;
@ -72,8 +65,7 @@ void Sprite::setTextureRect(const IntRect& rectangle)
if (rectangle != m_textureRect) if (rectangle != m_textureRect)
{ {
m_textureRect = rectangle; m_textureRect = rectangle;
updatePositions(); updateVertices();
updateTexCoords();
} }
} }
@ -81,8 +73,7 @@ void Sprite::setTextureRect(const IntRect& rectangle)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sprite::setColor(const Color& color) void Sprite::setColor(const Color& color)
{ {
// Update the vertices' color for (Vertex& vertex : m_vertices)
for (auto& vertex : m_vertices)
vertex.color = color; vertex.color = color;
} }
@ -111,10 +102,8 @@ const Color& Sprite::getColor() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
FloatRect Sprite::getLocalBounds() const FloatRect Sprite::getLocalBounds() const
{ {
const auto width = static_cast<float>(std::abs(m_textureRect.width)); // Last vertex posiion is equal to texture rect size absolute value
const auto height = static_cast<float>(std::abs(m_textureRect.height)); return {{0.f, 0.f}, m_vertices[3].position};
return {{0.f, 0.f}, {width, height}};
} }
@ -131,36 +120,36 @@ void Sprite::draw(RenderTarget& target, RenderStates states) const
states.transform *= getTransform(); states.transform *= getTransform();
states.texture = m_texture; states.texture = m_texture;
states.coordinateType = CoordinateType::Pixels; states.coordinateType = CoordinateType::Pixels;
target.draw(m_vertices.data(), m_vertices.size(), PrimitiveType::TriangleStrip, states); target.draw(m_vertices.data(), m_vertices.size(), PrimitiveType::TriangleStrip, states);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Sprite::updatePositions() void Sprite::updateVertices()
{ {
const FloatRect bounds = getLocalBounds(); const auto left = static_cast<float>(m_textureRect.left);
const auto top = static_cast<float>(m_textureRect.top);
const auto width = static_cast<float>(m_textureRect.width);
const auto height = static_cast<float>(m_textureRect.height);
const auto right = float{left + width};
const auto bottom = float{top + height};
m_vertices[0].position = Vector2f(0, 0); // Absolute value is used to support negative texture rect sizes
m_vertices[1].position = Vector2f(0, bounds.height); const auto absWidth = float{std::abs(width)};
m_vertices[2].position = Vector2f(bounds.width, 0); const auto absHeight = float{std::abs(height)};
m_vertices[3].position = Vector2f(bounds.width, bounds.height);
}
// Update positions
m_vertices[0].position = {0.f, 0.f};
m_vertices[1].position = {0.f, absHeight};
m_vertices[2].position = {absWidth, 0.f};
m_vertices[3].position = {absWidth, absHeight};
//////////////////////////////////////////////////////////// // Update texture coordinates
void Sprite::updateTexCoords() m_vertices[0].texCoords = {left, top};
{ m_vertices[1].texCoords = {left, bottom};
const FloatRect convertedTextureRect(m_textureRect); m_vertices[2].texCoords = {right, top};
m_vertices[3].texCoords = {right, bottom};
const float left = convertedTextureRect.left;
const float right = left + convertedTextureRect.width;
const float top = convertedTextureRect.top;
const float bottom = top + convertedTextureRect.height;
m_vertices[0].texCoords = Vector2f(left, top);
m_vertices[1].texCoords = Vector2f(left, bottom);
m_vertices[2].texCoords = Vector2f(right, top);
m_vertices[3].texCoords = Vector2f(right, bottom);
} }
} // namespace sf } // namespace sf

View File

@ -42,6 +42,16 @@ TEST_CASE("[Graphics] sf::Sprite", runDisplayTests())
CHECK(sprite.getLocalBounds() == sf::FloatRect({0, 0}, {40, 60})); CHECK(sprite.getLocalBounds() == sf::FloatRect({0, 0}, {40, 60}));
CHECK(sprite.getGlobalBounds() == sf::FloatRect({0, 0}, {40, 60})); CHECK(sprite.getGlobalBounds() == sf::FloatRect({0, 0}, {40, 60}));
} }
SECTION("Negative-size texture rectangle")
{
const sf::Sprite sprite(texture, {{0, 0}, {-40, -60}});
CHECK(&sprite.getTexture() == &texture);
CHECK(sprite.getTextureRect() == sf::IntRect({0, 0}, {-40, -60}));
CHECK(sprite.getColor() == sf::Color::White);
CHECK(sprite.getLocalBounds() == sf::FloatRect({0, 0}, {40, 60}));
CHECK(sprite.getGlobalBounds() == sf::FloatRect({0, 0}, {40, 60}));
}
} }
SECTION("Set/get texture") SECTION("Set/get texture")