diff --git a/include/SFML/Graphics/Matrix3.hpp b/include/SFML/Graphics/Matrix3.hpp index eeea1b0b5..2b8db6ea2 100644 --- a/include/SFML/Graphics/Matrix3.hpp +++ b/include/SFML/Graphics/Matrix3.hpp @@ -30,6 +30,7 @@ //////////////////////////////////////////////////////////// #include #include +#include #include @@ -68,6 +69,14 @@ public : //////////////////////////////////////////////////////////// void SetFromTransformations(const Vector2f& Center, const Vector2f& Translation, float Rotation, const Vector2f& Scale); + //////////////////////////////////////////////////////////// + /// Build a matrix from a projection + /// + /// \param Rectangle : Rectangle defining the region to project + /// + //////////////////////////////////////////////////////////// + void SetFromProjection(const FloatRect& Rectangle); + //////////////////////////////////////////////////////////// /// Transform a point by the matrix /// diff --git a/include/SFML/Graphics/Matrix3.inl b/include/SFML/Graphics/Matrix3.inl index 73c78b707..4f1734bab 100644 --- a/include/SFML/Graphics/Matrix3.inl +++ b/include/SFML/Graphics/Matrix3.inl @@ -54,6 +54,7 @@ inline Matrix3::Matrix3(float a00, float a01, float a02, //////////////////////////////////////////////////////////// inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector2f& Translation, float Rotation, const Vector2f& Scale) { + // Combine the transformations float Angle = Rotation * 3.141592654f / 180.f; float Cos = static_cast(cos(Angle)); float Sin = static_cast(sin(Angle)); @@ -64,6 +65,7 @@ inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector float Tx = -Center.x * SxCos - Center.y * SySin + Translation.x; float Ty = Center.x * SxSin - Center.y * SyCos + Translation.y; + // Rebuild the matrix myData[0] = SxCos; myData[4] = SySin; myData[8] = 0.f; myData[12] = Tx; myData[1] = -SxSin; myData[5] = SyCos; myData[9] = 0.f; myData[13] = Ty; myData[2] = 0.f; myData[6] = 0.f; myData[10] = 1.f; myData[14] = 0.f; @@ -71,6 +73,25 @@ inline void Matrix3::SetFromTransformations(const Vector2f& Center, const Vector } +//////////////////////////////////////////////////////////// +/// Build a matrix from a projection +//////////////////////////////////////////////////////////// +inline void Matrix3::SetFromProjection(const FloatRect& Rectangle) +{ + // Projection components + float A = 2.f / Rectangle.GetSize().x; + float B = -2.f / Rectangle.GetSize().y; + float C = -(Rectangle.Left + Rectangle.Right) / Rectangle.GetSize().x; + float D = (Rectangle.Bottom + Rectangle.Top) / Rectangle.GetSize().y; + + // Rebuild the projection matrix + myData[0] = A; myData[4] = 0.f; myData[8] = 0.f; myData[12] = C; + myData[1] = 0.f; myData[5] = B; myData[9] = 0.f; myData[13] = D; + myData[2] = 0.f; myData[6] = 0.f; myData[10] = 1.f; myData[14] = 0.f; + myData[3] = 0.f; myData[7] = 0.f; myData[11] = 0.f; myData[15] = 1.f; +} + + //////////////////////////////////////////////////////////// /// Transform a point by the matrix //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Rect.hpp b/include/SFML/Graphics/Rect.hpp index 5decd3c56..e956d6acb 100644 --- a/include/SFML/Graphics/Rect.hpp +++ b/include/SFML/Graphics/Rect.hpp @@ -28,6 +28,7 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// +#include #include @@ -60,20 +61,20 @@ public : Rect(T LeftCoord, T TopCoord, T RightCoord, T BottomCoord); //////////////////////////////////////////////////////////// - /// Get the width of the rectangle + /// Get the size of the rectangle /// - /// \return Width of rectangle + /// \return Size of rectangle /// //////////////////////////////////////////////////////////// - T GetWidth() const; + Vector2 GetSize() const; //////////////////////////////////////////////////////////// - /// Get the height of the rectangle + /// Get the center of the rectangle /// - /// \return Height of rectangle + /// \return Center of rectangle /// //////////////////////////////////////////////////////////// - T GetHeight() const; + Vector2 GetCenter() const; //////////////////////////////////////////////////////////// /// Move the whole rectangle by the given offset @@ -84,6 +85,14 @@ public : //////////////////////////////////////////////////////////// void Offset(T OffsetX, T OffsetY); + //////////////////////////////////////////////////////////// + /// Move the whole rectangle by the given offset + /// + /// \param Off : Offset to apply to the current position + /// + //////////////////////////////////////////////////////////// + void Offset(const Vector2& Off); + //////////////////////////////////////////////////////////// /// Check if a point is inside the rectangle's area /// @@ -95,16 +104,37 @@ public : //////////////////////////////////////////////////////////// bool Contains(T X, T Y) const; + //////////////////////////////////////////////////////////// + /// Check if a point is inside the rectangle's area + /// + /// \param Point : Point to test + /// + /// \return True if the point is inside + /// + //////////////////////////////////////////////////////////// + bool Contains(const Vector2& Point) const; + //////////////////////////////////////////////////////////// /// Check intersection between two rectangles /// - /// \param Rectangle : Rectangle to test - /// \param OverlappingRect : Rectangle to be filled with overlapping rect (NULL by default) + /// \param Rectangle : Rectangle to test /// /// \return True if rectangles overlap /// //////////////////////////////////////////////////////////// - bool Intersects(const Rect& Rectangle, Rect* OverlappingRect = NULL) const; + bool Intersects(const Rect& Rectangle) const; + + //////////////////////////////////////////////////////////// + /// Check intersection between two rectangles and return the + /// resulting rectangle + /// + /// \param Rectangle : Rectangle to test + /// \param OverlappingRect : Rectangle to be filled with the overlapping rect + /// + /// \return True if rectangles overlap + /// + //////////////////////////////////////////////////////////// + bool Intersects(const Rect& Rectangle, Rect& OverlappingRect) const; //////////////////////////////////////////////////////////// // Member data diff --git a/include/SFML/Graphics/Rect.inl b/include/SFML/Graphics/Rect.inl index 6c5962ddd..e22ed5712 100644 --- a/include/SFML/Graphics/Rect.inl +++ b/include/SFML/Graphics/Rect.inl @@ -52,22 +52,22 @@ Bottom(BottomCoord) //////////////////////////////////////////////////////////// -/// Get the width of the rectangle +/// Get the size of the rectangle //////////////////////////////////////////////////////////// template -T Rect::GetWidth() const +Vector2 Rect::GetSize() const { - return Right - Left; + return Vector2(Right - Left, Bottom - Top); } //////////////////////////////////////////////////////////// -/// Get the height of the rectangle +/// Get the center of the rectangle //////////////////////////////////////////////////////////// template -T Rect::GetHeight() const +Vector2 Rect::GetCenter() const { - return Bottom - Top; + return Vector2((Left + Right) / 2, (Top + Bottom) / 2); } @@ -84,6 +84,16 @@ void Rect::Offset(T OffsetX, T OffsetY) } +//////////////////////////////////////////////////////////// +/// Move the whole rectangle by the given offset +//////////////////////////////////////////////////////////// +template +void Rect::Offset(const Vector2& Off) +{ + Offset(Off.x, Off.y); +} + + //////////////////////////////////////////////////////////// /// Check if a point is inside the rectangle's area //////////////////////////////////////////////////////////// @@ -94,29 +104,55 @@ bool Rect::Contains(T X, T Y) const } +//////////////////////////////////////////////////////////// +/// Check if a point is inside the rectangle's area +//////////////////////////////////////////////////////////// +template +bool Rect::Contains(const Vector2& Point) const +{ + return Contains(Point.x, Point.y); +} + + //////////////////////////////////////////////////////////// /// Check intersection between two rectangles //////////////////////////////////////////////////////////// template -bool Rect::Intersects(const Rect& Rectangle, Rect* OverlappingRect) const +bool Rect::Intersects(const Rect& Rectangle) const { // Compute overlapping rect - Rect Overlapping(std::max(Left, Rectangle.Left), - std::max(Top, Rectangle.Top), - std::min(Right, Rectangle.Right), - std::min(Bottom, Rectangle.Bottom)); + Rect Overlapping(std::max(Left, Rectangle.Left), + std::max(Top, Rectangle.Top), + std::min(Right, Rectangle.Right), + std::min(Bottom, Rectangle.Bottom)); + + // If overlapping rect is valid, then there is intersection + return (Overlapping.Left < Overlapping.Right) && (Overlapping.Top < Overlapping.Bottom); +} + + +//////////////////////////////////////////////////////////// +/// Check intersection between two rectangles and return the +/// resulting rectangle +//////////////////////////////////////////////////////////// +template +bool Rect::Intersects(const Rect& Rectangle, Rect& OverlappingRect) const +{ + // Compute overlapping rect + Rect Overlapping(std::max(Left, Rectangle.Left), + std::max(Top, Rectangle.Top), + std::min(Right, Rectangle.Right), + std::min(Bottom, Rectangle.Bottom)); // If overlapping rect is valid, then there is intersection if ((Overlapping.Left < Overlapping.Right) && (Overlapping.Top < Overlapping.Bottom)) { - if (OverlappingRect) - *OverlappingRect = Overlapping; + OverlappingRect = Overlapping; return true; } else { - if (OverlappingRect) - *OverlappingRect = Rect(0, 0, 0, 0); + OverlappingRect = Rect(0, 0, 0, 0); return false; } } diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp index d5e401a33..f0ae84af6 100644 --- a/include/SFML/Graphics/View.hpp +++ b/include/SFML/Graphics/View.hpp @@ -36,10 +36,8 @@ namespace sf { -class RenderTarget; - //////////////////////////////////////////////////////////// -/// This class defines a view (position, size, etc.) ; +/// This class defines a view (position, size, etc.); /// you can consider it as a 2D camera //////////////////////////////////////////////////////////// class SFML_API View @@ -55,13 +53,30 @@ public : explicit View(const FloatRect& ViewRect = FloatRect(0, 0, 1000, 1000)); //////////////////////////////////////////////////////////// - /// Construct the view from its center and half-size + /// Construct the view from its center and size /// /// \param Center : Center of the view - /// \param HalfSize : Half-size of the view (from center to corner) + /// \param HalfSize : Size of the view /// //////////////////////////////////////////////////////////// - View(const sf::Vector2f& Center, const sf::Vector2f& HalfSize); + View(const Vector2f& Center, const Vector2f& Size); + + //////////////////////////////////////////////////////////// + /// Set the rectangle defining the view by its center and size + /// + /// \param Center : Center of the view rectangle + /// \param Size : Size of the view rectangle + /// + //////////////////////////////////////////////////////////// + void SetRect(const Vector2f& Center, const Vector2f& Size); + + //////////////////////////////////////////////////////////// + /// Set the rectangle defining the view + /// + /// \param Rect : Rectangle defining the center and size of the view + /// + //////////////////////////////////////////////////////////// + void SetRect(const FloatRect& Rect); //////////////////////////////////////////////////////////// /// Change the center of the view (take 2 values) @@ -78,32 +93,33 @@ public : /// \param Center : New center /// //////////////////////////////////////////////////////////// - void SetCenter(const sf::Vector2f& Center); + void SetCenter(const Vector2f& Center); //////////////////////////////////////////////////////////// - /// Change the half-size of the view (take 2 values) + /// Change the size of the view (take 2 values) /// - /// \param HalfWidth : New half-width - /// \param HalfHeight : New half-height + /// \param Width : New width + /// \param Height : New height /// //////////////////////////////////////////////////////////// - void SetHalfSize(float HalfWidth, float HalfHeight); + void SetSize(float Width, float Height); //////////////////////////////////////////////////////////// - /// Change the half-size of the view (take a vector) + /// Change the size of the view (take a vector) /// /// \param HalfSize : New half-size /// //////////////////////////////////////////////////////////// - void SetHalfSize(const sf::Vector2f& HalfSize); + void SetSize(const Vector2f& Size); //////////////////////////////////////////////////////////// - /// Rebuild the view from a rectangle + /// Get the rectangle defining the view, + /// which is the combined center and size. /// - /// \param ViewRect : Rectangle defining the position and size of the view + /// \return View rectangle /// //////////////////////////////////////////////////////////// - void SetFromRect(const FloatRect& ViewRect); + FloatRect GetRect() const; //////////////////////////////////////////////////////////// /// Get the center of the view @@ -111,23 +127,15 @@ public : /// \return Center of the view /// //////////////////////////////////////////////////////////// - const sf::Vector2f& GetCenter() const; + const Vector2f& GetCenter() const; //////////////////////////////////////////////////////////// - /// Get the half-size of the view + /// Get the size of the view /// - /// \return Half-size of the view + /// \return Size of the view /// //////////////////////////////////////////////////////////// - const sf::Vector2f& GetHalfSize() const; - - //////////////////////////////////////////////////////////// - /// Get the bounding rectangle of the view - /// - /// \return Bounding rectangle of the view - /// - //////////////////////////////////////////////////////////// - const sf::FloatRect& GetRect() const; + const Vector2f& GetSize() const; //////////////////////////////////////////////////////////// /// Move the view (take 2 values) @@ -144,7 +152,7 @@ public : /// \param Offset : Offset to move the view /// //////////////////////////////////////////////////////////// - void Move(const sf::Vector2f& Offset); + void Move(const Vector2f& Offset); //////////////////////////////////////////////////////////// /// Resize the view rectangle to simulate a zoom / unzoom effect @@ -154,32 +162,33 @@ public : //////////////////////////////////////////////////////////// void Zoom(float Factor); -private : - - friend class RenderTarget; - //////////////////////////////////////////////////////////// /// Get the projection matrix of the view /// - /// \return Projection matrix containing the view settings + /// \return Projection matrix /// //////////////////////////////////////////////////////////// const Matrix3& GetMatrix() const; //////////////////////////////////////////////////////////// - /// Recompute the view rectangle and the projection matrix + /// Get the inverse projection matrix of the view + /// + /// \return Inverse projection matrix /// //////////////////////////////////////////////////////////// - void RecomputeMatrix(); + const Matrix3& GetInverseMatrix() const; + +private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - sf::Vector2f myCenter; ///< Center of the view - sf::Vector2f myHalfSize; ///< Half-size of the view - FloatRect myRect; ///< Rectangle defining the bounds of the view - Matrix3 myMatrix; ///< Precomputed projection matrix corresponding to the view - bool myNeedUpdate; ///< Internal state telling if the matrix needs to be updated + sf::Vector2f myCenter; ///< Center of the view + sf::Vector2f mySize; ///< Size of the view + mutable Matrix3 myMatrix; ///< Precomputed projection matrix corresponding to the view + mutable Matrix3 myInverseMatrix; ///< Precomputed inverse projection matrix corresponding to the view + mutable bool myNeedUpdate; ///< Internal state telling if the matrix needs to be updated + mutable bool myNeedInvUpdate; ///< Internal state telling if the matrix needs to be updated }; } // namespace sf diff --git a/samples/pong/Pong.cpp b/samples/pong/Pong.cpp index 6ca169cff..2ed82ccc6 100644 --- a/samples/pong/Pong.cpp +++ b/samples/pong/Pong.cpp @@ -57,9 +57,9 @@ int main() sf::Sprite RightPaddle(RightPaddleImage); sf::Sprite Ball(BallImage); - LeftPaddle.Move(10, (App.GetView().GetRect().GetHeight() - LeftPaddle.GetSize().y) / 2); - RightPaddle.Move(App.GetView().GetRect().GetWidth() - RightPaddle.GetSize().x - 10, (App.GetView().GetRect().GetHeight() - RightPaddle.GetSize().y) / 2); - Ball.Move((App.GetView().GetRect().GetWidth() - Ball.GetSize().x) / 2, (App.GetView().GetRect().GetHeight() - Ball.GetSize().y) / 2); + LeftPaddle.Move(10, (App.GetView().GetSize().y - LeftPaddle.GetSize().y) / 2); + RightPaddle.Move(App.GetView().GetSize().x - RightPaddle.GetSize().x - 10, (App.GetView().GetSize().y - RightPaddle.GetSize().y) / 2); + Ball.Move((App.GetView().GetSize().x - Ball.GetSize().x) / 2, (App.GetView().GetSize().y - Ball.GetSize().y) / 2); // Define the paddles properties sf::Clock AITimer; @@ -97,12 +97,12 @@ int main() // Move the player's paddle if (App.GetInput().IsKeyDown(sf::Key::Up) && (LeftPaddle.GetPosition().y > 5.f)) LeftPaddle.Move(0.f, -LeftPaddleSpeed * App.GetFrameTime()); - if (App.GetInput().IsKeyDown(sf::Key::Down) && (LeftPaddle.GetPosition().y < App.GetView().GetRect().GetHeight() - LeftPaddle.GetSize().y - 5.f)) + if (App.GetInput().IsKeyDown(sf::Key::Down) && (LeftPaddle.GetPosition().y < App.GetView().GetSize().y - LeftPaddle.GetSize().y - 5.f)) LeftPaddle.Move(0.f, LeftPaddleSpeed * App.GetFrameTime()); // Move the computer's paddle if (((RightPaddleSpeed < 0.f) && (RightPaddle.GetPosition().y > 5.f)) || - ((RightPaddleSpeed > 0.f) && (RightPaddle.GetPosition().y < App.GetView().GetRect().GetHeight() - RightPaddle.GetSize().y - 5.f))) + ((RightPaddleSpeed > 0.f) && (RightPaddle.GetPosition().y < App.GetView().GetSize().y - RightPaddle.GetSize().y - 5.f))) { RightPaddle.Move(0.f, RightPaddleSpeed * App.GetFrameTime()); } @@ -127,7 +127,7 @@ int main() IsPlaying = false; End.SetText("You lost !\n(press escape to exit)"); } - if (Ball.GetPosition().x + Ball.GetSize().x > App.GetView().GetRect().GetWidth()) + if (Ball.GetPosition().x + Ball.GetSize().x > App.GetView().GetSize().x) { IsPlaying = false; End.SetText("You won !\n(press escape to exit)"); @@ -138,11 +138,11 @@ int main() BallAngle = -BallAngle; Ball.SetY(0.1f); } - if (Ball.GetPosition().y + Ball.GetSize().y > App.GetView().GetRect().GetHeight()) + if (Ball.GetPosition().y + Ball.GetSize().y > App.GetView().GetSize().y) { BallSound.Play(); BallAngle = -BallAngle; - Ball.SetY(App.GetView().GetRect().GetHeight() - Ball.GetSize().y - 0.1f); + Ball.SetY(App.GetView().GetSize().y - Ball.GetSize().y - 0.1f); } // Check the collisions between the ball and the paddles diff --git a/src/SFML/Graphics/Drawable.cpp b/src/SFML/Graphics/Drawable.cpp index e2484c650..788ff2644 100644 --- a/src/SFML/Graphics/Drawable.cpp +++ b/src/SFML/Graphics/Drawable.cpp @@ -381,7 +381,7 @@ void Drawable::Draw(RenderTarget& Target) const // We have to use glBlendFuncSeparate so that the resulting alpha is // not alphaČ, which is incorrect and would cause problems when rendering - // alpha pixels to a RenderImage that would be in turn rendered to another render target + // alpha pixels to a RenderImage that would be in turn be rendered to another render target switch (myBlendMode) { case Blend::Alpha : diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index 04e06c8d9..538fa3e44 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -288,7 +288,7 @@ void Image::Copy(const Image& Source, unsigned int DestX, unsigned int DestY, co // Adjust the source rectangle IntRect SrcRect = SourceRect; - if (SrcRect.GetWidth() == 0 || (SrcRect.GetHeight() == 0)) + if (SrcRect.GetSize().x == 0 || (SrcRect.GetSize().y == 0)) { SrcRect.Left = 0; SrcRect.Top = 0; @@ -304,8 +304,8 @@ void Image::Copy(const Image& Source, unsigned int DestX, unsigned int DestY, co } // Then find the valid bounds of the destination rectangle - int Width = SrcRect.GetWidth(); - int Height = SrcRect.GetHeight(); + int Width = SrcRect.GetSize().x; + int Height = SrcRect.GetSize().y; if (DestX + Width > myWidth) Width = myWidth - DestX; if (DestY + Height > myHeight) Height = myHeight - DestY; @@ -368,7 +368,7 @@ bool Image::CopyScreen(RenderWindow& Window, const IntRect& SourceRect) { // Adjust the source rectangle IntRect SrcRect = SourceRect; - if (SrcRect.GetWidth() == 0 || (SrcRect.GetHeight() == 0)) + if (SrcRect.GetSize().x == 0 || (SrcRect.GetSize().y == 0)) { SrcRect.Left = 0; SrcRect.Top = 0; @@ -384,8 +384,8 @@ bool Image::CopyScreen(RenderWindow& Window, const IntRect& SourceRect) } // Store the texture dimensions - myWidth = SrcRect.GetWidth(); - myHeight = SrcRect.GetHeight(); + myWidth = SrcRect.GetSize().x; + myHeight = SrcRect.GetSize().y; // We can then create the texture if (Window.SetActive() && CreateTexture()) diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 234a5a1c6..8393c24bf 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -175,7 +175,7 @@ void RenderTarget::Initialize() SetRenderStates(); // Setup the default view - myDefaultView.SetFromRect(FloatRect(0, 0, static_cast(GetWidth()), static_cast(GetHeight()))); + myDefaultView.SetRect(FloatRect(0, 0, static_cast(GetWidth()), static_cast(GetHeight()))); SetView(myDefaultView); Activate(false); diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp index 6d859a197..c28e69f73 100644 --- a/src/SFML/Graphics/RenderWindow.cpp +++ b/src/SFML/Graphics/RenderWindow.cpp @@ -142,13 +142,15 @@ sf::Vector2f RenderWindow::ConvertCoords(unsigned int WindowX, unsigned int Wind if (!TargetView) TargetView = &GetView(); - float Left = TargetView->GetCenter().x - TargetView->GetHalfSize().x; - float Top = TargetView->GetCenter().y - TargetView->GetHalfSize().y; - float Right = TargetView->GetCenter().x + TargetView->GetHalfSize().x; - float Bottom = TargetView->GetCenter().y + TargetView->GetHalfSize().y; + // First, convert from viewport coordinates to homogeneous coordinates: + // --> [0, Width] to [-1, 1] + // --> [0, Height] to [1, -1] + Vector2f Coords; + Coords.x = -1.f + 2.f * WindowX / GetWidth(); + Coords.y = 1.f - 2.f * WindowY / GetHeight(); - return sf::Vector2f(Left + WindowX * (Right - Left) / GetWidth(), - Top + WindowY * (Bottom - Top) / GetHeight()); + // Then transform by the inverse of the view matrix + return TargetView->GetInverseMatrix().Transform(Coords); } diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp index 278b1daf6..2b969a301 100644 --- a/src/SFML/Graphics/Sprite.cpp +++ b/src/SFML/Graphics/Sprite.cpp @@ -88,8 +88,8 @@ void Sprite::SetSubRect(const IntRect& SubRect) //////////////////////////////////////////////////////////// void Sprite::Resize(float Width, float Height) { - int LocalWidth = mySubRect.GetWidth(); - int LocalHeight = mySubRect.GetHeight(); + int LocalWidth = mySubRect.GetSize().x; + int LocalHeight = mySubRect.GetSize().y; if ((LocalWidth > 0) && (LocalHeight > 0)) SetScale(Width / LocalWidth, Height / LocalHeight); @@ -147,7 +147,7 @@ const IntRect& Sprite::GetSubRect() const //////////////////////////////////////////////////////////// Vector2f Sprite::GetSize() const { - return Vector2f(mySubRect.GetWidth() * GetScale().x, mySubRect.GetHeight() * GetScale().y); + return Vector2f(mySubRect.GetSize().x * GetScale().x, mySubRect.GetSize().y * GetScale().y); } @@ -162,8 +162,8 @@ Color Sprite::GetPixel(unsigned int X, unsigned int Y) const unsigned int ImageX = mySubRect.Left + X; unsigned int ImageY = mySubRect.Top + Y; - if (myIsFlippedX) ImageX = mySubRect.GetWidth() - ImageX - 1; - if (myIsFlippedY) ImageY = mySubRect.GetHeight() - ImageY - 1; + if (myIsFlippedX) ImageX = mySubRect.GetSize().x - ImageX - 1; + if (myIsFlippedY) ImageY = mySubRect.GetSize().y - ImageY - 1; return myImage->GetPixel(ImageX, ImageY) * GetColor(); } @@ -180,8 +180,8 @@ Color Sprite::GetPixel(unsigned int X, unsigned int Y) const void Sprite::Render(RenderTarget&) const { // Get the sprite size - float Width = static_cast(mySubRect.GetWidth()); - float Height = static_cast(mySubRect.GetHeight()); + float Width = static_cast(mySubRect.GetSize().x); + float Height = static_cast(mySubRect.GetSize().y); // Check if the image is valid if (myImage && (myImage->GetWidth() > 0) && (myImage->GetHeight() > 0)) diff --git a/src/SFML/Graphics/View.cpp b/src/SFML/Graphics/View.cpp index 0b2fb66a1..9143b2829 100644 --- a/src/SFML/Graphics/View.cpp +++ b/src/SFML/Graphics/View.cpp @@ -26,7 +26,6 @@ // Headers //////////////////////////////////////////////////////////// #include -#include namespace sf @@ -34,102 +33,116 @@ namespace sf //////////////////////////////////////////////////////////// /// Construct the view from a rectangle //////////////////////////////////////////////////////////// -View::View(const FloatRect& ViewRect) +View::View(const FloatRect& Rect) { - SetFromRect(ViewRect); + SetRect(Rect); } //////////////////////////////////////////////////////////// -/// Construct the view from its center and half-size +/// Construct the view from its center and size //////////////////////////////////////////////////////////// -View::View(const sf::Vector2f& Center, const sf::Vector2f& HalfSize) : -myCenter (Center), -myHalfSize (HalfSize), -myNeedUpdate(true) +View::View(const Vector2f& Center, const Vector2f& Size) : +myCenter (Center), +mySize (Size), +myNeedUpdate (true), +myNeedInvUpdate(true) { } +//////////////////////////////////////////////////////////// +/// Set the rectangle defining the view by its center and size +//////////////////////////////////////////////////////////// +void View::SetRect(const Vector2f& Center, const Vector2f& Size) +{ + myCenter = Center; + mySize = Size; + myNeedUpdate = true; + myNeedInvUpdate = true; +} + + +//////////////////////////////////////////////////////////// +/// Set the rectangle defining the view +//////////////////////////////////////////////////////////// +void View::SetRect(const FloatRect& Rect) +{ + SetRect(Rect.GetCenter(), Rect.GetSize()); +} + + //////////////////////////////////////////////////////////// /// Change the center of the view (take 2 values) //////////////////////////////////////////////////////////// void View::SetCenter(float X, float Y) { - myCenter.x = X; - myCenter.y = Y; - myNeedUpdate = true; + myCenter.x = X; + myCenter.y = Y; + myNeedUpdate = true; + myNeedInvUpdate = true; } //////////////////////////////////////////////////////////// /// Change the center of the view (take a vector) //////////////////////////////////////////////////////////// -void View::SetCenter(const sf::Vector2f& Center) +void View::SetCenter(const Vector2f& Center) { SetCenter(Center.x, Center.y); } //////////////////////////////////////////////////////////// -/// Change the half-size of the view (take 2 values) +/// Change the size of the view (take 2 values) //////////////////////////////////////////////////////////// -void View::SetHalfSize(float HalfWidth, float HalfHeight) +void View::SetSize(float Width, float Height) { - myHalfSize.x = HalfWidth; - myHalfSize.y = HalfHeight; - myNeedUpdate = true; + mySize.x = Width; + mySize.y = Height; + myNeedUpdate = true; + myNeedInvUpdate = true; } //////////////////////////////////////////////////////////// -/// Change the half-size of the view (take a vector) +/// Change the size of the view (take a vector) //////////////////////////////////////////////////////////// -void View::SetHalfSize(const sf::Vector2f& HalfSize) +void View::SetSize(const Vector2f& Size) { - SetHalfSize(HalfSize.x, HalfSize.y); + SetSize(Size.x, Size.y); } //////////////////////////////////////////////////////////// -/// Rebuild the view from a rectangle +/// Get the rectangle defining the view, +/// which is the combined center and size. //////////////////////////////////////////////////////////// -void View::SetFromRect(const FloatRect& ViewRect) +FloatRect View::GetRect() const { - SetCenter( (ViewRect.Right + ViewRect.Left) / 2, (ViewRect.Bottom + ViewRect.Top) / 2); - SetHalfSize((ViewRect.Right - ViewRect.Left) / 2, (ViewRect.Bottom - ViewRect.Top) / 2); + return FloatRect(myCenter.x - mySize.x / 2, + myCenter.y - mySize.y / 2, + myCenter.x + mySize.x / 2, + myCenter.y + mySize.y / 2); } //////////////////////////////////////////////////////////// /// Get the center of the view //////////////////////////////////////////////////////////// -const sf::Vector2f& View::GetCenter() const +const Vector2f& View::GetCenter() const { return myCenter; } //////////////////////////////////////////////////////////// -/// Get the half-size of the view +/// Get the size of the view //////////////////////////////////////////////////////////// -const sf::Vector2f& View::GetHalfSize() const +const Vector2f& View::GetSize() const { - return myHalfSize; -} - - -//////////////////////////////////////////////////////////// -/// Get the bounding rectangle of the view -//////////////////////////////////////////////////////////// -const sf::FloatRect& View::GetRect() const -{ - // Recompute it if needed - if (myNeedUpdate) - const_cast(this)->RecomputeMatrix(); - - return myRect; + return mySize; } @@ -138,16 +151,17 @@ const sf::FloatRect& View::GetRect() const //////////////////////////////////////////////////////////// void View::Move(float OffsetX, float OffsetY) { - myCenter.x += OffsetX; - myCenter.y += OffsetY; - myNeedUpdate = true; + myCenter.x += OffsetX; + myCenter.y += OffsetY; + myNeedUpdate = true; + myNeedInvUpdate = true; } //////////////////////////////////////////////////////////// /// Move the view (take a vector) //////////////////////////////////////////////////////////// -void View::Move(const sf::Vector2f& Offset) +void View::Move(const Vector2f& Offset) { Move(Offset.x, Offset.y); } @@ -160,8 +174,9 @@ void View::Zoom(float Factor) { if (Factor != 0) { - myHalfSize /= Factor; - myNeedUpdate = true; + mySize /= Factor; + myNeedUpdate = true; + myNeedInvUpdate = true; } } @@ -173,36 +188,28 @@ const Matrix3& View::GetMatrix() const { // Recompute the matrix if needed if (myNeedUpdate) - const_cast(this)->RecomputeMatrix(); + { + myMatrix.SetFromProjection(GetRect()); + myNeedUpdate = false; + } return myMatrix; } //////////////////////////////////////////////////////////// -/// Recompute the view rectangle and the projection matrix +/// Get the inverse projection matrix of the view //////////////////////////////////////////////////////////// -void View::RecomputeMatrix() +const Matrix3& View::GetInverseMatrix() const { - // Compute the 4 corners of the view - float Left = myCenter.x - myHalfSize.x; - float Top = myCenter.y - myHalfSize.y; - float Right = myCenter.x + myHalfSize.x; - float Bottom = myCenter.y + myHalfSize.y; + // Recompute the matrix if needed + if (myNeedInvUpdate) + { + myInverseMatrix = GetMatrix().GetInverse(); + myNeedInvUpdate = false; + } - // Update the view rectangle - be careful, reversed views are allowed ! - myRect.Left = std::min(Left, Right); - myRect.Top = std::min(Top, Bottom); - myRect.Right = std::max(Left, Right); - myRect.Bottom = std::max(Top, Bottom); - - // Update the projection matrix - myMatrix(0, 0) = 2.f / (Right - Left); - myMatrix(1, 1) = 2.f / (Top - Bottom); - myMatrix(0, 2) = (Left + Right) / (Left - Right); - myMatrix(1, 2) = (Bottom + Top) / (Bottom - Top); - - myNeedUpdate = false; + return myInverseMatrix; } } // namespace sf