diff --git a/examples/opengl/OpenGL.cpp b/examples/opengl/OpenGL.cpp index fd00839d5..f86522eee 100644 --- a/examples/opengl/OpenGL.cpp +++ b/examples/opengl/OpenGL.cpp @@ -4,7 +4,6 @@ //////////////////////////////////////////////////////////// #include #include -#include //////////////////////////////////////////////////////////// /// Entry point of application @@ -77,9 +76,9 @@ int main() } // Draw the background - window.SaveGLStates(); + window.PushGLStates(); window.Draw(background); - window.RestoreGLStates(); + window.PopGLStates(); // Activate the window before using OpenGL commands. // This is useless here because we have only one window which is @@ -138,12 +137,12 @@ int main() glEnd(); // Draw some text on top of our OpenGL object - window.SaveGLStates(); + window.PushGLStates(); sf::Text text("SFML / OpenGL demo"); - text.SetPosition(250.f, 450.f); text.SetColor(sf::Color(255, 255, 255, 170)); + text.SetPosition(250.f, 450.f); window.Draw(text); - window.RestoreGLStates(); + window.PopGLStates(); // Finally, display the rendered frame on screen window.Display(); diff --git a/examples/pong/Pong.cpp b/examples/pong/Pong.cpp index 0e9abfc45..a203dea76 100644 --- a/examples/pong/Pong.cpp +++ b/examples/pong/Pong.cpp @@ -19,172 +19,216 @@ int main() { std::srand(static_cast(std::time(NULL))); - // Defines PI - const float PI = 3.14159f; + // Define some constants + const float pi = 3.14159f; + const int gameWidth = 800; + const int gameHeight = 600; + sf::Vector2f paddleSize(25, 100); + float ballRadius = 10.f; // Create the window of the application - sf::RenderWindow window(sf::VideoMode(800, 600, 32), "SFML Pong"); + sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong"); // Load the sounds used in the game sf::SoundBuffer ballSoundBuffer; if (!ballSoundBuffer.LoadFromFile("resources/ball.wav")) - { return EXIT_FAILURE; - } sf::Sound ballSound(ballSoundBuffer); - // Load the textures used in the game - sf::Texture backgroundTexture, leftPaddleTexture, rightPaddleTexture, ballTexture; - if (!backgroundTexture.LoadFromFile("resources/background.jpg") || - !leftPaddleTexture.LoadFromFile("resources/paddle_left.png") || - !rightPaddleTexture.LoadFromFile("resources/paddle_right.png") || - !ballTexture.LoadFromFile("resources/ball.png")) - { - return EXIT_FAILURE; - } + // Create the left paddle + sf::RectangleShape leftPaddle; + leftPaddle.SetSize(paddleSize - sf::Vector2f(3, 3)); + leftPaddle.SetOutlineThickness(3); + leftPaddle.SetOutlineColor(sf::Color::Black); + leftPaddle.SetFillColor(sf::Color(100, 100, 200)); + leftPaddle.SetOrigin(paddleSize / 2.f); + + // Create the right paddle + sf::RectangleShape rightPaddle; + rightPaddle.SetSize(paddleSize - sf::Vector2f(3, 3)); + rightPaddle.SetOutlineThickness(3); + rightPaddle.SetOutlineColor(sf::Color::Black); + rightPaddle.SetFillColor(sf::Color(200, 100, 100)); + rightPaddle.SetOrigin(paddleSize / 2.f); + + // Create the ball + sf::CircleShape ball; + ball.SetRadius(ballRadius - 3); + ball.SetOutlineThickness(3); + ball.SetOutlineColor(sf::Color::Black); + ball.SetFillColor(sf::Color::White); + ball.SetOrigin(ballRadius / 2, ballRadius / 2); // Load the text font sf::Font font; if (!font.LoadFromFile("resources/sansation.ttf")) return EXIT_FAILURE; - // Initialize the end text - sf::Text end; - end.SetFont(font); - end.SetCharacterSize(60); - end.Move(150.f, 200.f); - end.SetColor(sf::Color(50, 50, 250)); - - // Create the sprites of the background, the paddles and the ball - sf::Sprite background(backgroundTexture); - sf::Sprite leftPaddle(leftPaddleTexture); - sf::Sprite rightPaddle(rightPaddleTexture); - sf::Sprite ball(ballTexture); - - leftPaddle.Move(10, (window.GetView().GetSize().y - leftPaddle.GetSize().y) / 2); - rightPaddle.Move(window.GetView().GetSize().x - rightPaddle.GetSize().x - 10, (window.GetView().GetSize().y - rightPaddle.GetSize().y) / 2); - ball.Move((window.GetView().GetSize().x - ball.GetSize().x) / 2, (window.GetView().GetSize().y - ball.GetSize().y) / 2); + // Initialize the pause message + sf::Text pauseMessage; + pauseMessage.SetFont(font); + pauseMessage.SetCharacterSize(40); + pauseMessage.SetPosition(170.f, 150.f); + pauseMessage.SetColor(sf::Color::White); + pauseMessage.SetString("Welcome to SFML pong!\nPress space to start the game"); // Define the paddles properties sf::Clock AITimer; - const float AITime = 0.1f; - float leftPaddleSpeed = 400.f; - float rightPaddleSpeed = 400.f; + const sf::Uint32 AITime = 300; + const float paddleSpeed = 400.f; + float rightPaddleSpeed = 0.f; + const float ballSpeed = 400.f; + float ballAngle = 0.f; // to be changed later - // Define the ball properties - float ballSpeed = 400.f; - float ballAngle; - do - { - // Make sure the ball initial angle is not too much vertical - ballAngle = std::rand() * 2 * PI / RAND_MAX; - } while (std::abs(std::cos(ballAngle)) < 0.7f); - - bool isPlaying = true; + bool isPlaying = false; while (window.IsOpened()) { // Handle events sf::Event event; while (window.PollEvent(event)) { - // Window closed or escape key pressed : exit + // Window closed or escape key pressed: exit if ((event.Type == sf::Event::Closed) || ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Keyboard::Escape))) { window.Close(); break; } + + // Space key pressed: play + if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Keyboard::Space)) + { + if (!isPlaying) + { + // (re)start the game + isPlaying = true; + + // Reset the position of the paddles and ball + leftPaddle.SetPosition(10 + paddleSize.x / 2, gameHeight / 2); + rightPaddle.SetPosition(gameWidth - 10 - paddleSize.x / 2, gameHeight / 2); + ball.SetPosition(gameWidth / 2, gameHeight / 2); + + // Reset the ball angle + do + { + // Make sure the ball initial angle is not too much vertical + ballAngle = (std::rand() % 360) * 2 * pi / 360; + } + while (std::abs(std::cos(ballAngle)) < 0.7f); + } + } } if (isPlaying) { + float deltaTime = window.GetFrameTime() / 1000.f; + // Move the player's paddle - if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up) && (leftPaddle.GetPosition().y > 5.f)) - leftPaddle.Move(0.f, -leftPaddleSpeed * window.GetFrameTime() / 1000.f); - if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Down) && (leftPaddle.GetPosition().y < window.GetView().GetSize().y - leftPaddle.GetSize().y - 5.f)) - leftPaddle.Move(0.f, leftPaddleSpeed * window.GetFrameTime() / 1000.f); + if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up) && + (leftPaddle.GetPosition().y - paddleSize.y / 2 > 5.f)) + { + leftPaddle.Move(0.f, -paddleSpeed * deltaTime); + } + if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Down) && + (leftPaddle.GetPosition().y + paddleSize.y / 2 < gameHeight - 5.f)) + { + leftPaddle.Move(0.f, paddleSpeed * deltaTime); + } // Move the computer's paddle - if (((rightPaddleSpeed < 0.f) && (rightPaddle.GetPosition().y > 5.f)) || - ((rightPaddleSpeed > 0.f) && (rightPaddle.GetPosition().y < window.GetView().GetSize().y - rightPaddle.GetSize().y - 5.f))) + if (((rightPaddleSpeed < 0.f) && (rightPaddle.GetPosition().y - paddleSize.y / 2 > 5.f)) || + ((rightPaddleSpeed > 0.f) && (rightPaddle.GetPosition().y + paddleSize.y / 2 < gameHeight - 5.f))) { - rightPaddle.Move(0.f, rightPaddleSpeed * window.GetFrameTime() / 1000.f); + rightPaddle.Move(0.f, rightPaddleSpeed * deltaTime); } // Update the computer's paddle direction according to the ball position if (AITimer.GetElapsedTime() > AITime) { AITimer.Reset(); - if ((rightPaddleSpeed < 0) && (ball.GetPosition().y + ball.GetSize().y > rightPaddle.GetPosition().y + rightPaddle.GetSize().y)) - rightPaddleSpeed = -rightPaddleSpeed; - if ((rightPaddleSpeed > 0) && (ball.GetPosition().y < rightPaddle.GetPosition().y)) - rightPaddleSpeed = -rightPaddleSpeed; + if (ball.GetPosition().y + ballRadius > rightPaddle.GetPosition().y + paddleSize.y / 2) + rightPaddleSpeed = paddleSpeed; + else if (ball.GetPosition().y - ballRadius < rightPaddle.GetPosition().y - paddleSize.y / 2) + rightPaddleSpeed = -paddleSpeed; + else + rightPaddleSpeed = 0.f; } // Move the ball - float factor = ballSpeed * window.GetFrameTime() / 1000.f; - ball.Move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor); + float factor = ballSpeed * deltaTime; + ball.Move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor); // Check collisions between the ball and the screen - if (ball.GetPosition().x < 0.f) + if (ball.GetPosition().x - ballRadius < 0.f) { isPlaying = false; - end.SetString("You lost !\n(press escape to exit)"); + pauseMessage.SetString("You lost !\nPress space to restart or\nescape to exit"); } - if (ball.GetPosition().x + ball.GetSize().x > window.GetView().GetSize().x) + if (ball.GetPosition().x + ballRadius > 800) { isPlaying = false; - end.SetString("You won !\n(press escape to exit)"); + pauseMessage.SetString("You won !\nPress space to restart or\nescape to exit"); } - if (ball.GetPosition().y < 0.f) + if (ball.GetPosition().y - ballRadius < 0.f) { ballSound.Play(); ballAngle = -ballAngle; - ball.SetY(0.1f); + ball.SetPosition(ball.GetPosition().x, ballRadius + 0.1f); } - if (ball.GetPosition().y + ball.GetSize().y > window.GetView().GetSize().y) + if (ball.GetPosition().y + ballRadius > gameHeight) { ballSound.Play(); ballAngle = -ballAngle; - ball.SetY(window.GetView().GetSize().y - ball.GetSize().y - 0.1f); + ball.SetPosition(ball.GetPosition().x, gameHeight - ballRadius - 0.1f); } // Check the collisions between the ball and the paddles // Left Paddle - if (ball.GetPosition().x < leftPaddle.GetPosition().x + leftPaddle.GetSize().x && - ball.GetPosition().x > leftPaddle.GetPosition().x + (leftPaddle.GetSize().x / 2.0f) && - ball.GetPosition().y + ball.GetSize().y >= leftPaddle.GetPosition().y && - ball.GetPosition().y <= leftPaddle.GetPosition().y + leftPaddle.GetSize().y) + if (ball.GetPosition().x - ballRadius < leftPaddle.GetPosition().x + paddleSize.x / 2 && + ball.GetPosition().x - ballRadius > leftPaddle.GetPosition().x && + ball.GetPosition().y + ballRadius >= leftPaddle.GetPosition().y - paddleSize.y / 2 && + ball.GetPosition().y - ballRadius <= leftPaddle.GetPosition().y + paddleSize.y / 2) { + if (ball.GetPosition().y > leftPaddle.GetPosition().y) + ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; + else + ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; + ballSound.Play(); - ballAngle = PI - ballAngle; - ball.SetX(leftPaddle.GetPosition().x + leftPaddle.GetSize().x + 0.1f); + ball.SetPosition(leftPaddle.GetPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.GetPosition().y); } // Right Paddle - if (ball.GetPosition().x + ball.GetSize().x > rightPaddle.GetPosition().x && - ball.GetPosition().x + ball.GetSize().x < rightPaddle.GetPosition().x + (rightPaddle.GetSize().x / 2.0f) && - ball.GetPosition().y + ball.GetSize().y >= rightPaddle.GetPosition().y && - ball.GetPosition().y <= rightPaddle.GetPosition().y + rightPaddle.GetSize().y) + if (ball.GetPosition().x + ballRadius > rightPaddle.GetPosition().x - paddleSize.x / 2 && + ball.GetPosition().x + ballRadius < rightPaddle.GetPosition().x && + ball.GetPosition().y + ballRadius >= rightPaddle.GetPosition().y - paddleSize.y / 2 && + ball.GetPosition().y - ballRadius <= rightPaddle.GetPosition().y + paddleSize.y / 2) { + if (ball.GetPosition().y > rightPaddle.GetPosition().y) + ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180; + else + ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180; + ballSound.Play(); - ballAngle = PI - ballAngle; - ball.SetX(rightPaddle.GetPosition().x - ball.GetSize().x - 0.1f); + ball.SetPosition(rightPaddle.GetPosition().x - ballRadius - paddleSize.x / 2 - 0.1f, ball.GetPosition().y); } } // Clear the window - window.Clear(); + window.Clear(sf::Color(50, 200, 50)); - // Draw the background, paddles and ball sprites - window.Draw(background); - window.Draw(leftPaddle); - window.Draw(rightPaddle); - window.Draw(ball); - - // If the game is over, display the end message - if (!isPlaying) - window.Draw(end); + if (isPlaying) + { + // Draw the paddles and the ball + window.Draw(leftPaddle); + window.Draw(rightPaddle); + window.Draw(ball); + } + else + { + // Draw the pause message + window.Draw(pauseMessage); + } // Display things on screen window.Display(); diff --git a/examples/pong/resources/background.jpg b/examples/pong/resources/background.jpg deleted file mode 100644 index 06dfdb8b8..000000000 Binary files a/examples/pong/resources/background.jpg and /dev/null differ diff --git a/examples/pong/resources/ball.png b/examples/pong/resources/ball.png deleted file mode 100644 index c296859b6..000000000 Binary files a/examples/pong/resources/ball.png and /dev/null differ diff --git a/examples/pong/resources/paddle_left.png b/examples/pong/resources/paddle_left.png deleted file mode 100644 index 63592c9be..000000000 Binary files a/examples/pong/resources/paddle_left.png and /dev/null differ diff --git a/examples/pong/resources/paddle_right.png b/examples/pong/resources/paddle_right.png deleted file mode 100644 index d408c5fd6..000000000 Binary files a/examples/pong/resources/paddle_right.png and /dev/null differ diff --git a/examples/shader/Shader.cpp b/examples/shader/Shader.cpp index 40ca7324f..e8456fd41 100644 --- a/examples/shader/Shader.cpp +++ b/examples/shader/Shader.cpp @@ -58,9 +58,9 @@ public : } // Get the current shader - const sf::Shader& GetShader() const + const sf::Shader* GetShader() const { - return myIterator->second; + return &myIterator->second; } private : @@ -144,8 +144,8 @@ int main() sf::Text shaderStr; shaderStr.SetFont(font); shaderStr.SetCharacterSize(20); - shaderStr.SetPosition(5.f, 0.f); shaderStr.SetColor(sf::Color(250, 100, 30)); + shaderStr.SetPosition(5.f, 0.f); shaderStr.SetString("Background shader: \"" + backgroundShader.GetName() + "\"\n" "Flower shader: \"" + entityShader.GetName() + "\"\n" "Global shader: \"" + globalShader.GetName() + "\"\n"); @@ -154,8 +154,8 @@ int main() sf::Text infoStr; infoStr.SetFont(font); infoStr.SetCharacterSize(20); - infoStr.SetPosition(5.f, 500.f); infoStr.SetColor(sf::Color(250, 100, 30)); + infoStr.SetPosition(5.f, 500.f); infoStr.SetString("Move your mouse to change the shaders' parameters\n" "Press numpad 1/4 to change the background shader\n" "Press numpad 2/5 to change the flower shader\n" @@ -249,8 +249,8 @@ void DisplayError() // Define a string for displaying the error message sf::Text error("Sorry, your system doesn't support shaders"); - error.SetPosition(100.f, 250.f); error.SetColor(sf::Color(200, 100, 150)); + error.SetPosition(100.f, 250.f); // Start the game loop while (window.IsOpened()) diff --git a/examples/sound/Sound.cpp b/examples/sound/Sound.cpp index 8215d48bd..fd31ce7aa 100644 --- a/examples/sound/Sound.cpp +++ b/examples/sound/Sound.cpp @@ -35,7 +35,8 @@ void PlaySound() sf::Sleep(100); // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.GetPlayingOffset() << " sec "; + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.GetPlayingOffset() / 1000.f << " sec "; + std::cout << std::flush; } std::cout << std::endl << std::endl; } @@ -68,7 +69,8 @@ void PlayMusic() sf::Sleep(100); // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << music.GetPlayingOffset() << " sec "; + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << music.GetPlayingOffset() / 1000.f << " sec "; + std::cout << std::flush; } std::cout << std::endl; } diff --git a/examples/sound_capture/SoundCapture.cpp b/examples/sound_capture/SoundCapture.cpp index 83e850095..41b7da765 100644 --- a/examples/sound_capture/SoundCapture.cpp +++ b/examples/sound_capture/SoundCapture.cpp @@ -76,7 +76,8 @@ int main() while (sound.GetStatus() == sf::Sound::Playing) { // Display the playing position - std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.GetPlayingOffset() << " sec"; + std::cout << "\rPlaying... " << std::fixed << std::setprecision(2) << sound.GetPlayingOffset() / 1000.f << " sec"; + std::cout << std::flush; // Leave some CPU time for other threads sf::Sleep(100); diff --git a/examples/win32/Win32.cpp b/examples/win32/Win32.cpp index 97c94e42d..34db79070 100644 --- a/examples/win32/Win32.cpp +++ b/examples/win32/Win32.cpp @@ -81,8 +81,8 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT) return EXIT_FAILURE; sf::Sprite sprite1(texture1); sf::Sprite sprite2(texture2); - sprite1.SetOrigin(sprite1.GetSize() / 2.f); - sprite1.SetPosition(sprite1.GetSize() / 2.f); + sprite1.SetOrigin(texture1.GetWidth() / 2.f, texture1.GetHeight() / 2.f); + sprite1.SetPosition(sprite1.GetOrigin()); // Create a clock for measuring elapsed time sf::Clock clock; @@ -100,16 +100,18 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, INT) } else { + sf::Uint32 time = clock.GetElapsedTime(); + // Clear views SFMLView1.Clear(); SFMLView2.Clear(); // Draw sprite 1 on view 1 - sprite1.SetRotation(clock.GetElapsedTime() * 0.1f); + sprite1.SetRotation(time * 0.1f); SFMLView1.Draw(sprite1); // Draw sprite 2 on view 2 - sprite2.SetX(cos(clock.GetElapsedTime() * 0.001f) * 100.f); + sprite2.SetPosition(std::cos(time * 0.001f) * 100.f, 0.f); SFMLView2.Draw(sprite2); // Display each view on screen diff --git a/include/SFML/Graphics.hpp b/include/SFML/Graphics.hpp index ba9943311..f20aedd46 100644 --- a/include/SFML/Graphics.hpp +++ b/include/SFML/Graphics.hpp @@ -30,18 +30,26 @@ //////////////////////////////////////////////////////////// #include +#include #include #include #include #include -#include +#include #include #include #include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include #include diff --git a/src/SFML/Graphics/Matrix3.cpp b/include/SFML/Graphics/BlendMode.hpp similarity index 76% rename from src/SFML/Graphics/Matrix3.cpp rename to include/SFML/Graphics/BlendMode.hpp index 7de4b0f65..448903bdb 100644 --- a/src/SFML/Graphics/Matrix3.cpp +++ b/include/SFML/Graphics/BlendMode.hpp @@ -1,40 +1,46 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -// Static member data -//////////////////////////////////////////////////////////// -const Matrix3 Matrix3::Identity(1, 0, 0, - 0, 1, 0, - 0, 0, 1); - -} // namespace sf +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_BLENDMODE_HPP +#define SFML_BLENDMODE_HPP + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup graphics +/// \brief Available blending modes for drawing +/// +//////////////////////////////////////////////////////////// +enum BlendMode +{ + BlendAlpha, ///< Pixel = Source * Source.a + Dest * (1 - Source.a) + BlendAdd, ///< Pixel = Source + Dest + BlendMultiply, ///< Pixel = Source * Dest + BlendNone ///< Pixel = Source +}; + +} // namespace sf + + +#endif // SFML_BLENDMODE_HPP diff --git a/include/SFML/Graphics/CircleShape.hpp b/include/SFML/Graphics/CircleShape.hpp new file mode 100644 index 000000000..fb1819487 --- /dev/null +++ b/include/SFML/Graphics/CircleShape.hpp @@ -0,0 +1,129 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CIRCLESHAPE_HPP +#define SFML_CIRCLESHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a circle +/// +//////////////////////////////////////////////////////////// +class SFML_API CircleShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a circle with a radius of 10. + /// + //////////////////////////////////////////////////////////// + CircleShape(); + + //////////////////////////////////////////////////////////// + /// \brief Set the radius of the circle + /// + /// The default radius of a circle is 10. + /// + /// \param radius New radius of the circle + /// + /// \see GetRadius + /// + //////////////////////////////////////////////////////////// + void SetRadius(float radius); + + //////////////////////////////////////////////////////////// + /// \brief Get the radius of the circle + /// + /// \return Radius of the circle + /// + /// \see SetRadius + /// + //////////////////////////////////////////////////////////// + float GetRadius() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points defining the shape + /// + /// \return Number of points of the shape + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetOutlinePointsCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// \param index Index of the point to get + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f GetOutlinePoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float myRadius; ///< Radius of the circle +}; + +} // namespace sf + + +#endif // SFML_CIRCLESHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::CircleShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// Usage example: +/// \code +/// sf::CircleShape circle; +/// circle.SetRadius(150); +/// circle.SetOutlineColor(sf::Color::Red); +/// circle.SetOutlineThickness(5); +/// circle.SetPosition(10, 20); +/// ... +/// window.Draw(circle); +/// \endcode +/// +/// \see sf::Shape, sf::StarShape, sf::RectangleShape, sf::ConvexShape +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Color.hpp b/include/SFML/Graphics/Color.hpp index 8307ad727..4838239de 100644 --- a/include/SFML/Graphics/Color.hpp +++ b/include/SFML/Graphics/Color.hpp @@ -64,14 +64,15 @@ public : //////////////////////////////////////////////////////////// // Static member data //////////////////////////////////////////////////////////// - static const Color Black; ///< Black predefined color - static const Color White; ///< White predefined color - static const Color Red; ///< Red predefined color - static const Color Green; ///< Green predefined color - static const Color Blue; ///< Blue predefined color - static const Color Yellow; ///< Yellow predefined color - static const Color Magenta; ///< Magenta predefined color - static const Color Cyan; ///< Cyan predefined color + static const Color Black; ///< Black predefined color + static const Color White; ///< White predefined color + static const Color Red; ///< Red predefined color + static const Color Green; ///< Green predefined color + static const Color Blue; ///< Blue predefined color + static const Color Yellow; ///< Yellow predefined color + static const Color Magenta; ///< Magenta predefined color + static const Color Cyan; ///< Cyan predefined color + static const Color Transparent; ///< Transparent (black) predefined color //////////////////////////////////////////////////////////// // Member data @@ -197,27 +198,28 @@ SFML_API Color& operator *=(Color& left, const Color& right); /// manipulated very easily: /// /// \code -/// sf::Color c1(255, 0, 0); // red -/// c1.red = 0; // make it black -/// c1.blue = 128; // make it dark blue +/// sf::Color color(255, 0, 0); // red +/// color.red = 0; // make it black +/// color.blue = 128; // make it dark blue /// \endcode /// /// The fourth component of colors, named "alpha", represents /// the opacity of the color. A color with an alpha value of /// 255 will be fully opaque, while an alpha value of 0 will /// make a color fully transparent, whatever the value of the -/// other components. +/// other components is. /// /// The most common colors are already defined as static variables: /// \code -/// sf::Color black = sf::Color::Black; -/// sf::Color white = sf::Color::White; -/// sf::Color red = sf::Color::Red; -/// sf::Color green = sf::Color::Green; -/// sf::Color blue = sf::Color::Blue; -/// sf::Color yellow = sf::Color::Yellow; -/// sf::Color magenta = sf::Color::Magenta; -/// sf::Color cyan = sf::Color::Cyan; +/// sf::Color black = sf::Color::Black; +/// sf::Color white = sf::Color::White; +/// sf::Color red = sf::Color::Red; +/// sf::Color green = sf::Color::Green; +/// sf::Color blue = sf::Color::Blue; +/// sf::Color yellow = sf::Color::Yellow; +/// sf::Color magenta = sf::Color::Magenta; +/// sf::Color cyan = sf::Color::Cyan; +/// sf::Color transparent = sf::Color::Transparent; /// \endcode /// /// Colors can also be added and modulated (multiplied) using the diff --git a/include/SFML/Graphics/ConvexShape.hpp b/include/SFML/Graphics/ConvexShape.hpp new file mode 100644 index 000000000..ac0d5be8d --- /dev/null +++ b/include/SFML/Graphics/ConvexShape.hpp @@ -0,0 +1,164 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_CONVEXSHAPE_HPP +#define SFML_CONVEXSHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a convex polygon +/// +//////////////////////////////////////////////////////////// +class SFML_API ConvexShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a default triangle, just so that it's not empty. + /// + //////////////////////////////////////////////////////////// + ConvexShape(); + + //////////////////////////////////////////////////////////// + /// \brief Set the number of points of the polygon + /// + /// The default number of points of a polygon is 6. + /// + /// \param count New number of points of the polygon + /// + /// \see GetPointsCount + /// + //////////////////////////////////////////////////////////// + void SetPointsCount(unsigned int count); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points of the polygon + /// + /// \return Number of points of the polygon + /// + /// \see SetPointsCount + /// + //////////////////////////////////////////////////////////// + unsigned int GetPointsCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the position of a point + /// + /// Don't forget that the polygon must remain convex, and + /// the points need to stay ordered! + /// + /// \param index Index of the point to change + /// \param point New position of the point + /// + /// \see GetPoint + /// + //////////////////////////////////////////////////////////// + void SetPoint(unsigned int index, const Vector2f& point); + + //////////////////////////////////////////////////////////// + /// \brief Get the position of a point + /// + /// \param index Index of the point to get + /// + /// \return Position of the index-th point of the polygon + /// + /// \see SetPoint + /// + //////////////////////////////////////////////////////////// + Vector2f GetPoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points defining the shape + /// + /// \return Number of points of the shape + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetOutlinePointsCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// \param index Index of the point to get + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f GetOutlinePoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector myPoints; ///< Points composing the convex polygon +}; + +} // namespace sf + + +#endif // SFML_CONVEXSHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::ConvexShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// It is important to keep in mind that a convex shape must +/// always be... convex, otherwise it may not be drawn correctly. +/// Moreover, the points must be defined in order; using a random +/// order would result in an incorrect shape. +/// +/// Usage example: +/// \code +/// sf::ConvexShape polygon; +/// polygon.SetPointsCount(3); +/// polygon.SetPoint(0, sf::Vector2f(0, 0)); +/// polygon.SetPoint(1, sf::Vector2f(0, 10)); +/// polygon.SetPoint(2, sf::Vector2f(25, 5)); +/// polygon.SetOutlineColor(sf::Color::Red); +/// polygon.SetOutlineThickness(5); +/// polygon.SetPosition(10, 20); +/// ... +/// window.Draw(polygon); +/// \endcode +/// +/// \see sf::Shape, sf::StarShape, sf::RectangleShape, sf::CircleShape +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Drawable.hpp b/include/SFML/Graphics/Drawable.hpp index fbee1be85..707068fd3 100644 --- a/include/SFML/Graphics/Drawable.hpp +++ b/include/SFML/Graphics/Drawable.hpp @@ -28,32 +28,14 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include -#include -#include +#include +#include namespace sf { -class Renderer; class RenderTarget; -namespace Blend -{ - //////////////////////////////////////////////////////////// - /// \ingroup graphics - /// \brief Available blending modes for drawable objects - /// - //////////////////////////////////////////////////////////// - enum Mode - { - Alpha, ///< Pixel = Src * Src.a + Dest * (1 - Src.a) - Add, ///< Pixel = Src + Dest - Multiply, ///< Pixel = Src * Dest - None ///< Pixel = Src - }; -} - //////////////////////////////////////////////////////////// /// \brief Abstract base class for objects that can be drawn /// to a render target @@ -67,449 +49,24 @@ public : /// \brief Virtual destructor /// //////////////////////////////////////////////////////////// - virtual ~Drawable(); - - //////////////////////////////////////////////////////////// - /// \brief Set the position of the object - /// - /// This function completely overwrites the previous position. - /// See Move to apply an offset based on the previous position instead. - /// The default position of a drawable object is (0, 0). - /// - /// \param x X coordinate of the new position - /// \param y Y coordinate of the new position - /// - /// \see Move, SetX, SetY, GetPosition - /// - //////////////////////////////////////////////////////////// - void SetPosition(float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Set the position of the object - /// - /// This function completely overwrites the previous position. - /// See Move to apply an offset based on the previous position instead. - /// The default position of a drawable object is (0, 0). - /// - /// \param position New position - /// - /// \see Move, SetX, SetY, GetPosition - /// - //////////////////////////////////////////////////////////// - void SetPosition(const Vector2f& position); - - //////////////////////////////////////////////////////////// - /// \brief Set the X position of the object - /// - /// \param x New X coordinate - /// - /// \see SetY, SetPosition, GetPosition - /// - //////////////////////////////////////////////////////////// - void SetX(float x); - - //////////////////////////////////////////////////////////// - /// \brief Set the Y position of the object - /// - /// \param y New Y coordinate - /// - /// \see SetX, SetPosition, GetPosition - /// - //////////////////////////////////////////////////////////// - void SetY(float y); - - //////////////////////////////////////////////////////////// - /// \brief Set the scale factors of the object - /// - /// \a factorX and \a factorY must be strictly positive, - /// otherwise they are ignored. - /// This function completely overwrites the previous scale. - /// See Scale to add a factor based on the previous scale instead. - /// The default scale of a drawable object is (1, 1). - /// - /// \param factorX New horizontal scale factor - /// \param factorY New vertical scale factor - /// - /// \see Scale, SetScaleX, SetScaleY, GetScale - /// - //////////////////////////////////////////////////////////// - void SetScale(float factorX, float factorY); - - //////////////////////////////////////////////////////////// - /// \brief Set the scale factors of the object - /// - /// \a scale.x and \a scale.y must be strictly positive, - /// otherwise they are ignored. - /// This function completely overwrites the previous scale. - /// See Scale to add a factor based on the previous scale instead. - /// The default scale of a drawable object is (1, 1). - /// - /// \param factors New scale factors - /// - /// \see Scale, SetScaleX, SetScaleY, GetScale - /// - //////////////////////////////////////////////////////////// - void SetScale(const Vector2f& factors); - - //////////////////////////////////////////////////////////// - /// \brief Set the X scale factor of the object - /// - /// \a factor must be strictly positive, otherwise it is ignored. - /// - /// \param factor New horizontal scale factor - /// - /// \see SetScaleY, SetScale, GetScale - /// - //////////////////////////////////////////////////////////// - void SetScaleX(float factor); - - //////////////////////////////////////////////////////////// - /// \brief Set the Y scale factor of the object - /// - /// \a factor must be strictly positive, otherwise it is ignored. - /// - /// \param factor New vertical scale factor - /// - /// \see SetScaleX, SetScale, GetScale - /// - //////////////////////////////////////////////////////////// - void SetScaleY(float factor); - - //////////////////////////////////////////////////////////// - /// \brief Set the local origin of the object - /// - /// The origin of an object defines the center point for - /// all transformations (position, scale, rotation). - /// The coordinates of this point must be relative to the - /// top-left corner of the object, and ignore all - /// transformations (position, scale, rotation). - /// The default origin of a drawable object is (0, 0). - /// - /// \param x X coordinate of the new origin - /// \param y Y coordinate of the new origin - /// - /// \see GetOrigin - /// - //////////////////////////////////////////////////////////// - void SetOrigin(float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Set the local origin of the object - /// - /// The origin of an object defines the center point for - /// all transformations (position, scale, rotation). - /// The coordinates of this point must be relative to the - /// top-left corner of the object, and ignore all - /// transformations (position, scale, rotation). - /// The default origin of a drawable object is (0, 0). - /// - /// \param origin New origin - /// - /// \see GetOrigin - /// - //////////////////////////////////////////////////////////// - void SetOrigin(const Vector2f& origin); - - //////////////////////////////////////////////////////////// - /// \brief Set the orientation of the object - /// - /// This function completely overwrites the previous rotation. - /// See Rotate to add an angle based on the previous rotation instead. - /// The default rotation of a drawable object is 0. - /// - /// \param angle New rotation, in degrees - /// - /// \see Rotate, GetRotation - /// - //////////////////////////////////////////////////////////// - void SetRotation(float angle); - - //////////////////////////////////////////////////////////// - /// \brief Set the global color of the object - /// - /// This global color affects the entire object, and modulates - /// (multiplies) its original pixels. - /// The default color is white. - /// - /// \param color New color - /// - /// \see GetColor - /// - //////////////////////////////////////////////////////////// - void SetColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Set the blending mode of the object - /// - /// This property defines how the pixels of an object are - /// blended with the pixels of the render target to which - /// it is drawn. To know more about the blending modes - /// available, see the sf::Blend::Mode enum. - /// The default blend mode is Blend::Alpha. - /// - /// \param mode New blending mode - /// - /// \see GetBlendMode - /// - //////////////////////////////////////////////////////////// - void SetBlendMode(Blend::Mode mode); - - //////////////////////////////////////////////////////////// - /// \brief Get the position of the object - /// - /// \return Current position - /// - /// \see SetPosition - /// - //////////////////////////////////////////////////////////// - const Vector2f& GetPosition() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the current scale of the object - /// - /// \return Current scale factors - /// - /// \see SetScale - /// - //////////////////////////////////////////////////////////// - const Vector2f& GetScale() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the local origin of the object - /// - /// \return Current origin - /// - /// \see SetOrigin - /// - //////////////////////////////////////////////////////////// - const Vector2f& GetOrigin() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the orientation of the object - /// - /// The rotation is always in the range [0, 360]. - /// - /// \return Current rotation, in degrees - /// - /// \see SetRotation - /// - //////////////////////////////////////////////////////////// - float GetRotation() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the color of the object - /// - /// \return Current color - /// - /// \see SetColor - /// - //////////////////////////////////////////////////////////// - const Color& GetColor() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the blend mode of the object - /// - /// \return Current blend mode - /// - /// \see SetBlendMode - /// - //////////////////////////////////////////////////////////// - Blend::Mode GetBlendMode() const; - - //////////////////////////////////////////////////////////// - /// \brief Move the object by a given offset - /// - /// This function adds to the current position of the object, - /// unlike SetPosition which overwrites it. - /// Thus, it is equivalent to the following code: - /// \code - /// sf::Vector2f pos = object.GetPosition(); - /// object.SetPosition(pos.x + offsetX, pos.y + offsetY); - /// \endcode - /// - /// \param offsetX X offset - /// \param offsetY Y offset - /// - /// \see SetPosition - /// - //////////////////////////////////////////////////////////// - void Move(float offsetX, float offsetY); - - //////////////////////////////////////////////////////////// - /// \brief Move the object by a given offset - /// - /// This function adds to the current position of the object, - /// unlike SetPosition which overwrites it. - /// Thus, it is equivalent to the following code: - /// \code - /// object.SetPosition(object.GetPosition() + offset); - /// \endcode - /// - /// \param offset Offset - /// - /// \see SetPosition - /// - //////////////////////////////////////////////////////////// - void Move(const Vector2f& offset); - - //////////////////////////////////////////////////////////// - /// \brief Scale the object - /// - /// This function multiplies the current scale of the object, - /// unlike SetScale which overwrites it. - /// Thus, it is equivalent to the following code: - /// \code - /// sf::Vector2f scale = object.GetScale(); - /// object.SetScale(scale.x * factorX, scale.y * factorY); - /// \endcode - /// - /// \param factorX Horizontal scale factor - /// \param factorY Vertical scale factor - /// - /// \see SetScale - /// - //////////////////////////////////////////////////////////// - void Scale(float factorX, float factorY); - - //////////////////////////////////////////////////////////// - /// \brief Scale the object - /// - /// This function multiplies the current scale of the object, - /// unlike SetScale which overwrites it. - /// Thus, it is equivalent to the following code: - /// \code - /// sf::Vector2f scale = object.GetScale(); - /// object.SetScale(scale.x * factor.x, scale.y * factor.y); - /// \endcode - /// - /// \param factor Scale factors - /// - /// \see SetScale - /// - //////////////////////////////////////////////////////////// - void Scale(const Vector2f& factor); - - //////////////////////////////////////////////////////////// - /// \brief Rotate the object - /// - /// This function ads to the current rotation of the object, - /// unlike SetRotation which overwrites it. - /// Thus, it is equivalent to the following code: - /// \code - /// object.SetRotation(object.GetRotation() + angle); - /// \endcode - /// - /// \param angle Angle of rotation, in degrees - /// - //////////////////////////////////////////////////////////// - void Rotate(float angle); - - //////////////////////////////////////////////////////////// - /// \brief Transform a point in object local coordinates - /// - /// This function takes a point in global coordinates, and - /// transforms it in coordinates local to the object. - /// In other words, it applies the inverse of all the - /// transformations applied to the object (origin, - /// translation, rotation and scale). - /// - /// \param point Point to transform - /// - /// \return The transformed point - /// - /// \see TransformToGlobal - /// - //////////////////////////////////////////////////////////// - Vector2f TransformToLocal(const Vector2f& point) const; - - //////////////////////////////////////////////////////////// - /// \brief Transform a local point in global coordinates - /// - /// This function takes a point in local coordinates, and - /// transforms it in global coordinates. In other words, - /// it applies the same transformations that are applied - /// to the object (origin, translation, rotation and scale). - /// - /// \param point Point to transform - /// - /// \return The transformed point - /// - /// \see TransformToLocal - /// - //////////////////////////////////////////////////////////// - Vector2f TransformToGlobal(const Vector2f& point) const; - -protected : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Drawable(); - - //////////////////////////////////////////////////////////// - /// \brief Get the transform matrix of the object - /// - /// \return Transform matrix - /// - /// \see GetInverseMatrix - /// - //////////////////////////////////////////////////////////// - const Matrix3& GetMatrix() const; - - //////////////////////////////////////////////////////////// - /// \brief Get the inverse transform matrix of the object - /// - /// \return Inverse transform matrix - /// - /// \see GetMatrix - /// - //////////////////////////////////////////////////////////// - const Matrix3& GetInverseMatrix() const; + virtual ~Drawable() {} private : friend class RenderTarget; - //////////////////////////////////////////////////////////// - /// \brief Draw the object to a render target - /// - /// This function applies the common states of the object, - /// then calls the virtual Render functions to let the derived - /// class draw the geometry of the object. - /// - /// \param target Render target - /// \param renderer Renderer providing low-level rendering commands - /// - //////////////////////////////////////////////////////////// - void Draw(RenderTarget& target, Renderer& renderer) const; - //////////////////////////////////////////////////////////// /// \brief Draw the object to a render target /// /// This is a pure virtual function that has to be implemented /// by the derived class to define how the drawable should be - /// rendered. + /// drawn. /// - /// \param target Render target - /// \param renderer Renderer providing low-level rendering commands + /// \param target Render target to draw to + /// \param states Current render states /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target, Renderer& renderer) const = 0; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Vector2f myPosition; ///< Position of the object on screen - Vector2f myScale; ///< Scale of the object - Vector2f myOrigin; ///< Origin of translation / rotation / scaling of the object - float myRotation; ///< Orientation of the object, in degrees - Color myColor; ///< Overlay color of the object - Blend::Mode myBlendMode; ///< Blending mode - mutable Matrix3 myMatrix; ///< Precomputed transform matrix gathering the translation / rotation / scale / center - mutable Matrix3 myInvMatrix; ///< Precomputed inverse transform matrix gathering the translation / rotation / scale / center - mutable bool myMatrixUpdated; ///< Do we need to recompute the transform matrix ? - mutable bool myInvMatrixUpdated; ///< Do we need to recompute the inverse transform matrix ? + virtual void Draw(RenderTarget& target, RenderStates states) const = 0; }; } // namespace sf @@ -522,44 +79,16 @@ private : /// \class sf::Drawable /// \ingroup graphics /// -/// sf::Drawable defines the attributes and operations that -/// are common to all the drawable classes: -/// \li transformations (position, rotation, scale, local origin) -/// \li global overlay color -/// \li blending mode with background pixels -/// \li the ability to be drawn on a sf::RenderTarget (either RenderWindow or RenderTexture) +/// sf::Drawable is a very simple base class that allows objects +/// of derived classes to be drawn to a sf::RenderTarget. /// -/// Please note that all these attributes are hardware accelerated, -/// therefore they are extremely cheap to use (unlike older -/// libraries that perform slow transformations on the CPU, such as -/// rotation or scale). +/// All you have to do in your derived class is to override the +/// Draw virtual function. /// -/// Usage example: -/// \code -/// // Here we'll use a sf::Sprite to demonstrate the features of sf::Drawable -/// sf::Sprite drawable = /* ...whatever... */; -/// -/// drawable.SetOrigin(10, 20); // set its origin to the local point (10, 20) -/// drawable.SetPosition(100, 100); // set its position to (100, 100) -/// drawable.SetRotation(45); // set its orientation to 45 degrees -/// drawable.SetColor(sf::Color::Red); // set its global color to red -/// drawable.SetBlendingMode(sf::Blend::Add); // set an additive blend mode -/// -/// window.Draw(drawable); // finally draw it (window is a sf::RenderWindow) -/// \endcode -/// -/// Deriving your own class from sf::Drawable is possible, however -/// you have to use the sf::Renderer class instead of direct OpenGL -/// calls, which is more limited. To create a derived drawable class, -/// all you have to do is to override the virtual Render function. -/// -/// One of the main benefits of creating your own drawable class is -/// that you can build hierarchies of drawable objects. Indeed, -/// when you draw a drawable inside the Render function of another -/// drawable, the former inherits the transformations and color of -/// the latter and combines them with its own attributes. -/// This way, you can apply global transformations/color to a set -/// of drawables as if it was a single entity. +/// Note that inheriting from sf::Drawable is not mandatory, +/// but it allows this nice syntax "window.Draw(object)" rather +/// than "object.Draw(window)", which is more consistent with other +/// SFML classes. /// /// Example: /// \code @@ -571,26 +100,27 @@ private : /// /// private : /// -/// virtual void Render(sf::RenderTarget& target, sf::Renderer& renderer) const +/// virtual void Draw(sf::RenderTarget& target, RenderStates states) const /// { -/// // Low-level geometry rendering -/// renderer.SetTexture(&myTexture); -/// renderer.Begin(sf::Renderer::QuadList); -/// renderer.AddVertex(...); -/// renderer.AddVertex(...); -/// renderer.AddVertex(...); -/// renderer.AddVertex(...); -/// renderer.End(); +/// // You can draw other high-level objects +/// target.Draw(mySprite, states); /// -/// // High-level drawable rendering -/// target.Draw(mySubSprite); +/// // ... or use the low-level API +/// states.Texture = &myTexture; +/// target.Draw(myVertices, states); +/// +/// // ... or draw with OpenGL directly +/// glBegin(GL_QUADS); +/// ... +/// glEnd(); /// } /// +/// sf::Sprite mySprite; /// sf::Texture myTexture; -/// sf::Sprite mySubSprite; +/// sf::VertexArray myVertices; /// }; /// \endcode /// -/// \see sf::Shape, sf::Sprite, sf::Text +/// \see sf::RenderTarget /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Glyph.hpp b/include/SFML/Graphics/Glyph.hpp index c0a4fdaf2..38ff22e7e 100644 --- a/include/SFML/Graphics/Glyph.hpp +++ b/include/SFML/Graphics/Glyph.hpp @@ -51,9 +51,9 @@ public : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - int Advance; ///< Offset to move horizontically to the next character - IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - IntRect SubRect; ///< Texture coordinates of the glyph inside the font's texture + int Advance; ///< Offset to move horizontically to the next character + IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline + IntRect TextureRect; ///< Texture coordinates of the glyph inside the font's texture }; } // namespace sf @@ -71,7 +71,7 @@ public : /// The sf::Glyph structure provides the information needed /// to handle the glyph: /// \li its coordinates in the font's texture -/// \li its bounding rect +/// \li its bounding rectangle /// \li the offset to apply to get the starting position of the next glyph /// /// \see sf::Font diff --git a/include/SFML/Graphics/Matrix3.hpp b/include/SFML/Graphics/Matrix3.hpp deleted file mode 100644 index f2bc76c04..000000000 --- a/include/SFML/Graphics/Matrix3.hpp +++ /dev/null @@ -1,176 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MATRIX3_HPP -#define SFML_MATRIX3_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Utility class to manipulate 3x3 matrices of floats -/// -//////////////////////////////////////////////////////////// -class SFML_API Matrix3 -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// This constructor creates an identity matrix. - /// - //////////////////////////////////////////////////////////// - Matrix3(); - - //////////////////////////////////////////////////////////// - /// \brief Construct a matrix from its 9 elements - /// - /// \param a00 Element (0, 0) of the matrix - /// \param a01 Element (0, 1) of the matrix - /// \param a02 Element (0, 2) of the matrix - /// \param a10 Element (1, 0) of the matrix - /// \param a11 Element (1, 1) of the matrix - /// \param a12 Element (1, 2) of the matrix - /// \param a20 Element (2, 0) of the matrix - /// \param a21 Element (2, 1) of the matrix - /// \param a22 Element (2, 2) of the matrix - /// - //////////////////////////////////////////////////////////// - Matrix3(float a00, float a01, float a02, - float a10, float a11, float a12, - float a20, float a21, float a22); - - //////////////////////////////////////////////////////////// - /// \brief Transform a point by the matrix - /// - /// \param point Point to transform - /// - /// \return Transformed point - /// - //////////////////////////////////////////////////////////// - Vector2f Transform(const Vector2f& point) const; - - //////////////////////////////////////////////////////////// - /// \brief Return the inverse of the matrix - /// - /// If the inverse cannot be computed, the identity matrix - /// is returned. - /// - /// \return A new matrix which is the inverse of self - /// - //////////////////////////////////////////////////////////// - Matrix3 GetInverse() const; - - //////////////////////////////////////////////////////////// - /// \brief Return the elements of the matrix - /// - /// This function returns an array of 16 floats containing - /// the corresponding 4x4 matrix, so that it is directly - /// compatible with OpenGL functions. - /// - /// \return Pointer to the 4x4 matrix elements - /// - //////////////////////////////////////////////////////////// - const float* Get4x4Elements() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of binary operator * - /// - /// \param right Right operand of the multiplication - /// - /// \return New matrix which is the result of self * \a right - /// - //////////////////////////////////////////////////////////// - Matrix3 operator *(const Matrix3& right) const; - - //////////////////////////////////////////////////////////// - /// \brief Build a matrix from a set of transformations - /// - /// \param origin Origin for the transformations - /// \param translation Translation offset - /// \param rotation Rotation angle in degrees - /// \param scale Scaling factors - /// - /// \return New Matrix3 containing the transformations - /// - /// \see Projection - /// - //////////////////////////////////////////////////////////// - static Matrix3 Transformation(const Vector2f& origin, const Vector2f& translation, float rotation, const Vector2f& scale); - - //////////////////////////////////////////////////////////// - /// \brief Build a 2D project matrix - /// - /// \param center Center of the view - /// \param size Size of the view - /// \param rotation Angle of rotation of the view, in degrees - /// - /// \return New Matrix3 containing the projection - /// - /// \see Transformation - /// - //////////////////////////////////////////////////////////// - static Matrix3 Projection(const Vector2f& center, const Vector2f& size, float rotation); - - //////////////////////////////////////////////////////////// - // Static member data - //////////////////////////////////////////////////////////// - static const Matrix3 Identity; ///< The identity matrix - -private : - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - float myData[16]; /// Matrix elements (we directly store it as a 4x4 matrix for optimization purpose) -}; - -#include - -} // namespace sf - - -#endif // SFML_MATRIX3_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Matrix3 -/// \ingroup graphics -/// -/// Matrix3 is only meant for internal use, its interface is -/// limited and its implementation is optimized for OpenGL -/// rendering. -/// -/// This type is not used at all in the public API of SFML. -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Matrix3.inl b/include/SFML/Graphics/Matrix3.inl deleted file mode 100644 index e7f7f629b..000000000 --- a/include/SFML/Graphics/Matrix3.inl +++ /dev/null @@ -1,147 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////// -inline Matrix3::Matrix3() -{ - myData[0] = 1.f; myData[4] = 0.f; myData[8] = 0.f; myData[12] = 0.f; - myData[1] = 0.f; myData[5] = 1.f; myData[9] = 0.f; myData[13] = 0.f; - 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; -} - - -//////////////////////////////////////////////////////////// -inline Matrix3::Matrix3(float a00, float a01, float a02, - float a10, float a11, float a12, - float a20, float a21, float a22) -{ - myData[0] = a00; myData[4] = a01; myData[8] = 0.f; myData[12] = a02; - myData[1] = a10; myData[5] = a11; myData[9] = 0.f; myData[13] = a12; - myData[2] = 0.f; myData[6] = 0.f; myData[10] = 1.f; myData[14] = 0.f; - myData[3] = a20; myData[7] = a21; myData[11] = 0.f; myData[15] = a22; -} - - -//////////////////////////////////////////////////////////// -inline Vector2f Matrix3::Transform(const Vector2f& point) const -{ - return Vector2f(myData[0] * point.x + myData[4] * point.y + myData[12], - myData[1] * point.x + myData[5] * point.y + myData[13]); -} - - -//////////////////////////////////////////////////////////// -inline Matrix3 Matrix3::GetInverse() const -{ - // Compute the determinant - float det = myData[0] * (myData[15] * myData[5] - myData[7] * myData[13]) - - myData[1] * (myData[15] * myData[4] - myData[7] * myData[12]) + - myData[3] * (myData[13] * myData[4] - myData[5] * myData[12]); - - // Compute the inverse if determinant is not zero - if (det != 0.f) // don't use an epsilon because the determinant may *really* be tiny - { - return Matrix3( (myData[15] * myData[5] - myData[7] * myData[13]) / det, - -(myData[15] * myData[4] - myData[7] * myData[12]) / det, - (myData[13] * myData[4] - myData[5] * myData[12]) / det, - -(myData[15] * myData[1] - myData[3] * myData[13]) / det, - (myData[15] * myData[0] - myData[3] * myData[12]) / det, - -(myData[13] * myData[0] - myData[1] * myData[12]) / det, - (myData[7] * myData[1] - myData[3] * myData[5]) / det, - -(myData[7] * myData[0] - myData[3] * myData[4]) / det, - (myData[5] * myData[0] - myData[1] * myData[4]) / det); - } - else - { - return Identity; - } -} - - -//////////////////////////////////////////////////////////// -inline const float* Matrix3::Get4x4Elements() const -{ - return myData; -} - - -//////////////////////////////////////////////////////////// -inline Matrix3 Matrix3::operator *(const Matrix3& right) const -{ - return Matrix3(myData[0] * right.myData[0] + myData[4] * right.myData[1] + myData[12] * right.myData[3], - myData[0] * right.myData[4] + myData[4] * right.myData[5] + myData[12] * right.myData[7], - myData[0] * right.myData[12] + myData[4] * right.myData[13] + myData[12] * right.myData[15], - myData[1] * right.myData[0] + myData[5] * right.myData[1] + myData[13] * right.myData[3], - myData[1] * right.myData[4] + myData[5] * right.myData[5] + myData[13] * right.myData[7], - myData[1] * right.myData[12] + myData[5] * right.myData[13] + myData[13] * right.myData[15], - myData[3] * right.myData[0] + myData[7] * right.myData[1] + myData[15] * right.myData[3], - myData[3] * right.myData[4] + myData[7] * right.myData[5] + myData[15] * right.myData[7], - myData[3] * right.myData[12] + myData[7] * right.myData[13] + myData[15] * right.myData[15]); -} - - -//////////////////////////////////////////////////////////// -inline Matrix3 Matrix3::Transformation(const Vector2f& origin, const Vector2f& translation, float rotation, const Vector2f& scale) -{ - // Combine the transformations - float angle = -rotation * 3.141592654f / 180.f; - float cosine = static_cast(std::cos(angle)); - float sine = static_cast(std::sin(angle)); - float sxCos = scale.x * cosine; - float syCos = scale.y * cosine; - float sxSin = scale.x * sine; - float sySin = scale.y * sine; - float tx = -origin.x * sxCos - origin.y * sySin + translation.x; - float ty = origin.x * sxSin - origin.y * syCos + translation.y; - - // Construct the matrix - return Matrix3( sxCos, sySin, tx, - -sxSin, syCos, ty, - 0.f, 0.f, 1.f); -} - - -//////////////////////////////////////////////////////////// -inline Matrix3 Matrix3::Projection(const Vector2f& center, const Vector2f& size, float rotation) -{ - // Rotation components - float angle = rotation * 3.141592654f / 180.f; - float cosine = static_cast(std::cos(angle)); - float sine = static_cast(std::sin(angle)); - float tx = -center.x * cosine - center.y * sine + center.x; - float ty = center.x * sine - center.y * cosine + center.y; - - // Projection components - float a = 2.f / size.x; - float b = -2.f / size.y; - float c = -a * center.x; - float d = -b * center.y; - - // Rebuild the projection matrix - return Matrix3( a * cosine, a * sine, a * tx + c, - -b * sine, b * cosine, b * ty + d, - 0.f, 0.f, 1.f); -} diff --git a/include/SFML/Graphics/PrimitiveType.hpp b/include/SFML/Graphics/PrimitiveType.hpp new file mode 100644 index 000000000..a7458b8a1 --- /dev/null +++ b/include/SFML/Graphics/PrimitiveType.hpp @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_PRIMITIVETYPE_HPP +#define SFML_PRIMITIVETYPE_HPP + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \ingroup graphics +/// \brief Types of primitives that a sf::VertexArray can render +/// +/// Points and lines have no area, therefore their thickness +/// will always be 1 pixel, regarldess the current transform +/// and view. +/// +//////////////////////////////////////////////////////////// +enum PrimitiveType +{ + Points, ///< List of individual points + Lines, ///< List of individual lines + LinesStrip, ///< List of connected lines, a point uses the previous point to form a line + Triangles, ///< List of individual triangles + TrianglesStrip, ///< List of connected triangles, a point uses the two previous points to form a triangle + TrianglesFan, ///< List of connected triangles, a point uses the common center and the previous point to form a triangle + Quads ///< List of individual quads +}; + +} // namespace sf + + +#endif // SFML_PRIMITIVETYPE_HPP diff --git a/include/SFML/Graphics/Rect.hpp b/include/SFML/Graphics/Rect.hpp index 9bb3f0391..0f7b1c089 100644 --- a/include/SFML/Graphics/Rect.hpp +++ b/include/SFML/Graphics/Rect.hpp @@ -154,6 +154,36 @@ public : T Height; ///< Height of the rectangle }; +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator == +/// +/// This operator compares strict equality between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator ==(const Rect& left, const Rect& right); + +//////////////////////////////////////////////////////////// +/// \relates Rect +/// \brief Overload of binary operator != +/// +/// This operator compares strict difference between two rectangles. +/// +/// \param left Left operand (a rectangle) +/// \param right Right operand (a rectangle) +/// +/// \return True if \a left is not equal to \a right +/// +//////////////////////////////////////////////////////////// +template +bool operator !=(const Rect& left, const Rect& right); + #include // Create typedefs for the most common types diff --git a/include/SFML/Graphics/Rect.inl b/include/SFML/Graphics/Rect.inl index 986885119..e978758f4 100644 --- a/include/SFML/Graphics/Rect.inl +++ b/include/SFML/Graphics/Rect.inl @@ -118,3 +118,21 @@ bool Rect::Intersects(const Rect& rectangle, Rect& intersection) const return false; } } + + +//////////////////////////////////////////////////////////// +template +inline bool operator ==(const Rect& left, const Rect& right) +{ + return (left.Left == right.Left) && (left.Width == right.Width) && + (left.Top == right.Top) && (left.Height == right.Height); +} + + +//////////////////////////////////////////////////////////// +template +inline bool operator !=(const Rect& left, const Rect& right) +{ + return (left.Left != right.Left) || (left.Width != right.Width) || + (left.Top != right.Top) || (left.Height != right.Height); +} diff --git a/include/SFML/Graphics/RectangleShape.hpp b/include/SFML/Graphics/RectangleShape.hpp new file mode 100644 index 000000000..0e9393f9e --- /dev/null +++ b/include/SFML/Graphics/RectangleShape.hpp @@ -0,0 +1,129 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RECTANGLESHAPE_HPP +#define SFML_RECTANGLESHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a rectangle +/// +//////////////////////////////////////////////////////////// +class SFML_API RectangleShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a 10x10 rectangle. + /// + //////////////////////////////////////////////////////////// + RectangleShape(); + + //////////////////////////////////////////////////////////// + /// \brief Set the size of the rectangle + /// + /// The default size of a rectangle is 10x10. + /// + /// \param size New size of the rectangle + /// + /// \see GetSize + /// + //////////////////////////////////////////////////////////// + void SetSize(const Vector2f& size); + + //////////////////////////////////////////////////////////// + /// \brief Get the size of the rectangle + /// + /// \return Size of the rectangle + /// + /// \see SetSize + /// + //////////////////////////////////////////////////////////// + const Vector2f& GetSize() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points defining the shape + /// + /// \return Number of points of the shape + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetOutlinePointsCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// \param index Index of the point to get + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f GetOutlinePoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f mySize; ///< Size of the rectangle +}; + +} // namespace sf + + +#endif // SFML_RECTANGLESHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RectangleShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// Usage example: +/// \code +/// sf::RectangleShape rectangle; +/// rectangle.SetSize(sf::Vector2f(100, 50)); +/// rectangle.SetOutlineColor(sf::Color::Red); +/// rectangle.SetOutlineThickness(5); +/// rectangle.SetPosition(10, 20); +/// ... +/// window.Draw(rectangle); +/// \endcode +/// +/// \see sf::Shape, sf::StarShape, sf::CircleShape, sf::ConvexShape +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderStates.hpp b/include/SFML/Graphics/RenderStates.hpp new file mode 100644 index 000000000..13d09d998 --- /dev/null +++ b/include/SFML/Graphics/RenderStates.hpp @@ -0,0 +1,173 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_RENDERSTATES_HPP +#define SFML_RENDERSTATES_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +class Shader; +class Texture; + +//////////////////////////////////////////////////////////// +/// \brief Define the states used for drawing to a RenderTarget +/// +//////////////////////////////////////////////////////////// +class SFML_API RenderStates +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Constructing a default set of render states is equivalent + /// to using sf::RenderStates::Default. + /// The default set defines: + /// \li the BlendAlpha blend mode + /// \li the identity transform + /// \li a null texture + /// \li a null shader + /// + //////////////////////////////////////////////////////////// + RenderStates(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom blend mode + /// + /// \param blendMode Blend mode to use + /// + //////////////////////////////////////////////////////////// + RenderStates(sf::BlendMode blendMode); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom transform + /// + /// \param transform Transform to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const sf::Transform& transform); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom texture + /// + /// \param texture Texture to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const sf::Texture* texture); + + //////////////////////////////////////////////////////////// + /// \brief Construct a default set of render states with a custom shader + /// + /// \param shader Shader to use + /// + //////////////////////////////////////////////////////////// + RenderStates(const sf::Shader* shader); + + //////////////////////////////////////////////////////////// + /// \brief Construct a set of render states with all its attributes + /// + /// \param blendMode Blend mode to use + /// \param transform Transform to use + /// \param texture Texture to use + /// \param shader Shader to use + /// + //////////////////////////////////////////////////////////// + RenderStates(sf::BlendMode blendMode, const sf::Transform& transform, + const sf::Texture* texture, const sf::Shader* shader); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const RenderStates Default; ///< Special instance holding the default render states + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + sf::BlendMode BlendMode; ///< Blending mode + sf::Transform Transform; ///< Transform + const sf::Texture* Texture; ///< Texture + const sf::Shader* Shader; ///< Shader +}; + +} // namespace sf + + +#endif // SFML_RENDERSTATES_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::RenderStates +/// \ingroup graphics +/// +/// There are four global states that can be applied to +/// the drawn objects: +/// \li the blend mode: how pixels of the object are blended with the background +/// \li the transform: how the object is positioned/rotated/scaled +/// \li the texture: what image is mapped to the object +/// \li the shader: what custom effect is applied to the object +/// +/// High-level objects such as sprites or text force some of +/// these states when they are drawn. For example, a sprite +/// will set its own texture, so that you don't have to care +/// about it when drawing the sprite. +/// +/// The transform is a special case: sprites, texts and shapes +/// (and it's a good idea to do it with your own drawable classes +/// too) combine their transform with the one that is passed in the +/// RenderStates structure. So that you can use a "global" transform +/// on top of each object's transform. +/// +/// Most objects, especially high-level drawables, can be drawn +/// directly without defining render states explicitely -- the +/// default set of states is ok in most cases. +/// \code +/// window.Draw(sprite); +/// \endcode +/// +/// If you want to use a single specific render state, +/// for example a shader, you can pass it directly to the Draw +/// function: sf::RenderStates has an implicit one-argument +/// constructor for each state. +/// \code +/// window.Draw(sprite, shader); +/// \endcode +/// +/// When you're inside the Draw function of a drawable +/// object (inherited from sf::Drawable), you can +/// either pass the render states unmodified, or change +/// some of them. +/// For example, a transformable object will combine the +/// current transform with its own transform. A sprite will +/// set its texture. Etc. +/// +/// \see sf::RenderTarget, sf::Drawable +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp index 961a26a21..548c09dff 100644 --- a/include/SFML/Graphics/RenderTarget.hpp +++ b/include/SFML/Graphics/RenderTarget.hpp @@ -31,14 +31,17 @@ #include #include #include -#include #include +#include +#include +#include +#include namespace sf { class Drawable; -class Shader; +class Vertex; //////////////////////////////////////////////////////////// /// \brief Base class for all render targets (window, texture, ...) @@ -65,61 +68,17 @@ public : //////////////////////////////////////////////////////////// void Clear(const Color& color = Color(0, 0, 0, 255)); - //////////////////////////////////////////////////////////// - /// \brief Draw an object into the target - /// - /// This function draws anything that inherits from the - /// sf::Drawable base class (sf::Sprite, sf::Shape, sf::Text, - /// or even your own derived classes). - /// - /// \param object Object to draw - /// - //////////////////////////////////////////////////////////// - void Draw(const Drawable& object); - - //////////////////////////////////////////////////////////// - /// \brief Draw an object into the target with a shader - /// - /// This function draws anything that inherits from the - /// sf::Drawable base class (sf::Sprite, sf::Shape, sf::Text, - /// or even your own derived classes). - /// The shader alters the way that the pixels are processed - /// right before being written to the render target. - /// - /// \param object Object to draw - /// \param shader Shader to use for drawing the object - /// - //////////////////////////////////////////////////////////// - void Draw(const Drawable& object, const Shader& shader); - - //////////////////////////////////////////////////////////// - /// \brief Return the width of the rendering region of the target - /// - /// \return Width in pixels - /// - /// \see GetHeight - /// - //////////////////////////////////////////////////////////// - virtual unsigned int GetWidth() const = 0; - - //////////////////////////////////////////////////////////// - /// \brief Return the height of the rendering region of the target - /// - /// \return Height in pixels - /// - /// \see GetWidth - /// - //////////////////////////////////////////////////////////// - virtual unsigned int GetHeight() const = 0; - //////////////////////////////////////////////////////////// /// \brief Change the current active view /// + /// The view is like a 2D camera, it controls which part of + /// the 2D scene is visible, and how it is viewed in the + /// render-target. /// The new view will affect everything that is drawn, until - /// another view is activated. + /// another view is set. /// The render target keeps its own copy of the view object, /// so it is not necessary to keep the original one alive - /// as long as it is in use. + /// after calling this function. /// To restore the original view of the target, you can pass /// the result of GetDefaultView() to this function. /// @@ -131,7 +90,7 @@ public : void SetView(const View& view); //////////////////////////////////////////////////////////// - /// \brief Retrieve the view currently in use in the render target + /// \brief Get the view currently in use in the render target /// /// \return The view object that is currently used /// @@ -218,11 +177,52 @@ public : //////////////////////////////////////////////////////////// Vector2f ConvertCoords(unsigned int x, unsigned int y, const View& view) const; + //////////////////////////////////////////////////////////// + /// \brief Draw a drawable object to the render-target + /// + /// \param drawable Object to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void Draw(const Drawable& drawable, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Draw primitives defined by an array of vertices + /// + /// \param vertices Pointer to the vertices + /// \param verticesCount Number of vertices in the array + /// \param type Type of primitives to draw + /// \param states Render states to use for drawing + /// + //////////////////////////////////////////////////////////// + void Draw(const Vertex* vertices, unsigned int verticesCount, + PrimitiveType type, const RenderStates& states = RenderStates::Default); + + //////////////////////////////////////////////////////////// + /// \brief Return the width of the rendering region of the target + /// + /// \return Width in pixels + /// + /// \see GetHeight + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetWidth() const = 0; + + //////////////////////////////////////////////////////////// + /// \brief Return the height of the rendering region of the target + /// + /// \return Height in pixels + /// + /// \see GetWidth + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetHeight() const = 0; + //////////////////////////////////////////////////////////// /// \brief Save the current OpenGL render states and matrices /// /// This function can be used when you mix SFML drawing - /// and direct OpenGL rendering. Combined with RestoreGLStates, + /// and direct OpenGL rendering. Combined with PopGLStates, /// it ensures that: /// \li SFML's internal states are not messed up by your OpenGL code /// \li your OpenGL states are not modified by a call to a SFML function @@ -231,34 +231,60 @@ public : /// calls Draw functions. Example: /// \code /// // OpenGL code here... - /// window.SaveGLStates(); + /// window.PushGLStates(); /// window.Draw(...); /// window.Draw(...); - /// window.RestoreGLStates(); + /// window.PopGLStates(); /// // OpenGL code here... /// \endcode /// - /// Note that this function is quite expensive and should be - /// used wisely. It is provided for convenience, and the best - /// results will be achieved if you handle OpenGL states - /// yourself (because you really know which states have really - /// changed, and need to be saved / restored). + /// Note that this function is quite expensive: it saves all the + /// possible OpenGL states and matrices, even the ones you + /// don't care about. Therefore it should be used wisely. + /// It is provided for convenience, but the best results will + /// be achieved if you handle OpenGL states yourself (because + /// you know which states have really changed, and need to be + /// saved and restored). Take a look at the ResetGLStates + /// function if you do so. /// - /// \see RestoreGLStates + /// \see PopGLStates /// //////////////////////////////////////////////////////////// - void SaveGLStates(); + void PushGLStates(); //////////////////////////////////////////////////////////// /// \brief Restore the previously saved OpenGL render states and matrices /// - /// See the description of SaveGLStates to get a detailed + /// See the description of PushGLStates to get a detailed /// description of these functions. /// - /// \see SaveGLStates + /// \see PushGLStates /// //////////////////////////////////////////////////////////// - void RestoreGLStates(); + void PopGLStates(); + + //////////////////////////////////////////////////////////// + /// \brief Reset the internal OpenGL states so that the target is ready for drawing + /// + /// This function can be used when you mix SFML drawing + /// and direct OpenGL rendering, if you choose not to use + /// PushGLStates/PopGLStates. It makes sure that all OpenGL + /// states needed by SFML are set, so that subsequent Draw() + /// calls will work as expected. + /// + /// Example: + /// \code + /// // OpenGL code here... + /// glPushAttrib(...); + /// window.ResetGLStates(); + /// window.Draw(...); + /// window.Draw(...); + /// glPopAttrib(...); + /// // OpenGL code here... + /// \endcode + /// + //////////////////////////////////////////////////////////// + void ResetGLStates(); protected : @@ -296,11 +322,9 @@ private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Renderer myRenderer; ///< Renderer that will process the rendering commands of the window - View myDefaultView; ///< Default view - View myCurrentView; ///< Current active view - bool myStatesSaved; ///< Are we between a SaveGLStates and a RestoreGLStates? - bool myViewHasChanged; ///< Has the current view changed? + View myDefaultView; ///< Default view + View myView; ///< Current view + bool myViewChanged; ///< Has the current view changed since last Draw? }; } // namespace sf @@ -328,8 +352,8 @@ private : /// On top of that, render targets are still able to render direct /// OpenGL stuff. It is even possible to mix together OpenGL calls /// and regular SFML drawing commands. When doing so, make sure that -/// OpenGL states are not messed up by calling the SaveGLStates / -/// RestoreGLStates functions. +/// OpenGL states are not messed up by calling the +/// PushGLStates/PopGLStates functions. /// /// \see sf::RenderWindow, sf::RenderTexture, sf::View /// diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index b6263d7f0..3f5ceaa0c 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -188,15 +188,14 @@ private : /// classes of the graphics module. /// /// sf::RenderWindow is derived from sf::Window, thus it inherits -/// all its features: mouse/keyboard/joystick input, events, window -/// handling, OpenGL rendering, etc. See the documentation of -/// sf::Window for a more complete description of all these features -/// and code samples. +/// all its features: events, window management, OpenGL rendering, +/// etc. See the documentation of sf::Window for a more complete +/// description of all these features, as well as code examples. /// /// On top of that, sf::RenderWindow adds more features related to /// 2D drawing with the graphics module (see its base class /// sf::RenderTarget for more details). -/// Here is a typical rendering / event loop with a sf::RenderWindow: +/// Here is a typical rendering and event loop with a sf::RenderWindow: /// /// \code /// // Declare and create a new render-window @@ -220,10 +219,10 @@ private : /// // Clear the whole window before rendering a new frame /// window.Clear(); /// -/// // Draw some sprites / shapes / texts -/// window.Draw(sprite); // sprite is a sf::Sprite -/// window.Draw(shape); // shape is a sf::Shape -/// window.Draw(text); // text is a sf::Text +/// // Draw some graphical entities +/// window.Draw(sprite); +/// window.Draw(circle); +/// window.Draw(text); /// /// // End the current frame and display its contents on screen /// window.Display(); @@ -232,9 +231,7 @@ private : /// /// Like sf::Window, sf::RenderWindow is still able to render direct /// OpenGL stuff. It is even possible to mix together OpenGL calls -/// and regular SFML drawing commands. When doing so, make sure that -/// OpenGL states are not messed up by calling the SaveGLStates / -/// RestoreGLStates functions. +/// and regular SFML drawing commands. /// /// \code /// // Create the render window @@ -256,9 +253,9 @@ private : /// ... /// /// // Draw a background sprite -/// window.SaveGLStates(); +/// window.PushGLStates(); /// window.Draw(sprite); -/// window.RestoreGLStates(); +/// window.PopGLStates(); /// /// // Draw a 3D object using OpenGL /// glBegin(GL_QUADS); @@ -267,9 +264,9 @@ private : /// glEnd(); /// /// // Draw text on top of the 3D object -/// window.SaveGLStates(); +/// window.PushGLStates(); /// window.Draw(text); -/// window.RestoreGLStates(); +/// window.PopGLStates(); /// /// // Finally, display the rendered frame on screen /// window.Display(); diff --git a/include/SFML/Graphics/Renderer.hpp b/include/SFML/Graphics/Renderer.hpp deleted file mode 100644 index 4d774c804..000000000 --- a/include/SFML/Graphics/Renderer.hpp +++ /dev/null @@ -1,363 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_RENDERER_HPP -#define SFML_RENDERER_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include - - -namespace sf -{ -class Shader; -class Texture; - -//////////////////////////////////////////////////////////// -/// \brief Handles the low-level rendering (states and geometry) -/// -//////////////////////////////////////////////////////////// -class SFML_API Renderer : GlResource, NonCopyable -{ -public : - - //////////////////////////////////////////////////////////// - /// \brief Types of primitives to be rendererd - /// - //////////////////////////////////////////////////////////// - enum PrimitiveType - { - TriangleList, ///< Simple list of triangles - TriangleStrip, ///< Triangle strip (consecutive triangles always share two points) - TriangleFan, ///< Triangle fan (one center point + outline points) - QuadList ///< Simple list of quads - }; - -public : - - //////////////////////////////////////////////////////////// - /// \brief Construct the renderer with its owner render target - /// - /// \param target Owner render target - /// - //////////////////////////////////////////////////////////// - Renderer(RenderTarget& target); - - //////////////////////////////////////////////////////////// - /// \brief Initialize the renderer (set the default states, etc.) - /// - //////////////////////////////////////////////////////////// - void Initialize(); - - //////////////////////////////////////////////////////////// - /// \brief Save the current OpenGL render states and matrices - /// - /// \see RestoreGLStates - /// - //////////////////////////////////////////////////////////// - void SaveGLStates(); - - //////////////////////////////////////////////////////////// - /// \brief Restore the previously saved OpenGL render states and matrices - /// - /// \see SaveGLStates - /// - //////////////////////////////////////////////////////////// - void RestoreGLStates(); - - //////////////////////////////////////////////////////////// - /// Clear the color buffer - /// - /// \param color Color to use to clear the color buffer - /// - //////////////////////////////////////////////////////////// - void Clear(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Save the current render states - /// - /// \see PopStates - /// - //////////////////////////////////////////////////////////// - void PushStates(); - - //////////////////////////////////////////////////////////// - /// \brief Restore the previously saved render states - /// - /// \see PushStates - /// - //////////////////////////////////////////////////////////// - void PopStates(); - - //////////////////////////////////////////////////////////// - /// \brief Set a new model-view matrix - /// - /// \param matrix New model-view matrix - /// - /// \see ApplyModelView - /// - //////////////////////////////////////////////////////////// - void SetModelView(const Matrix3& matrix); - - //////////////////////////////////////////////////////////// - /// \brief Combine a new model-view matrix with the current one - /// - /// \param matrix Model-view matrix to combine - /// - /// \see SetModelView - /// - //////////////////////////////////////////////////////////// - void ApplyModelView(const Matrix3& matrix); - - //////////////////////////////////////////////////////////// - /// \brief Set a new projection matrix - /// - /// \param matrix New projection matrix - /// - /// \see ApplyProjection - /// - //////////////////////////////////////////////////////////// - void SetProjection(const Matrix3& matrix); - - //////////////////////////////////////////////////////////// - /// \brief Set the current global color - /// - /// This color will be modulated with each vertex's color. - /// - /// \param color New global color - /// - /// \see ApplyColor - /// - //////////////////////////////////////////////////////////// - void SetColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Modulate the current global color with a new one - /// - /// This color will be modulated with each vertex's color. - /// - /// \param color Color to modulate - /// - /// \see SetColor - /// - //////////////////////////////////////////////////////////// - void ApplyColor(const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Set the current viewport - /// - /// \param viewport New viewport to apply - /// - //////////////////////////////////////////////////////////// - void SetViewport(const IntRect& viewport); - - //////////////////////////////////////////////////////////// - /// \brief Set the current alpha-blending mode - /// - /// \param mode New blending mode - /// - //////////////////////////////////////////////////////////// - void SetBlendMode(Blend::Mode mode); - - //////////////////////////////////////////////////////////// - /// \brief Set the current texture - /// - /// \param texture New texture - /// - //////////////////////////////////////////////////////////// - void SetTexture(const Texture* texture); - - //////////////////////////////////////////////////////////// - /// \brief Set the current shader - /// - /// \param shader New Shader - /// - //////////////////////////////////////////////////////////// - void SetShader(const Shader* shader); - - //////////////////////////////////////////////////////////// - /// \brief Begin rendering a new geometry batch - /// - /// You need to call End() to complete the batch and trigger - /// the actual rendering of the geometry that you passed - /// between Begin() and End(). - /// - /// Usage: - /// \code - /// renderer.Begin(Renderer::TriangleList); - /// renderer.AddVertex(...); - /// renderer.AddVertex(...); - /// renderer.AddVertex(...); - /// renderer.End(); - /// \endcode - /// - /// \param type Type of the primitives that are going to be rendered - /// - /// \see End - /// - //////////////////////////////////////////////////////////// - void Begin(PrimitiveType type); - - //////////////////////////////////////////////////////////// - /// \brief End the current geometry batch and render it - /// - /// \see Begin - /// - //////////////////////////////////////////////////////////// - void End(); - - //////////////////////////////////////////////////////////// - /// \brief Add a new vertex (position only) - /// - /// This function adds a new vertex to the current batch. - /// This is equivalent to calling AddVertex(x, y, 0, 0, Color::White). - /// - /// \param x X coordinate of the vertex - /// \param y Y coordinate of the vertex - /// - //////////////////////////////////////////////////////////// - void AddVertex(float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Add a new vertex (position + texture coordinates) - /// - /// This function adds a new vertex to the current batch. - /// This is equivalent to calling AddVertex(x, y, u, v, Color::White). - /// - /// \param x X coordinate of the vertex - /// \param y Y coordinate of the vertex - /// \param u X texture coordinate of the vertex - /// \param v Y texture coordinate of the vertex - /// - //////////////////////////////////////////////////////////// - void AddVertex(float x, float y, float u, float v); - - //////////////////////////////////////////////////////////// - /// \brief Add a new vertex (position + color) - /// - /// This function adds a new vertex to the current batch. - /// This is equivalent to calling AddVertex(x, y, 0, 0, color). - /// - /// \param x X coordinate of the vertex - /// \param y Y coordinate of the vertex - /// \param color Color of the vertex - /// - //////////////////////////////////////////////////////////// - void AddVertex(float x, float y, const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Add a new vertex (position + texture coordinates + color) - /// - /// This function adds a new vertex to the current batch. - /// - /// \param x X coordinate of the vertex - /// \param y Y coordinate of the vertex - /// \param u X texture coordinate of the vertex - /// \param v Y texture coordinate of the vertex - /// \param color Color of the vertex - /// - //////////////////////////////////////////////////////////// - void AddVertex(float x, float y, float u, float v, const Color& color); - -private : - - //////////////////////////////////////////////////////////// - /// \brief Process a new vertex - /// - /// This function is called by all the public overloads of AddVertex, - /// it processes a new vertex to be rendered. - /// - /// \param x X coordinate of the vertex - /// \param y Y coordinate of the vertex - /// \param u X texture coordinate of the vertex - /// \param v Y texture coordinate of the vertex - /// \param r Red component of the vertex color (normalized) - /// \param g Green component of the vertex color (normalized) - /// \param b Blue component of the vertex color (normalized) - /// \param a Alpha component of the vertex color (normalized) - /// - //////////////////////////////////////////////////////////// - void ProcessVertex(float x, float y, float u, float v, float r, float g, float b, float a); - - //////////////////////////////////////////////////////////// - // Structure holding the render states that can be stacked - //////////////////////////////////////////////////////////// - struct States - { - States() : r(1.f), g(1.f), b(1.f), a(1.f) {} - - Matrix3 modelView; ///< Model-view matrix - float r, g, b, a; ///< Vertex color (normalized components for faster operations) - }; - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - RenderTarget& myTarget; ///< Reference to the render target owning this renderer - States myStatesStack[64]; ///< Stack of render states - States* myStates; ///< Current set of render states - const Texture* myTexture; ///< Current texture - unsigned int myTextureId; ///< Current texture identifier (the sf::Texture instance may be the same, but not the internal OpenGL texture) - const Shader* myShader; ///< Current pixel shader - Blend::Mode myBlendMode; ///< Current blending mode - IntRect myViewport; ///< Current target viewport - bool myTextureIsValid; ///< Is the cached texture valid? (if not, the cached value is ignored) - bool myShaderIsValid; ///< Is the cached shader valid? (if not, the cached value is ignored) - bool myBlendModeIsValid; ///< Is the cached blend mode valid? (if not, the cached value is ignored) - bool myViewportIsValid; ///< Is the cached viewport valid? (if not, the cached value is ignored) -}; - -} // namespace sf - - -#endif // SFML_RENDERER_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Renderer -/// \ingroup graphics -/// -/// sf::Renderer is the abstraction layer between SFML code -/// and the low-level drawing API (OpenGL). It manages -/// render states efficiently, and provides a lightweight -/// abstraction for rendering geometry. -/// -/// The purpose of this class is to provide a single abstract -/// entry point for everything related to low-level rendering. -/// Hiding everything behind sf::Renderer makes optimizing -/// easy, as well as porting to other technologies in the future -/// (like OpenGL ES or OpenGL 3.x). -/// -/// This class is mainly meant for internal usage, you should -/// never care about it unless you write your own sf::Drawable -/// class that uses raw geometry in its Render function. -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Shader.hpp b/include/SFML/Graphics/Shader.hpp index 5f389ff8b..94ce11154 100644 --- a/include/SFML/Graphics/Shader.hpp +++ b/include/SFML/Graphics/Shader.hpp @@ -440,15 +440,20 @@ private : /// window.Draw(sprite, shader); /// \endcode /// +/// ... which is in fact just a shortcut for this: +/// \code +/// sf::RenderStates states; +/// states.Shader = shader; +/// window.Draw(sprite, states); +/// \endcode +/// /// Shaders can be used on any drawable, but they are mainly -/// made for sf::Sprite. Using a shader on a sf::String is more -/// limited, because the texture of the text is not the +/// made for sprites and shapes. Using a shader on a sf::String +/// is more limited, because the texture of the text is not the /// actual text that you see on screen, it is a big texture /// containing all the characters of the font in an arbitrary /// order. Thus, texture lookups on pixels other than the current -/// one may not give you the expected result. Using a shader -/// with sf::Shape is even more limited, as shapes don't use -/// any texture. +/// one may not give you the expected result. /// /// Shaders can also be used to apply global post-effects to the /// current contents of the target (like the old sf::PostFx class @@ -462,7 +467,7 @@ private : /// The first technique is more optimized because it doesn't involve /// retrieving the target's pixels to system memory, but the /// second one doesn't impact the rendering process and can be -/// easily inserted anywhere. +/// easily inserted anywhere without impacting all the code. /// /// Like sf::Texture that can be used as a raw OpenGL texture, /// sf::Shader can also be used directly as a raw fragment diff --git a/include/SFML/Graphics/Shape.hpp b/include/SFML/Graphics/Shape.hpp index a183539a4..e38c1784a 100644 --- a/include/SFML/Graphics/Shape.hpp +++ b/include/SFML/Graphics/Shape.hpp @@ -29,208 +29,155 @@ // Headers //////////////////////////////////////////////////////////// #include +#include +#include #include -#include namespace sf { //////////////////////////////////////////////////////////// -/// \brief A convex, colored polygon with an optional outline +/// \brief Base class for textured shapes with outline /// //////////////////////////////////////////////////////////// -class SFML_API Shape : public Drawable +class SFML_API Shape : public Drawable, public Transformable { public : //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// Creates an empty shape (no point). + /// \brief Virtual destructor /// //////////////////////////////////////////////////////////// - Shape(); + virtual ~Shape(); //////////////////////////////////////////////////////////// - /// \brief Add a new point to the shape + /// \brief Change the source texture of the shape /// - /// The new point is inserted at the end of the shape. + /// The \a texture argument refers to a texture that must + /// exist as long as the shape uses it. Indeed, the shape + /// doesn't store its own copy of the texture, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the source texture is destroyed and the shape tries to + /// use it, the behaviour is undefined. + /// \a texture can be NULL to disable texturing. + /// If \a resetRect is true, the TextureRect property of + /// the shape is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. /// - /// \param x X position of the point - /// \param y Y position of the point - /// \param color Color of the point - /// \param outlineColor Outline color of the point + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? + /// + /// \see GetTexture, SetTextureRect /// //////////////////////////////////////////////////////////// - void AddPoint(float x, float y, const Color& color = Color(255, 255, 255), const Color& outlineColor = Color(0, 0, 0)); + void SetTexture(const Texture* texture, bool resetRect = false); //////////////////////////////////////////////////////////// - /// \brief Add a new point to the shape + /// \brief Set the sub-rectangle of the texture that the shape will display /// - /// The new point is inserted at the end of the shape. + /// The texture rect is useful when you don't want to display + /// the whole texture, but rather a part of it. + /// By default, the texture rect covers the entire texture. /// - /// \param position Position of the point - /// \param color Color of the point - /// \param outlineColor Outline color of the point + /// \param rect Rectangle defining the region of the texture to display + /// + /// \see GetTextureRect, SetTexture /// //////////////////////////////////////////////////////////// - void AddPoint(const Vector2f& position, const Color& color = Color(255, 255, 255), const Color& outlineColor = Color(0, 0, 0)); + void SetTextureRect(const IntRect& rect); //////////////////////////////////////////////////////////// - /// \brief Get the number of points composing the shape + /// \brief Set the fill color of the shape /// - /// \return Total number of points + /// This color is modulated (multiplied) with the shape's + /// texture if any. It can be used to colorize the shape, + /// or change its global opacity. + /// You can use sf::Color::Transparent to make the inside of + /// the shape transparent, and have the outline alone. + /// By default, the shape's fill color is opaque white. + /// + /// \param color New color of the shape + /// + /// \see GetFillColor, SetOutlineColor /// //////////////////////////////////////////////////////////// - unsigned int GetPointsCount() const; + void SetFillColor(const Color& color); //////////////////////////////////////////////////////////// - /// \brief Enable or disable the shape's filling + /// \brief Set the outline color of the shape /// - /// This option is enabled by default. + /// You can use sf::Color::Transparent to disable the outline. + /// By default, the shape's outline color is opaque white. /// - /// \param enable True to enable, false to disable + /// \param color New outline color of the shape /// - /// \see EnableOutline + /// \see GetOutlineColor, SetFillColor /// //////////////////////////////////////////////////////////// - void EnableFill(bool enable); + void SetOutlineColor(const Color& color); //////////////////////////////////////////////////////////// - /// \brief Enable or disable the shape's outline + /// \brief Set the thickness of the shape's outline /// - /// This option is enabled by default. + /// This number cannot be negative. Using zero disables + /// the outline. + /// By default, the outline thickness is 0. /// - /// \param enable True to enable, false to disable + /// \param thickness New outline thickness /// - /// \see EnableFill - /// - //////////////////////////////////////////////////////////// - void EnableOutline(bool enable); - - //////////////////////////////////////////////////////////// - /// \brief Change the position of a point - /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. - /// - /// \param index Index of the point - /// \param position New position of the point - /// - /// \see GetPointPosition, SetPointColor, SetPointOutlineColor - /// - //////////////////////////////////////////////////////////// - void SetPointPosition(unsigned int index, const Vector2f& position); - - //////////////////////////////////////////////////////////// - /// \brief Change the position of a point - /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. - /// - /// \param index Index of the point - /// \param x New X coordinate of the point - /// \param y New Y coordinate of the point - /// - /// \see GetPointPosition, SetPointColor, SetPointOutlineColor - /// - //////////////////////////////////////////////////////////// - void SetPointPosition(unsigned int index, float x, float y); - - //////////////////////////////////////////////////////////// - /// \brief Change the color of a point - /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. - /// - /// \param index Index of the point - /// \param color New color of the point - /// - /// \see GetPointColor, SetPointPosition, SetPointOutlineColor - /// - //////////////////////////////////////////////////////////// - void SetPointColor(unsigned int index, const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Change the outline color of a point - /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. - /// - /// \param index Index of the point - /// \param color New outline color of the point - /// - /// \see GetPointOutlineColor, SetPointPosition, SetPointColor - /// - //////////////////////////////////////////////////////////// - void SetPointOutlineColor(unsigned int index, const Color& color); - - //////////////////////////////////////////////////////////// - /// \brief Change the thickness of the shape outline - /// - /// \param thickness New thickness of the outline - /// - /// \see GetOutlineThickness, EnableOutline + /// \see GetOutlineThickness /// //////////////////////////////////////////////////////////// void SetOutlineThickness(float thickness); //////////////////////////////////////////////////////////// - /// \brief Get the position of a point + /// \brief Get the source texture of the shape /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. + /// If the shape has no source texture, a NULL pointer is returned. + /// The returned pointer is const, which means that you can't + /// modify the texture when you retrieve it with this function. /// - /// \param index Index of the point + /// \return Pointer to the shape's texture /// - /// \return Position of the index-th point - /// - /// \see SetPointPosition, GetPointColor, GetPointOutlineColor + /// \see SetTexture /// //////////////////////////////////////////////////////////// - const Vector2f& GetPointPosition(unsigned int index) const; + const Texture* GetTexture() const; //////////////////////////////////////////////////////////// - /// \brief Get the color of a point + /// \brief Get the sub-rectangle of the texture displayed by the shape /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. + /// \return Texture rectangle of the shape /// - /// \param index Index of the point - /// - /// \return Color of the index-th point - /// - /// \see SetPointColor, GetPointPosition, GetPointOutlineColor + /// \see SetTextureRect /// //////////////////////////////////////////////////////////// - const Color& GetPointColor(unsigned int index) const; + const IntRect& GetTextureRect() const; //////////////////////////////////////////////////////////// - /// \brief Get the outline color of a point + /// \brief Get the fill color of the shape /// - /// Warning: this function doesn't check the validity of - /// \a index, if it is out of bounds (ie. in the range - /// [0, GetPointscount() - 1]) the behaviour is undefined. + /// \return Fill color of the shape /// - /// \param index Index of the point - /// - /// \return Outline color of the index-th point - /// - /// \see SetPointOutlineColor, GetPointPosition, GetPointColor + /// \see SetFillColor /// //////////////////////////////////////////////////////////// - const Color& GetPointOutlineColor(unsigned int index) const; + const Color& GetFillColor() const; //////////////////////////////////////////////////////////// - /// \brief Get the thickness of the shape outline + /// \brief Get the outline color of the shape /// - /// \return Current outline thickness + /// \return Outline color of the shape + /// + /// \see SetOutlineColor + /// + //////////////////////////////////////////////////////////// + const Color& GetOutlineColor() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the outline thickness of the shape + /// + /// \return Outline thickness of the shape /// /// \see SetOutlineThickness /// @@ -238,221 +185,124 @@ public : float GetOutlineThickness() const; //////////////////////////////////////////////////////////// - /// \brief Create a new line + /// \brief Get the local bounding rectangle of the entity /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::Shape line = sf::Shape::Line(0, 0, 10, 20, 2.5f, sf::Color::Green); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. /// - /// \param p1x X coordinate of the start point - /// \param p1y Y coordinate of the start point - /// \param p2x X coordinate of the end point - /// \param p2y Y coordinate of the end point - /// \param thickness Thickness of the line - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Rectangle, Circle + /// \return Local bounding rectangle of the entity /// //////////////////////////////////////////////////////////// - static Shape Line(float p1x, float p1y, float p2x, float p2y, float thickness, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); + FloatRect GetLocalBounds() const; //////////////////////////////////////////////////////////// - /// \brief Create a new line + /// \brief Get the global bounding rectangle of the entity /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::Vector2f start(0, 0); - /// sf::Vector2f end(10, 20); - /// sf::Shape line = sf::Shape::Line(start, end, 2.5f, sf::Color::Green); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. /// - /// \param start Start point - /// \param end End point - /// \param thickness Thickness of the line - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Rectangle, Circle + /// \return Global bounding rectangle of the entity /// //////////////////////////////////////////////////////////// - static Shape Line(const Vector2f& start, const Vector2f& end, float thickness, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); - - //////////////////////////////////////////////////////////// - /// \brief Create a new rectangular shape - /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::Shape rect = sf::Shape::Rectangle(10, 20, 50, 100, sf::Color::Red); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. - /// - /// \param left Left coordinate of the rectangle - /// \param top Top coordinate of the rectangle - /// \param width Width of the rectangle - /// \param height Height of the rectangle - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Line, Circle - /// - //////////////////////////////////////////////////////////// - static Shape Rectangle(float left, float top, float width, float height, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); - - //////////////////////////////////////////////////////////// - /// \brief Create a new rectangular shape - /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::FloatRect source(10, 20, 50, 100); - /// sf::Shape rect = sf::Shape::Rectangle(source, sf::Color::Red); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. - /// - /// \param rectangle Rectangle defining the shape - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Line, Circle - /// - //////////////////////////////////////////////////////////// - static Shape Rectangle(const FloatRect& rectangle, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); - - //////////////////////////////////////////////////////////// - /// \brief Create a new circular shape - /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::Shape circle = sf::Shape::Circle(0, 0, 7, sf::Color::Blue); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. - /// - /// \param x X coordinate of the center - /// \param y Y coordinate of the center - /// \param radius Radius of the circle - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Line, Rectangle - /// - //////////////////////////////////////////////////////////// - static Shape Circle(float x, float y, float radius, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); - - //////////////////////////////////////////////////////////// - /// \brief Create a new circular shape - /// - /// This is a static function that returns a new object, - /// don't try to call it on an existing object to modify it. - /// \code - /// sf::Vector2f center(0, 0); - /// sf::Shape circle = sf::Shape::Circle(center, 7, sf::Color::Blue); - /// \endcode - /// Warning: the position and color that you pass to this function - /// are used to compute the position and color of each point, - /// they have nothing to do with the global position and color - /// of the shape, inherited from sf::Drawable. - /// See the class description for more information about this. - /// - /// \param center Center of the circle - /// \param radius Radius of the circle - /// \param color Color of the shape's points - /// \param outline Outline thickness - /// \param outlineColor Outline color of the shape's points - /// - /// \see Line, Rectangle - /// - //////////////////////////////////////////////////////////// - static Shape Circle(const Vector2f& center, float radius, const Color& color, float outline = 0.f, const Color& outlineColor = Color(0, 0, 0)); + FloatRect GetGlobalBounds() const; protected : //////////////////////////////////////////////////////////// - /// \brief Draw the object to a render target - /// - /// \param target Render target - /// \param renderer Renderer providing low-level rendering commands + /// \brief Default constructor /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target, Renderer& renderer) const; + Shape(); + + //////////////////////////////////////////////////////////// + /// \brief Recompute the internal geometry of the shape + /// + /// This function must be called by the derived class everytime + /// the shape's points change (ie. the result of either + /// GetPointsCount or GetPoint is different). + /// + //////////////////////////////////////////////////////////// + void Update(); private : //////////////////////////////////////////////////////////// - /// \brief Compile the shape + /// \brief Get the number of points defining the shape /// - /// This function precomputes all the internal parameters - /// needed to properly render the shape (center, outline points). + /// This function must be implemented in derived classes. + /// + /// \return Number of points of the shape /// //////////////////////////////////////////////////////////// - void Compile(); + virtual unsigned int GetOutlinePointsCount() const = 0; //////////////////////////////////////////////////////////// - /// \brief Compute the normal of a given 2D segment + /// \brief Get a point of the shape /// - /// \param p1 First point of the segment - /// \param p2 Second point of the segment - /// \param normal Variable to fill with the calculated normal + /// This function must be implemented in derived classes. /// - /// \return False if the normal couldn't be calculated (segment is null) + /// \param index Index of the point to get + /// + /// \return Index-th point of the shape /// //////////////////////////////////////////////////////////// - static bool ComputeNormal(const Vector2f& p1, const Vector2f& p2, Vector2f& normal); + virtual Vector2f GetOutlinePoint(unsigned int index) const = 0; + +private : //////////////////////////////////////////////////////////// - /// \brief Define a simple 2D point with position, normal and colors + /// \brief Draw the shape to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states /// //////////////////////////////////////////////////////////// - struct Point - { - Point(const Vector2f& position = Vector2f(0, 0), const Color& color = Color(255, 255, 255), const Color& outlineColor = Color(255, 255, 255)); + virtual void Draw(RenderTarget& target, RenderStates states) const; - Vector2f Position; ///< Position - Vector2f Normal; ///< Extruded normal - Color Col; ///< Color of the point - Color OutlineCol; ///< Outline color of the point - }; + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' color + /// + //////////////////////////////////////////////////////////// + void UpdateFillColors(); + + //////////////////////////////////////////////////////////// + /// \brief Update the fill vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void UpdateTexCoords(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' position + /// + //////////////////////////////////////////////////////////// + void UpdateOutline(); + + //////////////////////////////////////////////////////////// + /// \brief Update the outline vertices' color + /// + //////////////////////////////////////////////////////////// + void UpdateOutlineColors(); + +private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - std::vector myPoints; ///< Points composing the shape - float myOutline; ///< Outline thickness - bool myIsFillEnabled; ///< Should we draw the inside if the shape ? - bool myIsOutlineEnabled; ///< Should we draw the outline if the shape ? - bool myIsCompiled; ///< Compiled state of the shape + const Texture* myTexture; ///< Texture of the shape + IntRect myTextureRect; ///< Rectangle defining the area of the source texture to display + Color myFillColor; ///< Fill color + Color myOutlineColor; ///< Outline color + float myOutlineThickness; ///< Thickness of the shape's outline + VertexArray myVertices; ///< Vertex array containing the fill geometry + VertexArray myOutlineVertices; ///< Vertex array containing the outline geometry + FloatRect myInsideBounds; ///< Bounding rectangle of the inside (fill) + FloatRect myBounds; ///< Bounding rectangle of the whole shape (outline + fill) }; } // namespace sf @@ -467,73 +317,28 @@ private : /// /// sf::Shape is a drawable class that allows to define and /// display a custom convex shape on a render target. +/// It's only an abstract base, it needs to be specialized for +/// concrete types of shapes (circle, rectangle, convex polygon, +/// star, ...). /// -/// It is important to keep in mind that shapes must always be -/// convex, otherwise they may not be drawn correctly. Moreover, -/// the points must be added in the right order; using a random -/// order would also result in an incorrect shape. +/// In addition to the attributes provided by the specialized +/// shape classes, a shape always has the following attributes: +/// \li a texture +/// \li a texture rectangle +/// \li a fill color +/// \li an outline color +/// \li an outline thickness /// -/// A shape is made of points that have their own individual -/// attributes: -/// \li position (relative to the origin of the shape) -/// \li color -/// \li outline color +/// Each feature is optional, and can be disabled easily: +/// \li the texture can be null +/// \li the fill/outline colors can be sf::Color::Transparent +/// \li the outline thickness can be zero /// -/// Shapes have an outline that can be enabled or not. You can -/// control the thickness of the outline with the SetOutlineThickness -/// function. +/// You can write your own derived shape class, there are only +/// two virtual functions to override: +/// \li GetOutlinePointsCount must return the number of points of the shape +/// \li GetOutlinePoint must return the points of the shape /// -/// They also inherits all the functions from sf::Drawable: -/// position, rotation, scale, origin, global color and blend -/// mode. -/// -/// Some static functions are provided to directly create common -/// shapes such as lines, rectangles and circles: -/// \code -/// sf::Shape line = sf::Shape::Line(start, end, thickness, color); -/// sf::Shape rectangle = sf::Shape::Rectangle(rect, thickness); -/// sf::Shape circle = sf::Shape::Circle(center, radius, color); -/// \endcode -/// -/// A common mistake is to mix the individual points -/// positions / colors and the global position / color of the shape. -/// They are completely separate attributes that are combined -/// when the shape is drawn (positions are added, colors are multiplied). -/// \code -/// sf::Shape line = sf::Shape::Line(sf::Vector2f(100, 100), sf::Vector2f(200, 200), 10, sf::Color::Red); -/// -/// // --> line.GetPosition() is (0, 0), *not* (100, 100) -/// // --> line.GetColor() is white, *not* red -/// \endcode -/// So if you plan to change the position / color of your shape -/// after it is created, you'd better create the points around -/// the origin and with white color, and use only the global -/// position / color (SetPosition, SetColor). -/// -/// Usage example: -/// \code -/// // Create a shape -/// sf::Shape shape; -/// -/// // Define its points -/// shape.AddPoint(10, 10, sf::Color::White, sf::Color::Red); -/// shape.AddPoint(50, 10, sf::Color::White, sf::Color::Green); -/// shape.AddPoint(10, 50, sf::Color::White, sf::Color::Blue); -/// -/// // Enable outline only -/// shape.EnableFill(false); -/// shape.EnableOutline(true); -/// shape.SetOutlineThickness(10); -/// -/// // Display it -/// window.Draw(shape); // window is a sf::RenderWindow -/// -/// // Display static shapes -/// window.Draw(sf::Shape::Line(0, 0, 10, 20, sf::Color::Red)); -/// window.Draw(sf::Shape::Rectangle(100, 1000, 50, 20, sf::Color::Green)); -/// window.Draw(sf::Shape::Circle(500, 500, 20, sf::Color::Blue, 5, sf::Color::Black)); -/// \endcode -/// -/// \see sf::Sprite +/// \see sf::LineShape, sf::RectangleShape, sf::CircleShape, sf::ConvexShape, sf::Transformable /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Sprite.hpp b/include/SFML/Graphics/Sprite.hpp index cb754797d..675a920f8 100644 --- a/include/SFML/Graphics/Sprite.hpp +++ b/include/SFML/Graphics/Sprite.hpp @@ -28,8 +28,9 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include #include +#include +#include #include @@ -39,10 +40,10 @@ class Texture; //////////////////////////////////////////////////////////// /// \brief Drawable representation of a texture, with its -/// own transformations, color, blend mode, etc. +/// own transformations, color, etc. /// //////////////////////////////////////////////////////////// -class SFML_API Sprite : public Drawable +class SFML_API Sprite : public Drawable, public Transformable { public : @@ -57,11 +58,24 @@ public : //////////////////////////////////////////////////////////// /// \brief Construct the sprite from a source texture /// + /// \param texture Source texture + /// /// \see SetTexture /// //////////////////////////////////////////////////////////// explicit Sprite(const Texture& texture); + //////////////////////////////////////////////////////////// + /// \brief Construct the sprite from a sub-rectangle of a source texture + /// + /// \param texture Source texture + /// \param rectangle Sub-rectangle of the texture to assign to the sprite + /// + /// \see SetTexture, SetTextureRect + /// + //////////////////////////////////////////////////////////// + Sprite(const Texture& texture, const IntRect& rectangle); + //////////////////////////////////////////////////////////// /// \brief Change the source texture of the sprite /// @@ -70,91 +84,52 @@ public : /// doesn't store its own copy of the texture, but rather keeps /// a pointer to the one that you passed to this function. /// If the source texture is destroyed and the sprite tries to - /// use it, it may appear as a white rectangle. - /// If \a adjustToNewSize is true, the SubRect property of - /// the sprite is adjusted to the size of the new texture. If - /// it is false, the SubRect is unchanged. + /// use it, the behaviour is undefined. + /// If \a resetRect is true, the TextureRect property of + /// the sprite is automatically adjusted to the size of the new + /// texture. If it is false, the texture rect is left unchanged. /// - /// \param texture New texture - /// \param adjustToNewSize Should the sub-rect be adjusted to the size of the new texture? + /// \param texture New texture + /// \param resetRect Should the texture rect be reset to the size of the new texture? /// - /// \see GetTexture, SetSubRect + /// \see GetTexture, SetTextureRect /// //////////////////////////////////////////////////////////// - void SetTexture(const Texture& texture, bool adjustToNewSize = false); + void SetTexture(const Texture& texture, bool resetRect = false); //////////////////////////////////////////////////////////// - /// \brief Set the part of the texture that the sprite will display + /// \brief Set the sub-rectangle of the texture that the sprite will display /// - /// The sub-rectangle is useful when you don't want to display + /// The texture rect is useful when you don't want to display /// the whole texture, but rather a part of it. - /// By default, the sub-rectangle covers the entire texture. + /// By default, the texture rect covers the entire texture. /// /// \param rectangle Rectangle defining the region of the texture to display /// - /// \see GetSubRect, SetTexture + /// \see GetTextureRect, SetTexture /// //////////////////////////////////////////////////////////// - void SetSubRect(const IntRect& rectangle); + void SetTextureRect(const IntRect& rectangle); //////////////////////////////////////////////////////////// - /// \brief Change the size of the sprite + /// \brief Set the global color of the sprite /// - /// This function is just a shortcut that calls SetScale - /// with the proper values, calculated from the size of - /// the current subrect. - /// If \a width or \a height is not strictly positive, - /// this functions does nothing. + /// This color is modulated (multiplied) with the sprite's + /// texture. It can be used to colorize the sprite, or change + /// its global opacity. + /// By default, the sprite's color is opaque white. /// - /// \param width New width of the sprite - /// \param height New height of the sprite + /// \param color New color of the sprite /// - /// \see GetSize + /// \see GetColor /// //////////////////////////////////////////////////////////// - void Resize(float width, float height); - - //////////////////////////////////////////////////////////// - /// \brief Change the size of the sprite - /// - /// This function is just a shortcut that calls SetScale - /// with the proper values, calculated from the size of - /// the current subrect. - /// If \a size.x or \a size.y is not strictly positive, - /// this functions does nothing. - /// - /// \param size New size of the sprite - /// - /// \see GetSize - /// - //////////////////////////////////////////////////////////// - void Resize(const Vector2f& size); - - //////////////////////////////////////////////////////////// - /// \brief Flip the sprite horizontally - /// - /// \param flipped True to flip the sprite - /// - /// \see FlipY - /// - //////////////////////////////////////////////////////////// - void FlipX(bool flipped); - - //////////////////////////////////////////////////////////// - /// \brief Flip the sprite vertically - /// - /// \param flipped True to flip the sprite - /// - /// \see FlipX - /// - //////////////////////////////////////////////////////////// - void FlipY(bool flipped); + void SetColor(const Color& color); //////////////////////////////////////////////////////////// /// \brief Get the source texture of the sprite /// - /// If the sprite has no source texture, or if the texture - /// doesn't exist anymore, a NULL pointer is returned. + /// If the sprite has no source texture, a NULL pointer is returned. /// The returned pointer is const, which means that you can't /// modify the texture when you retrieve it with this function. /// @@ -166,48 +141,82 @@ public : const Texture* GetTexture() const; //////////////////////////////////////////////////////////// - /// \brief Get the region of the texture displayed by the sprite + /// \brief Get the sub-rectangle of the texture displayed by the sprite /// - /// \return Rectangle defining the region of the texture + /// \return Texture rectangle of the sprite /// - /// \see SetSubRect + /// \see SetTextureRect /// //////////////////////////////////////////////////////////// - const IntRect& GetSubRect() const; + const IntRect& GetTextureRect() const; //////////////////////////////////////////////////////////// - /// \brief Get the global size of the sprite + /// \brief Get the global color of the sprite /// - /// This function is a shortcut that multiplies the - /// size of the subrect by the scale factors. + /// \return Global color of the sprite /// - /// \return Size of the sprite - /// - /// \see Resize + /// \see SetColor /// //////////////////////////////////////////////////////////// - Vector2f GetSize() const; - -protected : + const Color& GetColor() const; //////////////////////////////////////////////////////////// - /// \brief Draw the object to a render target + /// \brief Get the local bounding rectangle of the entity /// - /// \param target Render target - /// \param renderer Renderer providing low-level rendering commands + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. + /// + /// \return Local bounding rectangle of the entity /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target, Renderer& renderer) const; + FloatRect GetLocalBounds() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the global bounding rectangle of the entity + /// + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity + /// + //////////////////////////////////////////////////////////// + FloatRect GetGlobalBounds() const; private : + //////////////////////////////////////////////////////////// + /// \brief Draw the sprite to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void Draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' positions + /// + //////////////////////////////////////////////////////////// + void UpdatePositions(); + + //////////////////////////////////////////////////////////// + /// \brief Update the vertices' texture coordinates + /// + //////////////////////////////////////////////////////////// + void UpdateTexCoords(); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - ResourcePtr myTexture; ///< Texture used to draw the sprite - IntRect mySubRect; ///< Sub-rectangle of source texture to assign to the sprite - bool myIsFlippedX; ///< Is the sprite flipped on the X axis ? - bool myIsFlippedY; ///< Is the sprite flipped on the Y axis ? + Vertex myVertices[4]; ///< Vertices defining the sprite's geometry + const Texture* myTexture; ///< Texture of the sprite + IntRect myTextureRect; ///< Rectangle defining the area of the source texture to display }; } // namespace sf @@ -223,11 +232,11 @@ private : /// sf::Sprite is a drawable class that allows to easily display /// a texture (or a part of it) on a render target. /// -/// It inherits all the functions from sf::Drawable: -/// position, rotation, scale, origin, global color and blend -/// mode. It also adds sprite-specific properties such as the -/// texture to use, the part of it to display, and some convenience -/// functions to flip or resize the sprite. +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds sprite-specific +/// properties such as the texture to use, the part of it to display, +/// and some convenience functions to change the overall color of the +/// sprite, or to get its bounding rectangle. /// /// sf::Sprite works in combination with the sf::Texture class, which /// loads and provides the pixel data of a given texture. @@ -237,11 +246,11 @@ private : /// and any operation on it is slow (often too slow for real-time /// applications). On the other side, a sf::Sprite is a lightweight /// object which can use the pixel data of a sf::Texture and draw -/// it with its own transformation / color / blending attributes. +/// it with its own transformation/color/blending attributes. /// /// It is important to note that the sf::Sprite instance doesn't /// copy the texture that it uses, it only keeps a reference to it. -/// Thus, a sf::Texture must not be destructed while it is +/// Thus, a sf::Texture must not be destroyed while it is /// used by a sf::Sprite (i.e. never write a function that /// uses a local sf::Texture instance for creating a sprite). /// @@ -254,13 +263,14 @@ private : /// // Create a sprite /// sf::Sprite sprite; /// sprite.SetTexture(texture); -/// sprite.SetSubRect(sf::IntRect(10, 10, 50, 30)); -/// sprite.Resize(100, 60); +/// sprite.SetTextureRect(sf::IntRect(10, 10, 50, 30)); +/// sprite.SetColor(sf::Color(255, 255, 255, 200)); +/// sprite.SetPosition(100, 25); /// -/// // Display it -/// window.Draw(sprite); // window is a sf::RenderWindow +/// // Draw it +/// window.Draw(sprite); /// \endcode /// -/// \see sf::Texture +/// \see sf::Texture, sf::Transformable /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/StarShape.hpp b/include/SFML/Graphics/StarShape.hpp new file mode 100644 index 000000000..c906a5b83 --- /dev/null +++ b/include/SFML/Graphics/StarShape.hpp @@ -0,0 +1,178 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_STARSHAPE_HPP +#define SFML_STARSHAPE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Specialized shape representing a star +/// +//////////////////////////////////////////////////////////// +class SFML_API StarShape : public Shape +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a star with 5 points, an inner radius of 10 and + /// an outer radius of 20. + /// + //////////////////////////////////////////////////////////// + StarShape(); + + //////////////////////////////////////////////////////////// + /// \brief Set the inner radius of the star + /// + /// The default inner radius of a star is 10. + /// + /// \param radius New inner radius of the star + /// + /// \see GetInnerRadius + /// + //////////////////////////////////////////////////////////// + void SetInnerRadius(float radius); + + //////////////////////////////////////////////////////////// + /// \brief Get the inner radius of the star + /// + /// \return Inner radius of the star + /// + /// \see SetInnerRadius + /// + //////////////////////////////////////////////////////////// + float GetInnerRadius() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the outer radius of the star + /// + /// The default outer radius of a star is 20. + /// + /// \param radius New outer radius of the star + /// + /// \see GetOuterRadius + /// + //////////////////////////////////////////////////////////// + void SetOuterRadius(float radius); + + //////////////////////////////////////////////////////////// + /// \brief Get the outer radius of the star + /// + /// \return Outer radius of the star + /// + /// \see SetOuterRadius + /// + //////////////////////////////////////////////////////////// + float GetOuterRadius() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the number of points of the star + /// + /// The default number of points of a star is 5. + /// + /// \param count New number of points of the star + /// + /// \see GetPointsCount + /// + //////////////////////////////////////////////////////////// + void SetPointsCount(unsigned int count); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points of the star + /// + /// \return Number of points of the star + /// + /// \see SetPointsCount + /// + //////////////////////////////////////////////////////////// + unsigned int GetPointsCount() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Get the number of points defining the shape + /// + /// \return Number of points of the shape + /// + //////////////////////////////////////////////////////////// + virtual unsigned int GetOutlinePointsCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a point of the shape + /// + /// \param index Index of the point to get + /// + /// \return Index-th point of the shape + /// + //////////////////////////////////////////////////////////// + virtual Vector2f GetOutlinePoint(unsigned int index) const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float myInnerRadius; ///< Inner radius of the star + float myOuterRadius; ///< Outer radius of the star + unsigned int myPointsCount; ///< Number of points of the star +}; + +} // namespace sf + + +#endif // SFML_STARSHAPE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::StarShape +/// \ingroup graphics +/// +/// This class inherits all the functions of sf::Transformable +/// (position, rotation, scale, bounds, ...) as well as the +/// functions of sf::Shape (outline, color, texture, ...). +/// +/// Usage example: +/// \code +/// sf::StarShape star; +/// star.SetInnerRadius(25); +/// star.SetInnerRadius(40); +/// star.SetPointsCount(6); +/// star.SetOutlineColor(sf::Color::Red); +/// star.SetOutlineThickness(5); +/// star.SetPosition(10, 20); +/// ... +/// window.Draw(star); +/// \endcode +/// +/// \see sf::Shape, sf::CircleShape, sf::RectangleShape, sf::ConvexShape +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Text.hpp b/include/SFML/Graphics/Text.hpp index 1aa45aa75..47f35f8e6 100644 --- a/include/SFML/Graphics/Text.hpp +++ b/include/SFML/Graphics/Text.hpp @@ -28,12 +28,14 @@ //////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// -#include #include #include +#include #include #include +#include #include +#include namespace sf @@ -42,7 +44,7 @@ namespace sf /// \brief Graphical text that can be drawn to a render target /// //////////////////////////////////////////////////////////// -class SFML_API Text : public Drawable +class SFML_API Text : public Drawable, public Transformable { public : @@ -100,6 +102,12 @@ public : //////////////////////////////////////////////////////////// /// \brief Set the text's font /// + /// The \a font argument refers to a texture that must + /// exist as long as the text uses it. Indeed, the text + /// doesn't store its own copy of the font, but rather keeps + /// a pointer to the one that you passed to this function. + /// If the font is destroyed and the text tries to + /// use it, the behaviour is undefined. /// Texts have a valid font by default, which the built-in /// Font::GetDefaultFont(). /// @@ -136,6 +144,18 @@ public : //////////////////////////////////////////////////////////// void SetStyle(unsigned long style); + //////////////////////////////////////////////////////////// + /// \brief Set the global color of the text + /// + /// By default, the text's color is opaque white. + /// + /// \param color New color of the text + /// + /// \see GetColor + /// + //////////////////////////////////////////////////////////// + void SetColor(const Color& color); + //////////////////////////////////////////////////////////// /// \brief Get the text's string /// @@ -188,14 +208,23 @@ public : //////////////////////////////////////////////////////////// unsigned long GetStyle() const; + //////////////////////////////////////////////////////////// + /// \brief Get the global color of the text + /// + /// \return Global color of the text + /// + /// \see SetColor + /// + //////////////////////////////////////////////////////////// + const Color& GetColor() const; + //////////////////////////////////////////////////////////// /// \brief Return the position of the \a index-th character /// /// This function computes the visual position of a character /// from its index in the string. The returned position is - /// in local coordinates (translation, rotation, scale and - /// origin are not applied). You can easily get the corresponding - /// global position with the TransformToGlobal function. + /// in global coordinates (translation, rotation, scale and + /// origin are applied). /// If \a index is out of range, the position of the end of /// the string is returned. /// @@ -204,46 +233,63 @@ public : /// \return Position of the character /// //////////////////////////////////////////////////////////// - Vector2f GetCharacterPos(std::size_t index) const; + Vector2f FindCharacterPos(std::size_t index) const; //////////////////////////////////////////////////////////// - /// \brief Get the bounding rectangle of the text + /// \brief Get the local bounding rectangle of the entity /// - /// The returned rectangle is in global coordinates. + /// The returned rectangle is in local coordinates, which means + /// that it ignores the transformations (translation, rotation, + /// scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// entity in the entity's coordinate system. /// - /// \return Bounding rectangle of the text + /// \return Local bounding rectangle of the entity /// //////////////////////////////////////////////////////////// - FloatRect GetRect() const; - -protected : + FloatRect GetLocalBounds() const; //////////////////////////////////////////////////////////// - /// \brief Draw the object to a render target + /// \brief Get the global bounding rectangle of the entity /// - /// \param target Render target - /// \param renderer Renderer providing low-level rendering commands + /// The returned rectangle is in global coordinates, which means + /// that it takes in account the transformations (translation, + /// rotation, scale, ...) that are applied to the entity. + /// In other words, this function returns the bounds of the + /// sprite in the global 2D world's coordinate system. + /// + /// \return Global bounding rectangle of the entity /// //////////////////////////////////////////////////////////// - virtual void Render(RenderTarget& target, Renderer& renderer) const; + FloatRect GetGlobalBounds() const; private : //////////////////////////////////////////////////////////// - /// \brief Recompute the bounding rectangle + /// \brief Draw the text to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states /// //////////////////////////////////////////////////////////// - void UpdateRect() const; + virtual void Draw(RenderTarget& target, RenderStates states) const; + + //////////////////////////////////////////////////////////// + /// \brief Update the text's geometry + /// + //////////////////////////////////////////////////////////// + void UpdateGeometry(); //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - String myString; ///< String to display - ResourcePtr myFont; ///< Font used to display the string - unsigned int myCharacterSize; ///< Base size of characters, in pixels - unsigned long myStyle; ///< Text style (see Style enum) - mutable FloatRect myBaseRect; ///< Bounding rectangle of the text in object coordinates - mutable bool myRectUpdated; ///< Is the bounding rectangle up-to-date ? + String myString; ///< String to display + const Font* myFont; ///< Font used to display the string + unsigned int myCharacterSize; ///< Base size of characters, in pixels + unsigned long myStyle; ///< Text style (see the Style enum) + Color myColor; ///< Text color + VertexArray myVertices; ///< Vertex array containing the text's geometry + FloatRect myBounds; ///< Bounding rectangle of the text (in local coordinates) }; } // namespace sf @@ -259,13 +305,13 @@ private : /// sf::Text is a drawable class that allows to easily display /// some text with custom style and color on a render target. /// -/// It inherits all the functions from sf::Drawable: -/// position, rotation, scale, origin, global color and blend -/// mode. It also adds text-specific properties such as the -/// font to use, the character size, the font style (bold, -/// italic, underlined), and the text to display of course. +/// It inherits all the functions from sf::Transformable: +/// position, rotation, scale, origin. It also adds text-specific +/// properties such as the font to use, the character size, +/// the font style (bold, italic, underlined), the global color +/// and the text to display of course. /// It also provides convenience functions to calculate the -/// graphical size of the text, or to get the visual position +/// graphical size of the text, or to get the global position /// of a given character. /// /// sf::Text works in combination with the sf::Font class, which @@ -294,12 +340,17 @@ private : /// sf::Text text("hello"); /// text.SetFont(font); /// text.SetCharacterSize(30); -/// text.SetStyle(sf::Text::Regular); +/// text.SetStyle(sf::Text::Bold); +/// text.SetColor(sf::Color::Red); /// -/// // Display it -/// window.Draw(text); // window is a sf::RenderWindow +/// // Draw it +/// window.Draw(text); /// \endcode /// -/// \see sf::Font +/// Note that you don't need to load a font to draw text, +/// SFML comes with a built-in font that is implicitely used +/// by default. +/// +/// \see sf::Font, sf::Transformable /// //////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Texture.hpp b/include/SFML/Graphics/Texture.hpp index f4a2a276d..b4d9a109e 100644 --- a/include/SFML/Graphics/Texture.hpp +++ b/include/SFML/Graphics/Texture.hpp @@ -46,6 +46,18 @@ class InputStream; //////////////////////////////////////////////////////////// class SFML_API Texture : public Resource, GlResource { +public : + + //////////////////////////////////////////////////////////// + /// \brief Types of texture coordinates that can be used for rendering + /// + //////////////////////////////////////////////////////////// + enum CoordinateType + { + Normalized, ///< Texture coordinates in range [0 .. 1] + Pixels ///< Texture coordinates in range [0 .. size] + }; + public : //////////////////////////////////////////////////////////// @@ -354,12 +366,23 @@ public : /// \brief Activate the texture for rendering /// /// This function is mainly used internally by the SFML - /// render system. However it can be useful when + /// rendering system. However it can be useful when /// using sf::Texture together with OpenGL code (this function /// is equivalent to glBindTexture). /// + /// The \a coordinateType argument controls how texture + /// coordinates will be interpreted. If Normalized (the default), they + /// must be in range [0 .. 1], which is the default way of handling + /// texture coordinates with OpenGL. If Pixels, they must be given + /// in pixels (range [0 .. size]). This mode is used internally by + /// the graphics classes of SFML, it makes the definition of texture + /// coordinates more intuitive for the high-level API, users don't need + /// to compute normalized values. + /// + /// \param coordinateType Type of texture coordinates to use + /// //////////////////////////////////////////////////////////// - void Bind() const; + void Bind(CoordinateType coordinateType = Normalized) const; //////////////////////////////////////////////////////////// /// \brief Enable or disable the smooth filter @@ -388,18 +411,38 @@ public : bool IsSmooth() const; //////////////////////////////////////////////////////////// - /// \brief Convert a rectangle of pixels into texture coordinates + /// \brief Enable or disable repeating /// - /// This function is used by code that needs to map the texture - /// to some OpenGL geometry. It converts the source rectangle, - /// expressed in pixels, to float coordinates in the range [0, 1]. + /// Repeating is involved when using texture coordinates + /// outside the texture rectangle [0, 0, width, height]. + /// In this case, if repeat mode is enabled, the whole texture + /// will be repeated as many times as needed to reach the + /// coordinate (for example, if the X texture coordinate is + /// 3 * width, the texture will be repeated 3 times). + /// If repeat mode is disabled, the "extra space" will instead + /// be filled with border pixels. + /// Warning: on very old graphics cards, white pixels may appear + /// when the texture is repeated. With such cards, repeat mode + /// can be used reliably only if the texture has power-of-two + /// dimensions (such as 256x128). + /// Repeating is disabled by default. /// - /// \param rectangle Rectangle to convert + /// \param repeated True to repeat the texture, false to disable repeating /// - /// \return Texture coordinates corresponding to \a rectangle + /// \see IsRepeated /// //////////////////////////////////////////////////////////// - FloatRect GetTexCoords(const IntRect& rectangle) const; + void SetRepeated(bool repeated); + + //////////////////////////////////////////////////////////// + /// \brief Tell whether the texture is repeated or not + /// + /// \return True if repeat mode is enabled, false if it is disabled + /// + /// \see SetRepeated + /// + //////////////////////////////////////////////////////////// + bool IsRepeated() const; //////////////////////////////////////////////////////////// /// \brief Overload of assignment operator @@ -452,6 +495,7 @@ private : unsigned int myTextureHeight; ///< Actual texture height (can be greater than image height because of padding) unsigned int myTexture; ///< Internal texture identifier bool myIsSmooth; ///< Status of the smooth filter + bool myIsRepeated; ///< Is the texture in repeat mode? mutable bool myPixelsFlipped; ///< To work around the inconsistency in Y orientation }; @@ -515,7 +559,7 @@ private : /// sprite.SetTexture(texture); /// /// // Draw the textured sprite -/// window.Draw(sprite); // window is a sf::RenderWindow +/// window.Draw(sprite); /// \endcode /// /// \code diff --git a/include/SFML/Graphics/Transform.hpp b/include/SFML/Graphics/Transform.hpp new file mode 100644 index 000000000..174599898 --- /dev/null +++ b/include/SFML/Graphics/Transform.hpp @@ -0,0 +1,450 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TRANSFORM_HPP +#define SFML_TRANSFORM_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a 3x3 transform matrix +/// +//////////////////////////////////////////////////////////// +class SFML_API Transform +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an identity transform (a transform that does nothing). + /// + //////////////////////////////////////////////////////////// + Transform(); + + //////////////////////////////////////////////////////////// + /// \brief Construct a transform from a 3x3 matrix + /// + /// \param a00 Element (0, 0) of the matrix + /// \param a01 Element (0, 1) of the matrix + /// \param a02 Element (0, 2) of the matrix + /// \param a10 Element (1, 0) of the matrix + /// \param a11 Element (1, 1) of the matrix + /// \param a12 Element (1, 2) of the matrix + /// \param a20 Element (2, 0) of the matrix + /// \param a21 Element (2, 1) of the matrix + /// \param a22 Element (2, 2) of the matrix + /// + //////////////////////////////////////////////////////////// + Transform(float a00, float a01, float a02, + float a10, float a11, float a12, + float a20, float a21, float a22); + + //////////////////////////////////////////////////////////// + /// \brief Return the transform as a 4x4 matrix + /// + /// This function returns a pointer to an array of 16 floats + /// containing the transform elements as a 4x4 matrix, which + /// is directly compatible with OpenGL functions. + /// + /// \code + /// sf::Transform transform = ...; + /// glLoadMatrixf(transform.GetMatrix()); + /// \endcode + /// + /// \return Pointer to a 4x4 matrix + /// + //////////////////////////////////////////////////////////// + const float* GetMatrix() const; + + //////////////////////////////////////////////////////////// + /// \brief Return the inverse of the transform + /// + /// If the inverse cannot be computed, an identity transform + /// is returned. + /// + /// \return A new transform which is the inverse of self + /// + //////////////////////////////////////////////////////////// + Transform GetInverse() const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a 2D point + /// + /// \param x X coordinate of the point to transform + /// \param y Y coordinate of the point to transform + /// + /// \return Transformed point + /// + //////////////////////////////////////////////////////////// + Vector2f TransformPoint(float x, float y) const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a 2D point + /// + /// \param point Point to transform + /// + /// \return Transformed point + /// + //////////////////////////////////////////////////////////// + Vector2f TransformPoint(const Vector2f& point) const; + + //////////////////////////////////////////////////////////// + /// \brief Transform a rectangle + /// + /// Since SFML doesn't provide support for oriented rectangles, + /// the result of this function is always an axis-aligned + /// rectangle. Which means that if the transform contains a + /// rotation, the bounding rectangle of the transformed rectangle + /// is returned. + /// + /// \param rectangle Rectangle to transform + /// + /// \return Transformed rectangle + /// + //////////////////////////////////////////////////////////// + FloatRect TransformRect(const FloatRect& rectangle) const; + + //////////////////////////////////////////////////////////// + /// \brief Combine two transforms + /// + /// The result is a transform that is equivalent to applying + /// *this followed by \a transform. Mathematically, it is + /// equivalent to a matrix multiplication. + /// + /// \param transform Transform to combine to this transform + /// + /// \return New combined transform + /// + //////////////////////////////////////////////////////////// + Transform Combine(const Transform& transform) const; + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a translation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Translate(100, 200).Rotate(45); + /// \endcode + /// + /// \param x Offset to apply on X axis + /// \param y Offset to apply on Y axis + /// + /// \return Reference to *this + /// + /// \see Rotate, Scale + /// + //////////////////////////////////////////////////////////// + Transform& Translate(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a translation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Translate(sf::Vector2f(100, 200)).Rotate(45); + /// \endcode + /// + /// \param offset Translation offset to apply + /// + /// \return Reference to *this + /// + /// \see Rotate, Scale + /// + //////////////////////////////////////////////////////////// + Transform& Translate(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Rotate(90).Translate(50, 20); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// + /// \return Reference to *this + /// + /// \see Translate, Scale + /// + //////////////////////////////////////////////////////////// + Transform& Rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// The center of rotation is provided for convenience as a second + /// argument, so that you can build rotations around arbitrary points + /// more easily (and efficiently) than the usual + /// Translate(-center).Rotate(angle).Translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Rotate(90, 8, 3).Translate(50, 20); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// \param centerX X coordinate of the center of rotation + /// \param centerY Y coordinate of the center of rotation + /// + /// \return Reference to *this + /// + /// \see Translate, Scale + /// + //////////////////////////////////////////////////////////// + Transform& Rotate(float angle, float centerX, float centerY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a rotation + /// + /// The center of rotation is provided for convenience as a second + /// argument, so that you can build rotations around arbitrary points + /// more easily (and efficiently) than the usual + /// Translate(-center).Rotate(angle).Translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Rotate(90, sf::Vector2f(8, 3)).Translate(sf::Vector2f(50, 20)); + /// \endcode + /// + /// \param angle Rotation angle, in degrees + /// \param center Center of rotation + /// + /// \return Reference to *this + /// + /// \see Translate, Scale + /// + //////////////////////////////////////////////////////////// + Transform& Rotate(float angle, const Vector2f& center); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Scale(2, 1).Rotate(45); + /// \endcode + /// + /// \param scaleX Scaling factor on the X axis + /// \param scaleY Scaling factor on the Y axis + /// + /// \return Reference to *this + /// + /// \see Translate, Rotate + /// + //////////////////////////////////////////////////////////// + Transform& Scale(float scaleX, float scaleY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// The center of scaling is provided for convenience as a second + /// argument, so that you can build scaling around arbitrary points + /// more easily (and efficiently) than the usual + /// Translate(-center).Scale(factors).Translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Scale(2, 1, 8, 3).Rotate(45); + /// \endcode + /// + /// \param scaleX Scaling factor on X axis + /// \param scaleY Scaling factor on Y axis + /// \param centerX X coordinate of the center of scaling + /// \param centerY Y coordinate of the center of scaling + /// + /// \return Reference to *this + /// + /// \see Translate, Rotate + /// + //////////////////////////////////////////////////////////// + Transform& Scale(float scaleX, float scaleY, float centerX, float centerY); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Scale(sf::Vector2f(2, 1)).Rotate(45); + /// \endcode + /// + /// \param factors Scaling factors + /// + /// \return Reference to *this + /// + /// \see Translate, Rotate + /// + //////////////////////////////////////////////////////////// + Transform& Scale(const Vector2f& factors); + + //////////////////////////////////////////////////////////// + /// \brief Combine the current transform with a scaling + /// + /// The center of scaling is provided for convenience as a second + /// argument, so that you can build scaling around arbitrary points + /// more easily (and efficiently) than the usual + /// Translate(-center).Scale(factors).Translate(center). + /// + /// This function returns a reference to *this, so that calls + /// can be chained. + /// \code + /// sf::Transform transform; + /// transform.Scale(sf::Vector2f(2, 1), sf::Vector2f(8, 3)).Rotate(45); + /// \endcode + /// + /// \param factors Scaling factors + /// \param center Center of scaling + /// + /// \return Reference to *this + /// + /// \see Translate, Rotate + /// + //////////////////////////////////////////////////////////// + Transform& Scale(const Vector2f& factors, const Vector2f& center); + + //////////////////////////////////////////////////////////// + // Static member data + //////////////////////////////////////////////////////////// + static const Transform Identity; ///< The identity transform (does nothing) + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + float myMatrix[16]; /// 4x4 matrix defining the transformation +}; + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator * to combine two transforms +/// +/// This call is equivalent to calling left.Combine(right). +/// +/// \param left Left operand (the first transform) +/// \param right Right operand (the second transform) +/// +/// \return New combined transform +/// +//////////////////////////////////////////////////////////// +SFML_API Transform operator *(const Transform& left, const Transform& right); + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator *= to combine two transforms +/// +/// This call is equivalent to calling left = left.Combine(right). +/// +/// \param left Left operand (the first transform) +/// \param right Right operand (the second transform) +/// +/// \return The combined transform +/// +//////////////////////////////////////////////////////////// +SFML_API Transform& operator *=(Transform& left, const Transform& right); + +//////////////////////////////////////////////////////////// +/// \relates sf::Transform +/// \brief Overload of binary operator * to transform a point +/// +/// This call is equivalent to calling left.TransformPoint(right). +/// +/// \param left Left operand (the transform) +/// \param right Right operand (the point to transform) +/// +/// \return New transformed point +/// +//////////////////////////////////////////////////////////// +SFML_API Vector2f operator *(const Transform& left, const Vector2f& right); + +} // namespace sf + + +#endif // SFML_TRANSFORM_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Transform +/// \ingroup graphics +/// +/// A sf::Transform specifies how to translate, rotate, scale, +/// shear, project, whatever things. In mathematical terms, it defines +/// how to transform a coordinate system into another. +/// +/// For example, if you apply a rotation transform to a sprite, the +/// result will be a rotated sprite. And anything that is transformed +/// by this rotation transform will be rotated the same way, according +/// to its initial position. +/// +/// Transforms are typically used for drawing. But they can also be +/// used for any computation that requires to transform points between +/// the local and global coordinate systems of an entity (like collision +/// detection). +/// +/// Example: +/// \code +/// // define a translation transform +/// sf::Transform translation; +/// translation.Translate(20, 50); +/// +/// // define a rotation transform +/// sf::Transform rotation; +/// rotation.Rotate(45); +/// +/// // combine them +/// sf::Transform transform = translation * rotation; +/// +/// // use the result to transform stuff... +/// sf::Vector2f point = transform.TransformPoint(10, 20); +/// sf::FloatRect rect = transform.TransformRect(sf::FloatRect(0, 0, 10, 100)); +/// \endcode +/// +/// \see sf::Transformable, sf::RenderStates +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Transformable.hpp b/include/SFML/Graphics/Transformable.hpp new file mode 100644 index 000000000..d20a16a2a --- /dev/null +++ b/include/SFML/Graphics/Transformable.hpp @@ -0,0 +1,414 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_TRANSFORMABLE_HPP +#define SFML_TRANSFORMABLE_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Decomposed transform defined by a position, a rotation and a scale +/// +//////////////////////////////////////////////////////////// +class SFML_API Transformable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Transformable(); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the object + /// + /// This function completely overwrites the previous position. + /// See Move to apply an offset based on the previous position instead. + /// The default position of a transformable object is (0, 0). + /// + /// \param x X coordinate of the new position + /// \param y Y coordinate of the new position + /// + /// \see Move, GetPosition + /// + //////////////////////////////////////////////////////////// + void SetPosition(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Set the position of the object + /// + /// This function completely overwrites the previous position. + /// See Move to apply an offset based on the previous position instead. + /// The default position of a transformable object is (0, 0). + /// + /// \param position New position + /// + /// \see Move, GetPosition + /// + //////////////////////////////////////////////////////////// + void SetPosition(const Vector2f& position); + + //////////////////////////////////////////////////////////// + /// \brief Set the orientation of the object + /// + /// This function completely overwrites the previous rotation. + /// See Rotate to add an angle based on the previous rotation instead. + /// The default rotation of a transformable object is 0. + /// + /// \param angle New rotation, in degrees + /// + /// \see Rotate, GetRotation + /// + //////////////////////////////////////////////////////////// + void SetRotation(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Set the scale factors of the object + /// + /// \a factorX and \a factorY must be strictly positive, + /// otherwise they are ignored. + /// This function completely overwrites the previous scale. + /// See Scale to add a factor based on the previous scale instead. + /// The default scale of a transformable object is (1, 1). + /// + /// \param factorX New horizontal scale factor + /// \param factorY New vertical scale factor + /// + /// \see Scale, GetScale + /// + //////////////////////////////////////////////////////////// + void SetScale(float factorX, float factorY); + + //////////////////////////////////////////////////////////// + /// \brief Set the scale factors of the object + /// + /// \a scale.x and \a scale.y must be strictly positive, + /// otherwise they are ignored. + /// This function completely overwrites the previous scale. + /// See Scale to add a factor based on the previous scale instead. + /// The default scale of a transformable object is (1, 1). + /// + /// \param factors New scale factors + /// + /// \see Scale, GetScale + /// + //////////////////////////////////////////////////////////// + void SetScale(const Vector2f& factors); + + //////////////////////////////////////////////////////////// + /// \brief Set the local origin of the object + /// + /// The origin of an object defines the center point for + /// all transformations (position, scale, rotation). + /// The coordinates of this point must be relative to the + /// top-left corner of the object, and ignore all + /// transformations (position, scale, rotation). + /// The default origin of a transformable object is (0, 0). + /// + /// \param x X coordinate of the new origin + /// \param y Y coordinate of the new origin + /// + /// \see GetOrigin + /// + //////////////////////////////////////////////////////////// + void SetOrigin(float x, float y); + + //////////////////////////////////////////////////////////// + /// \brief Set the local origin of the object + /// + /// The origin of an object defines the center point for + /// all transformations (position, scale, rotation). + /// The coordinates of this point must be relative to the + /// top-left corner of the object, and ignore all + /// transformations (position, scale, rotation). + /// The default origin of a transformable object is (0, 0). + /// + /// \param origin New origin + /// + /// \see GetOrigin + /// + //////////////////////////////////////////////////////////// + void SetOrigin(const Vector2f& origin); + + //////////////////////////////////////////////////////////// + /// \brief Get the position of the object + /// + /// \return Current position + /// + /// \see SetPosition + /// + //////////////////////////////////////////////////////////// + const Vector2f& GetPosition() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the orientation of the object + /// + /// The rotation is always in the range [0, 360]. + /// + /// \return Current rotation, in degrees + /// + /// \see SetRotation + /// + //////////////////////////////////////////////////////////// + float GetRotation() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the current scale of the object + /// + /// \return Current scale factors + /// + /// \see SetScale + /// + //////////////////////////////////////////////////////////// + const Vector2f& GetScale() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the local origin of the object + /// + /// \return Current origin + /// + /// \see SetOrigin + /// + //////////////////////////////////////////////////////////// + const Vector2f& GetOrigin() const; + + //////////////////////////////////////////////////////////// + /// \brief Move the object by a given offset + /// + /// This function adds to the current position of the object, + /// unlike SetPosition which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f pos = object.GetPosition(); + /// object.SetPosition(pos.x + offsetX, pos.y + offsetY); + /// \endcode + /// + /// \param offsetX X offset + /// \param offsetY Y offset + /// + /// \see SetPosition + /// + //////////////////////////////////////////////////////////// + void Move(float offsetX, float offsetY); + + //////////////////////////////////////////////////////////// + /// \brief Move the object by a given offset + /// + /// This function adds to the current position of the object, + /// unlike SetPosition which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// object.SetPosition(object.GetPosition() + offset); + /// \endcode + /// + /// \param offset Offset + /// + /// \see SetPosition + /// + //////////////////////////////////////////////////////////// + void Move(const Vector2f& offset); + + //////////////////////////////////////////////////////////// + /// \brief Rotate the object + /// + /// This function adds to the current rotation of the object, + /// unlike SetRotation which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// object.SetRotation(object.GetRotation() + angle); + /// \endcode + /// + /// \param angle Angle of rotation, in degrees + /// + //////////////////////////////////////////////////////////// + void Rotate(float angle); + + //////////////////////////////////////////////////////////// + /// \brief Scale the object + /// + /// This function multiplies the current scale of the object, + /// unlike SetScale which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f scale = object.GetScale(); + /// object.SetScale(scale.x * factorX, scale.y * factorY); + /// \endcode + /// + /// \param factorX Horizontal scale factor + /// \param factorY Vertical scale factor + /// + /// \see SetScale + /// + //////////////////////////////////////////////////////////// + void Scale(float factorX, float factorY); + + //////////////////////////////////////////////////////////// + /// \brief Scale the object + /// + /// This function multiplies the current scale of the object, + /// unlike SetScale which overwrites it. + /// Thus, it is equivalent to the following code: + /// \code + /// sf::Vector2f scale = object.GetScale(); + /// object.SetScale(scale.x * factor.x, scale.y * factor.y); + /// \endcode + /// + /// \param factor Scale factors + /// + /// \see SetScale + /// + //////////////////////////////////////////////////////////// + void Scale(const Vector2f& factor); + + //////////////////////////////////////////////////////////// + /// \brief Get the combined transform of the object + /// + /// \return Transform combining the position/rotation/scale/origin of the object + /// + /// \see GetInverseTransform + /// + //////////////////////////////////////////////////////////// + const Transform& GetTransform() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the inverse of the combined transform of the object + /// + /// \return Inversed of the combined transformations applied to the object + /// + /// \see GetTransform + /// + //////////////////////////////////////////////////////////// + const Transform& GetInverseTransform() const; + +private : + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f myOrigin; ///< Origin of translation/rotation/scaling of the object + Vector2f myPosition; ///< Position of the object in the 2D world + float myRotation; ///< Orientation of the object, in degrees + Vector2f myScale; ///< Scale of the object + mutable Transform myTransform; ///< Combined transformation of the object + mutable bool myTransformNeedUpdate; ///< Does the transform need to be recomputed? + mutable Transform myInverseTransform; ///< Combined transformation of the object + mutable bool myInverseTransformNeedUpdate; ///< Does the transform need to be recomputed? +}; + +} // namespace sf + + +#endif // SFML_TRANSFORMABLE_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Transformable +/// \ingroup graphics +/// +/// This class is provided for convenience, on top of sf::Transform. +/// +/// sf::Transform, as a low-level class, offers a great level of +/// flexibility but it is not always convenient to manage. Indeed, +/// one can easily combine any kind of operation, such as a translation +/// followed by a rotation followed by a scaling, but once the result +/// transform is built, there's no way to go backward and, let's say, +/// change only the rotation without modifying the translation and scaling. +/// The entire transform must be recomputed, which means that you +/// need to retrieve the initial translation and scale factors as +/// well, and combine them the same way you did before updating the +/// rotation. This is a tedious operation, and it requires to store +/// all the individual components of the final transform. +/// +/// That's exactly what sf::Transformable was written for: it hides +/// these variables and the composed transform behind an easy to use +/// interface. You can set or get any of the individual components +/// without worrying about the others. It also provides the composed +/// transform (as a sf::Transform), and keeps it up-to-date. +/// +/// In addition to the position, rotation and scale, sf::Transformable +/// provides an "origin" component, which represents the local origin +/// of the three other components. Let's take an example with a 10x10 +/// pixels sprite. By default, the sprite is positionned/rotated/scaled +/// relatively to its top-left corner, because it is the local point +/// (0, 0). But if we change the origin to be (5, 5), the sprite will +/// be positionned/rotated/scaled around its center instead. And if +/// we set the origin to (10, 10), it will be transformed around its +/// bottom-right corner. +/// +/// To keep the sf::Transformable class simple, there's only one +/// origin for all the components. You cannot position the sprite +/// relatively to its top-left corner while rotating it around its +/// center, for example. To do such things, use sf::Transform directly. +/// +/// sf::Transformable can be used as a base class. It is often +/// combined with sf::Drawable -- that's what SFML's sprites, +/// texts and shapes do. +/// \code +/// class MyEntity : public sf::Transformable, public sf::Drawable +/// { +/// virtual void Draw(sf::RenderTarget& target, sf::RenderStates states) const +/// { +/// states.Transform *= GetTransform(); +/// target.Draw(..., states); +/// } +/// }; +/// +/// MyEntity entity; +/// entity.SetPosition(10, 20); +/// entity.SetRotation(45); +/// window.Draw(entity); +/// \endcode +/// +/// It can also be used as a member, if you don't want to use +/// its API directly (because you don't need all its functions, +/// or you have different naming conventions for example). +/// \code +/// class MyEntity +/// { +/// public : +/// void setPosition(const MyVector& v) +/// { +/// m_transform.SetPosition(v.x(), v.y()); +/// } +/// +/// void draw(sf::RenderTarget& target) const +/// { +/// target.Draw(..., m_transform.GetTransform()); +/// } +/// +/// private : +/// sf::Transformable m_transform; +/// }; +/// \endcode +/// +/// \see sf::Transform +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/Vertex.hpp b/include/SFML/Graphics/Vertex.hpp new file mode 100644 index 000000000..21ff96eaf --- /dev/null +++ b/include/SFML/Graphics/Vertex.hpp @@ -0,0 +1,143 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VERTEX_HPP +#define SFML_VERTEX_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a point with color and texture coordinates +/// +//////////////////////////////////////////////////////////// +class SFML_API Vertex +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + Vertex(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position + /// + /// The vertex color is white and texture coordinates are (0, 0). + /// + /// \param position Vertex position + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& position); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position and color + /// + /// The texture coordinates are (0, 0). + /// + /// \param position Vertex position + /// \param color Vertex color + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& position, const Color& color); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position and texture coordinates + /// + /// The vertex color is white. + /// + /// \param position Vertex position + /// \param texCoords Vertex texture coordinates + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& position, const Vector2i& texCoords); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex from its position, color and texture coordinates + /// + /// \param position Vertex position + /// \param color Vertex color + /// \param texCoords Vertex texture coordinates + /// + //////////////////////////////////////////////////////////// + Vertex(const Vector2f& position, const Color& color, const Vector2i& texCoords); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + Vector2f Position; ///< 2D position of the vertex + sf::Color Color; ///< Color of the vertex + Vector2i TexCoords; ///< Coordinates of the texture's pixel to map to the vertex +}; + +} // namespace sf + + +#endif // SFML_VERTEX_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::Vertex +/// \ingroup graphics +/// +/// A vertex is an improved point. It has a position and other +/// extra attributes that will be used for drawing: in SFML, +/// vertices also have a color and a pair of texture coordinates. +/// +/// The vertex is the building block of drawing. Everything which +/// is visible on screen is made of vertices. They are grouped +/// as 2D primitives (triangles, quads, ...), and these primitives +/// are grouped to create even more complex 2D entities such as +/// sprites, texts, etc. +/// +/// If you use the graphical entities of SFML (sprite, text, shape) +/// you won't have to deal with vertices directly. But if you want +/// to define your own 2D entities, such as tiled maps or particle +/// systems, using vertices will allow you to get maximum performances. +/// +/// Example: +/// \code +/// // define a 100x100 square, red, with a 10x10 texture mapped on it +/// sf::Vertex vertices[] = +/// { +/// sf::Vertex(sf::Vector2f( 0, 0), sf::Color::Red, sf::Vector2i( 0, 0)), +/// sf::Vertex(sf::Vector2f( 0, 100), sf::Color::Red, sf::Vector2i( 0, 10)), +/// sf::Vertex(sf::Vector2f(100, 100), sf::Color::Red, sf::Vector2i(10, 10)), +/// sf::Vertex(sf::Vector2f(100, 0), sf::Color::Red, sf::Vector2i(10, 0)) +/// }; +/// +/// // draw it +/// window.Draw(vertices, 4, sf::Quads); +/// \endcode +/// +/// \see sf::VertexArray +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/VertexArray.hpp b/include/SFML/Graphics/VertexArray.hpp new file mode 100644 index 000000000..5c8470543 --- /dev/null +++ b/include/SFML/Graphics/VertexArray.hpp @@ -0,0 +1,220 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +#ifndef SFML_VERTEXARRAY_HPP +#define SFML_VERTEXARRAY_HPP + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Define a set of one or more 2D primitives +/// +//////////////////////////////////////////////////////////// +class SFML_API VertexArray : public Drawable +{ +public : + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates an empty vertex array. + /// + //////////////////////////////////////////////////////////// + VertexArray(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vertex array with a type and an initial number of vertices + /// + /// \param type Type of primitives + /// \param verticesCount Initial number of vertices in the array + /// + //////////////////////////////////////////////////////////// + VertexArray(PrimitiveType type, unsigned int verticesCount = 0); + + //////////////////////////////////////////////////////////// + /// \brief Return the vertices count + /// + /// \return Number of vertices in the array + /// + //////////////////////////////////////////////////////////// + unsigned int GetVerticesCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get a read-write access to a vertex by its index + /// + /// This function doesn't check \a index, it must be in range + /// [0, GetVerticesCount() - 1]. + /// + /// \param index Index of the vertex to get + /// + /// \return Reference to the index-th vertex + /// + /// \see GetVerticesCount + /// + //////////////////////////////////////////////////////////// + Vertex& operator [](unsigned int index); + + //////////////////////////////////////////////////////////// + /// \brief Get a read-only access to a vertex by its index + /// + /// This function doesn't check \a index, it must be in range + /// [0, GetVerticesCount() - 1]. + /// + /// \param index Index of the vertex to get + /// + /// \return Const reference to the index-th vertex + /// + /// \see GetVerticesCount + /// + //////////////////////////////////////////////////////////// + const Vertex& operator [](unsigned int index) const; + + //////////////////////////////////////////////////////////// + /// \brief Clear the vertex array + /// + /// This function removes all the vertices from the array. + /// It doesn't deallocate the corresponding memory, so that + /// adding new vertices after clearing doesn't involve + /// reallocating all the memory. + /// + //////////////////////////////////////////////////////////// + void Clear(); + + //////////////////////////////////////////////////////////// + /// \brief Resize the vertex array + /// + /// If \a count is greater than the current size, the previous + /// vertices are kept and new (default-constructed) vertices are + /// added. + /// If \a count is less than the current size, existing vertices + /// are removed from the array. + /// + /// \param verticesCount New size of the array (number of vertices) + /// + //////////////////////////////////////////////////////////// + void Resize(unsigned int verticesCount); + + //////////////////////////////////////////////////////////// + /// \brief Add a vertex to the array + /// + /// \param vertex Vertex to add + /// + //////////////////////////////////////////////////////////// + void Append(const Vertex& vertex); + + //////////////////////////////////////////////////////////// + /// \brief Set the type of primitives to draw + /// + /// This function defines how the vertices must be interpreted + /// when it's time to draw them: + /// \li As points + /// \li As lines + /// \li As triangles + /// \li As quads + /// The default primitive type is sf::Points. + /// + /// \param type Type of primitive + /// + //////////////////////////////////////////////////////////// + void SetPrimitiveType(PrimitiveType type); + + //////////////////////////////////////////////////////////// + /// \brief Get the type of primitives drawn by the vertex array + /// + /// \return Primitive type + /// + //////////////////////////////////////////////////////////// + PrimitiveType GetPrimitiveType() const; + + //////////////////////////////////////////////////////////// + /// \brief Compute the bounding rectangle of the vertex array + /// + /// This function returns the axis-aligned rectangle that + /// contains all the vertices of the array. + /// + /// \return Bounding rectangle of the vertex array + /// + //////////////////////////////////////////////////////////// + FloatRect GetBounds() const; + +private : + + //////////////////////////////////////////////////////////// + /// \brief Draw the vertex array to a render target + /// + /// \param target Render target to draw to + /// \param states Current render states + /// + //////////////////////////////////////////////////////////// + virtual void Draw(RenderTarget& target, RenderStates states) const; + +private: + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::vector myVertices; ///< Vertices contained in the array + PrimitiveType myPrimitiveType; ///< Type of primitives to draw +}; + +} // namespace sf + + +#endif // SFML_VERTEXARRAY_HPP + + +//////////////////////////////////////////////////////////// +/// \class sf::VertexArray +/// \ingroup graphics +/// +/// sf::VertexArray is a very simple wrapper around a dynamic +/// array of vertices and a primitives type. +/// +/// It inherits sf::Drawable, but unlike other drawables it +/// is not transformable. +/// +/// Example: +/// \code +/// sf::VertexArray lines(sf::LinesStrip, 4); +/// lines[0].Position = sf::Vector2f(10, 0); +/// lines[1].Position = sf::Vector2f(20, 0); +/// lines[2].Position = sf::Vector2f(30, 5); +/// lines[3].Position = sf::Vector2f(40, 2); +/// +/// window.Draw(lines); +/// \endcode +/// +/// \see sf::Vertex +/// +//////////////////////////////////////////////////////////// diff --git a/include/SFML/Graphics/View.hpp b/include/SFML/Graphics/View.hpp index 14a0b9474..dee4eb491 100644 --- a/include/SFML/Graphics/View.hpp +++ b/include/SFML/Graphics/View.hpp @@ -30,7 +30,7 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include #include @@ -241,42 +241,42 @@ public : void Zoom(float factor); //////////////////////////////////////////////////////////// - /// \brief Get the projection matrix of the view + /// \brief Get the projection transform of the view /// - /// This functions is meant for internal use only. + /// This function is meant for internal use only. /// - /// \return Projection matrix defining the view + /// \return Projection transform defining the view /// - /// \see GetInverseMatrix + /// \see GetInverseTransform /// //////////////////////////////////////////////////////////// - const Matrix3& GetMatrix() const; + const Transform& GetTransform() const; //////////////////////////////////////////////////////////// - /// \brief Get the inverse projection matrix of the view + /// \brief Get the inverse projection transform of the view /// - /// This functions is meant for internal use only. + /// This function is meant for internal use only. /// - /// \return Inverse of the projection matrix defining the view + /// \return Inverse of the projection transform defining the view /// - /// \see GetMatrix + /// \see GetTransform /// //////////////////////////////////////////////////////////// - const Matrix3& GetInverseMatrix() const; + const Transform& GetInverseTransform() const; private : //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Vector2f myCenter; ///< Center of the view, in scene coordinates - Vector2f mySize; ///< Size of the view, in scene coordinates - float myRotation; ///< Angle of rotation of the view rectangle, in degrees - FloatRect myViewport; ///< Viewport rectangle, expressed as a factor of the render-target's size - mutable Matrix3 myMatrix; ///< Precomputed projection matrix corresponding to the view - mutable Matrix3 myInverseMatrix; ///< Precomputed inverse projection matrix corresponding to the view - mutable bool myMatrixUpdated; ///< Internal state telling if the matrix needs to be updated - mutable bool myInvMatrixUpdated; ///< Internal state telling if the matrix needs to be updated + Vector2f myCenter; ///< Center of the view, in scene coordinates + Vector2f mySize; ///< Size of the view, in scene coordinates + float myRotation; ///< Angle of rotation of the view rectangle, in degrees + FloatRect myViewport; ///< Viewport rectangle, expressed as a factor of the render-target's size + mutable Transform myTransform; ///< Precomputed projection transform corresponding to the view + mutable Transform myInverseTransform; ///< Precomputed inverse projection transform corresponding to the view + mutable bool myTransformUpdated; ///< Internal state telling if the transform needs to be updated + mutable bool myInvTransformUpdated; ///< Internal state telling if the inverse transform needs to be updated }; } // namespace sf diff --git a/include/SFML/System/Utf.hpp b/include/SFML/System/Utf.hpp index 5fe481b6f..f322f26da 100644 --- a/include/SFML/System/Utf.hpp +++ b/include/SFML/System/Utf.hpp @@ -149,7 +149,6 @@ public : /// \param begin Iterator pointing to the beginning of the input sequence /// \param end Iterator pointing to the end of the input sequence /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion /// /// \return Iterator to the end of the output sequence which has been written /// @@ -357,7 +356,6 @@ public : /// \param begin Iterator pointing to the beginning of the input sequence /// \param end Iterator pointing to the end of the input sequence /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion /// /// \return Iterator to the end of the output sequence which has been written /// @@ -566,7 +564,6 @@ public : /// \param begin Iterator pointing to the beginning of the input sequence /// \param end Iterator pointing to the end of the input sequence /// \param output Iterator pointing to the beginning of the output sequence - /// \param locale Locale to use for conversion /// /// \return Iterator to the end of the output sequence which has been written /// diff --git a/include/SFML/System/Vector3.hpp b/include/SFML/System/Vector3.hpp index 64042890d..dd438c59d 100644 --- a/include/SFML/System/Vector3.hpp +++ b/include/SFML/System/Vector3.hpp @@ -82,7 +82,7 @@ public : /// \relates Vector3 /// \brief Overload of unary operator - /// -/// \param right Vector to negate +/// \param left Vector to negate /// /// \return Memberwise opposite of the vector /// diff --git a/include/SFML/Window/Context.hpp b/include/SFML/Window/Context.hpp index def5acf9f..48b214914 100644 --- a/include/SFML/Window/Context.hpp +++ b/include/SFML/Window/Context.hpp @@ -41,6 +41,8 @@ namespace priv class GlContext; } +typedef void* ContextId; + //////////////////////////////////////////////////////////// /// \brief Class holding a valid drawing context /// @@ -75,6 +77,18 @@ public : //////////////////////////////////////////////////////////// bool SetActive(bool active); + //////////////////////////////////////////////////////////// + /// \brief Return the identifier of the current active context + /// + /// The returned id has no special meaning, it should only be + /// used as a key to map external stuff to internal contexts. + /// This function returns 0 if no context is active. + /// + /// \return Identifier of the current context + /// + //////////////////////////////////////////////////////////// + static ContextId GetCurrentContextId(); + public : //////////////////////////////////////////////////////////// diff --git a/src/SFML/Graphics/CMakeLists.txt b/src/SFML/Graphics/CMakeLists.txt index 09daa851d..1a87fd408 100644 --- a/src/SFML/Graphics/CMakeLists.txt +++ b/src/SFML/Graphics/CMakeLists.txt @@ -5,9 +5,9 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics) # all source files set(SRC ${SRCROOT}/Arial.hpp + ${INCROOT}/BlendMode.hpp ${SRCROOT}/Color.cpp ${INCROOT}/Color.hpp - ${SRCROOT}/Drawable.cpp ${INCROOT}/Drawable.hpp ${SRCROOT}/Font.cpp ${INCROOT}/Font.hpp @@ -18,13 +18,11 @@ set(SRC ${INCROOT}/Image.hpp ${SRCROOT}/ImageLoader.cpp ${SRCROOT}/ImageLoader.hpp - ${SRCROOT}/Matrix3.cpp - ${INCROOT}/Matrix3.hpp - ${INCROOT}/Matrix3.inl + ${INCROOT}/PrimitiveType.hpp ${INCROOT}/Rect.hpp ${INCROOT}/Rect.inl - ${SRCROOT}/Renderer.cpp - ${INCROOT}/Renderer.hpp + ${SRCROOT}/RenderStates.cpp + ${INCROOT}/RenderStates.hpp ${SRCROOT}/RenderTexture.cpp ${INCROOT}/RenderTexture.hpp ${SRCROOT}/RenderTextureImpl.cpp @@ -41,14 +39,30 @@ set(SRC ${INCROOT}/Shader.hpp ${SRCROOT}/Shape.cpp ${INCROOT}/Shape.hpp + ${SRCROOT}/CircleShape.cpp + ${INCROOT}/CircleShape.hpp + ${SRCROOT}/RectangleShape.cpp + ${INCROOT}/RectangleShape.hpp + ${SRCROOT}/StarShape.cpp + ${INCROOT}/StarShape.hpp + ${SRCROOT}/ConvexShape.cpp + ${INCROOT}/ConvexShape.hpp ${SRCROOT}/Sprite.cpp ${INCROOT}/Sprite.hpp ${SRCROOT}/Text.cpp ${INCROOT}/Text.hpp ${SRCROOT}/Texture.cpp ${INCROOT}/Texture.hpp + ${SRCROOT}/Transform.cpp + ${INCROOT}/Transform.hpp + ${SRCROOT}/Transformable.cpp + ${INCROOT}/Transformable.hpp ${SRCROOT}/View.cpp ${INCROOT}/View.hpp + ${SRCROOT}/Vertex.cpp + ${INCROOT}/Vertex.hpp + ${SRCROOT}/VertexArray.cpp + ${INCROOT}/VertexArray.hpp ${SRCROOT}/stb_image/stb_image.h ${SRCROOT}/stb_image/stb_image_write.h ) diff --git a/src/SFML/Graphics/CircleShape.cpp b/src/SFML/Graphics/CircleShape.cpp new file mode 100644 index 000000000..86a6a3cb5 --- /dev/null +++ b/src/SFML/Graphics/CircleShape.cpp @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +CircleShape::CircleShape() : +myRadius(10) +{ +} + + +//////////////////////////////////////////////////////////// +void CircleShape::SetRadius(float radius) +{ + myRadius = radius; + Update(); +} + + +//////////////////////////////////////////////////////////// +float CircleShape::GetRadius() const +{ + return myRadius; +} + + +//////////////////////////////////////////////////////////// +unsigned int CircleShape::GetOutlinePointsCount() const +{ + return 30; +} + + +//////////////////////////////////////////////////////////// +Vector2f CircleShape::GetOutlinePoint(unsigned int index) const +{ + float angle = index * 2 * 3.141592654f / GetOutlinePointsCount(); + float x = std::cos(angle) * myRadius; + float y = std::sin(angle) * myRadius; + + return Vector2f(myRadius + x, myRadius + y); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Color.cpp b/src/SFML/Graphics/Color.cpp index 0c6fccf07..bef16d5ec 100644 --- a/src/SFML/Graphics/Color.cpp +++ b/src/SFML/Graphics/Color.cpp @@ -42,6 +42,7 @@ const Color Color::Blue(0, 0, 255); const Color Color::Yellow(255, 255, 0); const Color Color::Magenta(255, 0, 255); const Color Color::Cyan(0, 255, 255); +const Color Color::Transparent(0, 0, 0, 0); //////////////////////////////////////////////////////////// diff --git a/src/SFML/Graphics/ConvexShape.cpp b/src/SFML/Graphics/ConvexShape.cpp new file mode 100644 index 000000000..222d5367f --- /dev/null +++ b/src/SFML/Graphics/ConvexShape.cpp @@ -0,0 +1,85 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +ConvexShape::ConvexShape() +{ + // Let's define a triangle by default... just so that it's not empty + SetPointsCount(3); + SetPoint(0, Vector2f(5, 0)); + SetPoint(1, Vector2f(0, 10)); + SetPoint(2, Vector2f(10, 10)); +} + + +//////////////////////////////////////////////////////////// +void ConvexShape::SetPointsCount(unsigned int count) +{ + myPoints.resize(count); +} + + +//////////////////////////////////////////////////////////// +unsigned int ConvexShape::GetPointsCount() const +{ + return myPoints.size(); +} + + +//////////////////////////////////////////////////////////// +void ConvexShape::SetPoint(unsigned int index, const Vector2f& point) +{ + myPoints[index] = point; +} + + +//////////////////////////////////////////////////////////// +Vector2f ConvexShape::GetPoint(unsigned int index) const +{ + return myPoints[index]; +} + + +//////////////////////////////////////////////////////////// +unsigned int ConvexShape::GetOutlinePointsCount() const +{ + return GetPointsCount(); +} + + +//////////////////////////////////////////////////////////// +Vector2f ConvexShape::GetOutlinePoint(unsigned int index) const +{ + return GetPoint(index); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Drawable.cpp b/src/SFML/Graphics/Drawable.cpp deleted file mode 100644 index 5dd4336f6..000000000 --- a/src/SFML/Graphics/Drawable.cpp +++ /dev/null @@ -1,314 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Drawable::~Drawable() -{ - // Nothing to do -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetPosition(float x, float y) -{ - SetX(x); - SetY(y); -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetPosition(const Vector2f& position) -{ - SetX(position.x); - SetY(position.y); -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetX(float x) -{ - myPosition.x = x; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetY(float y) -{ - myPosition.y = y; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetScale(float factorX, float factorY) -{ - SetScaleX(factorX); - SetScaleY(factorY); -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetScale(const Vector2f& factors) -{ - SetScaleX(factors.x); - SetScaleY(factors.y); -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetScaleX(float factor) -{ - if (factor > 0) - { - myScale.x = factor; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; - } -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetScaleY(float factor) -{ - if (factor > 0) - { - myScale.y = factor; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; - } -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetOrigin(float x, float y) -{ - myOrigin.x = x; - myOrigin.y = y; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetOrigin(const Vector2f& origin) -{ - SetOrigin(origin.x, origin.y); -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetRotation(float angle) -{ - myRotation = static_cast(std::fmod(angle, 360)); - if (myRotation < 0) - myRotation += 360.f; - - myMatrixUpdated = false; - myInvMatrixUpdated = false; -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetColor(const Color& color) -{ - myColor = color; -} - - -//////////////////////////////////////////////////////////// -void Drawable::SetBlendMode(Blend::Mode mode) -{ - myBlendMode = mode; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& Drawable::GetPosition() const -{ - return myPosition; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& Drawable::GetScale() const -{ - return myScale; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& Drawable::GetOrigin() const -{ - return myOrigin; -} - - -//////////////////////////////////////////////////////////// -float Drawable::GetRotation() const -{ - return myRotation; -} - - -//////////////////////////////////////////////////////////// -const Color& Drawable::GetColor() const -{ - return myColor; -} - - -//////////////////////////////////////////////////////////// -Blend::Mode Drawable::GetBlendMode() const -{ - return myBlendMode; -} - - -//////////////////////////////////////////////////////////// -void Drawable::Move(float offsetX, float offsetY) -{ - SetPosition(myPosition.x + offsetX, myPosition.y + offsetY); -} - - -//////////////////////////////////////////////////////////// -void Drawable::Move(const Vector2f& offset) -{ - SetPosition(myPosition + offset); -} - - -//////////////////////////////////////////////////////////// -void Drawable::Scale(float factorX, float factorY) -{ - SetScale(myScale.x * factorX, myScale.y * factorY); -} - - -//////////////////////////////////////////////////////////// -void Drawable::Scale(const Vector2f& factor) -{ - SetScale(myScale.x * factor.x, myScale.y * factor.y); -} - - -//////////////////////////////////////////////////////////// -void Drawable::Rotate(float angle) -{ - SetRotation(myRotation + angle); -} - - -//////////////////////////////////////////////////////////// -Vector2f Drawable::TransformToLocal(const Vector2f& point) const -{ - return GetInverseMatrix().Transform(point); -} - - -//////////////////////////////////////////////////////////// -Vector2f Drawable::TransformToGlobal(const Vector2f& point) const -{ - return GetMatrix().Transform(point); -} - - -//////////////////////////////////////////////////////////// -Drawable::Drawable() : -myPosition (0, 0), -myScale (1, 1), -myOrigin (0, 0), -myRotation (0), -myColor (255, 255, 255, 255), -myBlendMode (Blend::Alpha), -myMatrixUpdated (false), -myInvMatrixUpdated(false) -{ -} - - -//////////////////////////////////////////////////////////// -const Matrix3& Drawable::GetMatrix() const -{ - // First recompute it if needed - if (!myMatrixUpdated) - { - myMatrix = Matrix3::Transformation(myOrigin, myPosition, myRotation, myScale); - myMatrixUpdated = true; - } - - return myMatrix; -} - - -//////////////////////////////////////////////////////////// -const Matrix3& Drawable::GetInverseMatrix() const -{ - // First recompute it if needed - if (!myInvMatrixUpdated) - { - myInvMatrix = GetMatrix().GetInverse(); - myInvMatrixUpdated = true; - } - - return myInvMatrix; -} - - -//////////////////////////////////////////////////////////// -void Drawable::Draw(RenderTarget& target, Renderer& renderer) const -{ - // Set the current model-view matrix - renderer.ApplyModelView(GetMatrix()); - - // Set the current global color - renderer.ApplyColor(myColor); - - // Set the current alpha-blending mode - renderer.SetBlendMode(myBlendMode); - - // Let the derived class render the object geometry - Render(target, renderer); -} - -} // namespace sf diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index 5bc51c83a..8e8ffc720 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -452,7 +452,7 @@ Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c Page& page = myPages[characterSize]; // Find a good position for the new glyph into the texture - glyph.SubRect = FindGlyphRect(page, width + 2 * padding, height + 2 * padding); + glyph.TextureRect = FindGlyphRect(page, width + 2 * padding, height + 2 * padding); // Compute the glyph's bounding box glyph.Bounds.Left = bitmapGlyph->left - padding; @@ -493,10 +493,10 @@ Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) c } // Write the pixels to the texture - unsigned int x = glyph.SubRect.Left + padding; - unsigned int y = glyph.SubRect.Top + padding; - unsigned int width = glyph.SubRect.Width - 2 * padding; - unsigned int height = glyph.SubRect.Height - 2 * padding; + unsigned int x = glyph.TextureRect.Left + padding; + unsigned int y = glyph.TextureRect.Top + padding; + unsigned int width = glyph.TextureRect.Width - 2 * padding; + unsigned int height = glyph.TextureRect.Height - 2 * padding; page.Texture.Update(&myPixelBuffer[0], width, height, x, y); } diff --git a/src/SFML/Graphics/RectangleShape.cpp b/src/SFML/Graphics/RectangleShape.cpp new file mode 100644 index 000000000..ba8d0ebfd --- /dev/null +++ b/src/SFML/Graphics/RectangleShape.cpp @@ -0,0 +1,76 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +RectangleShape::RectangleShape() : +mySize(10, 10) +{ +} + + +//////////////////////////////////////////////////////////// +void RectangleShape::SetSize(const Vector2f& size) +{ + mySize = size; + Update(); +} + + +//////////////////////////////////////////////////////////// +const Vector2f& RectangleShape::GetSize() const +{ + return mySize; +} + + +//////////////////////////////////////////////////////////// +unsigned int RectangleShape::GetOutlinePointsCount() const +{ + return 4; +} + + +//////////////////////////////////////////////////////////// +Vector2f RectangleShape::GetOutlinePoint(unsigned int index) const +{ + switch (index) + { + default: + case 0: return Vector2f(0, 0); + case 1: return Vector2f(mySize.x, 0); + case 2: return Vector2f(mySize.x, mySize.y); + case 3: return Vector2f(0, mySize.y); + } +} + +} // namespace sf diff --git a/src/SFML/Graphics/RenderStates.cpp b/src/SFML/Graphics/RenderStates.cpp new file mode 100644 index 000000000..83794db47 --- /dev/null +++ b/src/SFML/Graphics/RenderStates.cpp @@ -0,0 +1,98 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const RenderStates RenderStates::Default; + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates() : +BlendMode(BlendAlpha), +Transform(), +Texture (NULL), +Shader (NULL) +{ +} + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates(const sf::Transform& transform) : +BlendMode(BlendAlpha), +Transform(transform), +Texture (NULL), +Shader (NULL) +{ +} + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates(sf::BlendMode blendMode) : +BlendMode(blendMode), +Transform(), +Texture (NULL), +Shader (NULL) +{ +} + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates(const sf::Texture* texture) : +BlendMode(BlendAlpha), +Transform(), +Texture (texture), +Shader (NULL) +{ +} + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates(const sf::Shader* shader) : +BlendMode(BlendAlpha), +Transform(), +Texture (NULL), +Shader (shader) +{ +} + + +//////////////////////////////////////////////////////////// +RenderStates::RenderStates(sf::BlendMode blendMode, const sf::Transform& transform, + const sf::Texture* texture, const sf::Shader* shader) : +BlendMode(blendMode), +Transform(transform), +Texture (texture), +Shader (shader) +{ +} + +} // namespace sf diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 60d3b58e5..4d8d593fe 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -27,96 +27,37 @@ //////////////////////////////////////////////////////////// #include #include +#include +#include +#include +#include #include -#ifdef _MSC_VER - #pragma warning(disable : 4355) // "'this' : used in base member initializer list" -#endif - namespace sf { //////////////////////////////////////////////////////////// RenderTarget::RenderTarget() : -myRenderer (*this), -myStatesSaved (false), -myViewHasChanged(false) +myDefaultView(), +myView (), +myViewChanged(false) { - } //////////////////////////////////////////////////////////// RenderTarget::~RenderTarget() { - // Nothing to do } //////////////////////////////////////////////////////////// void RenderTarget::Clear(const Color& color) -{ - if (Activate(true)) - myRenderer.Clear(color); -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::Draw(const Drawable& object) { if (Activate(true)) { - // Update the projection matrix and viewport if the current view has changed - // Note: we do the changes here and not directly in SetView in order to gather - // rendering commands, which is safer in multithreaded environments - if (myViewHasChanged) - { - myRenderer.SetProjection(myCurrentView.GetMatrix()); - myRenderer.SetViewport(GetViewport(myCurrentView)); - myViewHasChanged = false; - } - - // Save the current render states - myRenderer.PushStates(); - - // Setup the shader - myRenderer.SetShader(NULL); - - // Let the object draw itself - object.Draw(*this, myRenderer); - - // Restore the previous render states - myRenderer.PopStates(); - } -} - - -//////////////////////////////////////////////////////////// -void RenderTarget::Draw(const Drawable& object, const Shader& shader) -{ - if (Activate(true)) - { - // Update the projection matrix and viewport if the current view has changed - // Note: we do the changes here and not directly in SetView in order to gather - // rendering commands, which is safer in multithreaded environments - if (myViewHasChanged) - { - myRenderer.SetProjection(myCurrentView.GetMatrix()); - myRenderer.SetViewport(GetViewport(myCurrentView)); - myViewHasChanged = false; - } - - // Save the current render states - myRenderer.PushStates(); - - // Setup the shader - myRenderer.SetShader(&shader); - - // Let the object draw itself - object.Draw(*this, myRenderer); - - // Restore the previous render states - myRenderer.PopStates(); + GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)); + GLCheck(glClear(GL_COLOR_BUFFER_BIT)); } } @@ -124,16 +65,15 @@ void RenderTarget::Draw(const Drawable& object, const Shader& shader) //////////////////////////////////////////////////////////// void RenderTarget::SetView(const View& view) { - // Save it for later use - myCurrentView = view; - myViewHasChanged = true; + myView = view; + myViewChanged = true; } //////////////////////////////////////////////////////////// const View& RenderTarget::GetView() const { - return myCurrentView; + return myView; } @@ -175,35 +115,159 @@ Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y, const View& coords.y = 1.f - 2.f * (static_cast(y) - viewport.Top) / viewport.Height; // Then transform by the inverse of the view matrix - return view.GetInverseMatrix().Transform(coords); + return view.GetInverseTransform().TransformPoint(coords); } //////////////////////////////////////////////////////////// -void RenderTarget::SaveGLStates() +void RenderTarget::Draw(const Drawable& drawable, const RenderStates& states) { + drawable.Draw(*this, states); +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::Draw(const Vertex* vertices, unsigned int verticesCount, + PrimitiveType type, const RenderStates& states) +{ + // Nothing to draw? + if (!vertices || (verticesCount == 0)) + return; + if (Activate(true)) { - myRenderer.SaveGLStates(); - myStatesSaved = true; + // Apply the new view if needed + if (myViewChanged) + { + // Set the viewport + IntRect viewport = GetViewport(myView); + int top = GetHeight() - (viewport.Top + viewport.Height); + GLCheck(glViewport(viewport.Left, top, viewport.Width, viewport.Height)); - // Restore the render states and the current view, for SFML rendering - myRenderer.Initialize(); - SetView(GetView()); + // Set the projection matrix + GLCheck(glMatrixMode(GL_PROJECTION)); + GLCheck(glLoadMatrixf(myView.GetTransform().GetMatrix())); + + myViewChanged = false; + } + + // Apply the transform + GLCheck(glMatrixMode(GL_MODELVIEW)); + GLCheck(glLoadMatrixf(states.Transform.GetMatrix())); + + // Apply the blend mode + switch (states.BlendMode) + { + // Alpha blending + // glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target + // is a RenderTexture -- in this case the alpha value must be written directly to the target buffer + default : + case BlendAlpha : + if (GLEW_EXT_blend_func_separate) + GLCheck(glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); + else + GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + break; + + // Additive blending + case BlendAdd : + GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); + break; + + // Multiplicative blending + case BlendMultiply : + GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); + break; + + // No blending + case BlendNone : + GLCheck(glBlendFunc(GL_ONE, GL_ZERO)); + break; + } + + // Apply the texture + if (states.Texture) + states.Texture->Bind(Texture::Pixels); + else + GLCheck(glBindTexture(GL_TEXTURE_2D, 0)); + + // Apply the shader + if (states.Shader) + states.Shader->Bind(); + else + GLCheck(glUseProgramObjectARB(0)); + + // Setup the pointers to the vertices' components + const char* data = reinterpret_cast(vertices); + GLCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)); + GLCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)); + GLCheck(glTexCoordPointer(2, GL_INT, sizeof(Vertex), data + 12)); + + // Find the OpenGL primitive type + static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, + GL_TRIANGLES, GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, GL_QUADS}; + GLenum mode = modes[type]; + + // Draw the primitives + GLCheck(glDrawArrays(mode, 0, verticesCount)); } } //////////////////////////////////////////////////////////// -void RenderTarget::RestoreGLStates() +void RenderTarget::PushGLStates() { - if (myStatesSaved) + if (Activate(true)) { - if (Activate(true)) - { - myRenderer.RestoreGLStates(); - myStatesSaved = false; - } + GLCheck(glPushAttrib(GL_ALL_ATTRIB_BITS)); + GLCheck(glMatrixMode(GL_MODELVIEW)); + GLCheck(glPushMatrix()); + GLCheck(glMatrixMode(GL_PROJECTION)); + GLCheck(glPushMatrix()); + GLCheck(glMatrixMode(GL_TEXTURE)); + GLCheck(glPushMatrix()); + } + + ResetGLStates(); +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::PopGLStates() +{ + if (Activate(true)) + { + GLCheck(glPopAttrib()); + GLCheck(glMatrixMode(GL_PROJECTION)); + GLCheck(glPopMatrix()); + GLCheck(glMatrixMode(GL_MODELVIEW)); + GLCheck(glPopMatrix()); + GLCheck(glMatrixMode(GL_TEXTURE)); + GLCheck(glPopMatrix()); + } +} + + +//////////////////////////////////////////////////////////// +void RenderTarget::ResetGLStates() +{ + if (Activate(true)) + { + // Make sure that GLEW is initialized + priv::EnsureGlewInit(); + + GLCheck(glDisable(GL_LIGHTING)); + GLCheck(glDisable(GL_DEPTH_TEST)); + GLCheck(glEnable(GL_TEXTURE_2D)); + GLCheck(glEnable(GL_ALPHA_TEST)); + GLCheck(glEnable(GL_BLEND)); + GLCheck(glAlphaFunc(GL_GREATER, 0)); + GLCheck(glEnableClientState(GL_VERTEX_ARRAY)); + GLCheck(glEnableClientState(GL_COLOR_ARRAY)); + GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + + SetView(GetView()); } } @@ -215,9 +279,8 @@ void RenderTarget::Initialize() myDefaultView.Reset(FloatRect(0, 0, static_cast(GetWidth()), static_cast(GetHeight()))); SetView(myDefaultView); - // Initialize the renderer - if (Activate(true)) - myRenderer.Initialize(); + // Initialize the default OpenGL render-states + ResetGLStates(); } } // namespace sf diff --git a/src/SFML/Graphics/Renderer.cpp b/src/SFML/Graphics/Renderer.cpp deleted file mode 100644 index 82a60a545..000000000 --- a/src/SFML/Graphics/Renderer.cpp +++ /dev/null @@ -1,348 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) -// -// 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. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Renderer::Renderer(RenderTarget& target) : -myTarget (target), -myTextureIsValid (false), -myShaderIsValid (false), -myBlendModeIsValid(false), -myViewportIsValid (false) -{ - myStates = &myStatesStack[0]; -} - - -//////////////////////////////////////////////////////////// -void Renderer::Initialize() -{ - // Default render states - GLCheck(glDisable(GL_LIGHTING)); - GLCheck(glDisable(GL_DEPTH_TEST)); - GLCheck(glEnable(GL_TEXTURE_2D)); - GLCheck(glEnable(GL_ALPHA_TEST)); - GLCheck(glAlphaFunc(GL_GREATER, 0)); - - // Default transform matrices - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glLoadIdentity()); - GLCheck(glMatrixMode(GL_PROJECTION)); - GLCheck(glLoadIdentity()); - - // Invalidate the cached SFML states - myTextureIsValid = false; - myShaderIsValid = false; - myBlendModeIsValid = false; - myViewportIsValid = false; -} - - -//////////////////////////////////////////////////////////// -void Renderer::SaveGLStates() -{ - // Save render states - GLCheck(glPushAttrib(GL_ALL_ATTRIB_BITS)); - - // Save matrices - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glPushMatrix()); - GLCheck(glMatrixMode(GL_PROJECTION)); - GLCheck(glPushMatrix()); -} - - -//////////////////////////////////////////////////////////// -void Renderer::RestoreGLStates() -{ - // Restore render states - GLCheck(glPopAttrib()); - - // Restore matrices - GLCheck(glMatrixMode(GL_PROJECTION)); - GLCheck(glPopMatrix()); - GLCheck(glMatrixMode(GL_MODELVIEW)); - GLCheck(glPopMatrix()); -} - - -//////////////////////////////////////////////////////////// -void Renderer::Clear(const Color& color) -{ - GLCheck(glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f)); - GLCheck(glClear(GL_COLOR_BUFFER_BIT)); -} - - -//////////////////////////////////////////////////////////// -void Renderer::PushStates() -{ - myStates++; - *myStates = *(myStates - 1); -} - - -//////////////////////////////////////////////////////////// -void Renderer::PopStates() -{ - myStates--; -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetModelView(const Matrix3& matrix) -{ - myStates->modelView = matrix; -} - - -//////////////////////////////////////////////////////////// -void Renderer::ApplyModelView(const Matrix3& matrix) -{ - myStates->modelView = myStates->modelView * matrix; -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetProjection(const Matrix3& matrix) -{ - // Apply it immediately (this one is not critical for performances) - GLCheck(glMatrixMode(GL_PROJECTION)); - GLCheck(glLoadMatrixf(matrix.Get4x4Elements())); -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetColor(const Color& color) -{ - myStates->r = color.r / 255.f; - myStates->g = color.g / 255.f; - myStates->b = color.b / 255.f; - myStates->a = color.a / 255.f; -} - - -//////////////////////////////////////////////////////////// -void Renderer::ApplyColor(const Color& color) -{ - myStates->r *= color.r / 255.f; - myStates->g *= color.g / 255.f; - myStates->b *= color.b / 255.f; - myStates->a *= color.a / 255.f; -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetViewport(const IntRect& viewport) -{ - if ((viewport.Left != myViewport.Left) || (viewport.Width != myViewport.Width) || - (viewport.Top != myViewport.Top) || (viewport.Height != myViewport.Height) || - !myViewportIsValid) - { - // Revert the Y axis to match the OpenGL convention - int top = myTarget.GetHeight() - (viewport.Top + viewport.Height); - - // Apply the new viewport - GLCheck(glViewport(viewport.Left, top, viewport.Width, viewport.Height)); - - // Store it - myViewport = viewport; - myViewportIsValid = true; - } -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetBlendMode(Blend::Mode mode) -{ - if ((mode != myBlendMode) || !myBlendModeIsValid) - { - // Apply the new blending mode - if (mode == Blend::None) - { - GLCheck(glDisable(GL_BLEND)); - } - else - { - GLCheck(glEnable(GL_BLEND)); - - switch (mode) - { - // Alpha blending - // glBlendFuncSeparateEXT is used when available to avoid an incorrect alpha value when the target - // is a RenderTexture -- in this case the alpha value must be written directly to the target buffer - default : - case Blend::Alpha : - if (GLEW_EXT_blend_func_separate) - GLCheck(glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); - else - GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - break; - - // Additive blending - case Blend::Add : - GLCheck(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); - break; - - // Multiplicative blending - case Blend::Multiply : - GLCheck(glBlendFunc(GL_DST_COLOR, GL_ZERO)); - break; - } - } - - // Store it - myBlendMode = mode; - myBlendModeIsValid = true; - } -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetTexture(const Texture* texture) -{ - if ((texture != myTexture) || (texture && (texture->myTexture != myTextureId)) || !myTextureIsValid) - { - // Apply the new texture - if (texture) - texture->Bind(); - else - GLCheck(glBindTexture(GL_TEXTURE_2D, 0)); - - // Store it - myTexture = texture; - myTextureId = texture ? texture->myTexture : 0; - myTextureIsValid = true; - } -} - - -//////////////////////////////////////////////////////////// -void Renderer::SetShader(const Shader* shader) -{ - if ((shader != myShader) || !myShaderIsValid) - { - if (Shader::IsAvailable()) // to avoid calling possibly unsupported functions - { - // Apply the new shader - if (shader) - shader->Bind(); - else - GLCheck(glUseProgramObjectARB(0)); - - // Store it - myShader = shader; - myShaderIsValid = true; - } - } - else if (shader && myShaderIsValid) - { - // If the shader was already the current one, make sure that - // it is synchronized (in case it was modified since last use) - shader->Use(); - } -} - - -//////////////////////////////////////////////////////////// -void Renderer::Begin(PrimitiveType type) -{ - // Begin rendering - switch (type) - { - case TriangleList : glBegin(GL_TRIANGLES); break; - case TriangleStrip : glBegin(GL_TRIANGLE_STRIP); break; - case TriangleFan : glBegin(GL_TRIANGLE_FAN); break; - case QuadList : glBegin(GL_QUADS); break; - default: break; - } -} - - -//////////////////////////////////////////////////////////// -void Renderer::End() -{ - // End rendering - glEnd(); -} - - -//////////////////////////////////////////////////////////// -void Renderer::AddVertex(float x, float y) -{ - ProcessVertex(x, y, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f); -} - - -//////////////////////////////////////////////////////////// -void Renderer::AddVertex(float x, float y, float u, float v) -{ - ProcessVertex(x, y, u, v, 1.f, 1.f, 1.f, 1.f); -} - - -//////////////////////////////////////////////////////////// -void Renderer::AddVertex(float x, float y, const Color& color) -{ - ProcessVertex(x, y, 0.f, 0.f, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); -} - - -//////////////////////////////////////////////////////////// -void Renderer::AddVertex(float x, float y, float u, float v, const Color& color) -{ - ProcessVertex(x, y, u, v, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); -} - - -//////////////////////////////////////////////////////////// -void Renderer::ProcessVertex(float x, float y, float u, float v, float r, float g, float b, float a) -{ - // Transform the vertex position by the current model-view matrix - Vector2f position = myStates->modelView.Transform(Vector2f(x, y)); - - // Modulate the vertex color with the current global color - r *= myStates->r; - g *= myStates->g; - b *= myStates->b; - a *= myStates->a; - - // Render the vertex - glColor4f(r, g, b, a); - glTexCoord2f(u, v); - glVertex2f(position.x, position.y); -} - -} // namespace sf diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index e5c62fd66..7cdc3ea23 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -371,7 +371,7 @@ bool Shader::CompileProgram() static const char* vertexSrc = "void main()" "{" - " gl_TexCoord[0] = gl_MultiTexCoord0;" + " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;" " gl_FrontColor = gl_Color;" " gl_Position = ftransform();" "}"; diff --git a/src/SFML/Graphics/Shape.cpp b/src/SFML/Graphics/Shape.cpp index ed80496ff..9e17e4393 100644 --- a/src/SFML/Graphics/Shape.cpp +++ b/src/SFML/Graphics/Shape.cpp @@ -26,365 +26,271 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include +#include +#include #include +//////////////////////////////////////////////////////////// +// Private data +//////////////////////////////////////////////////////////// +namespace +{ + // Compute the normal of a segment + sf::Vector2f ComputeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2) + { + sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x); + float length = std::sqrt(normal.x * normal.x + normal.y * normal.y); + if (length != 0.f) + normal /= length; + return normal; + } +} + + namespace sf { //////////////////////////////////////////////////////////// -Shape::Shape() : -myOutline (0.f), -myIsFillEnabled (true), -myIsOutlineEnabled(true), -myIsCompiled (false) +Shape::~Shape() { - // Put a placeholder for the center of the shape - myPoints.push_back(Point()); } //////////////////////////////////////////////////////////// -void Shape::AddPoint(float x, float y, const Color& color, const Color& outlineColor) +void Shape::SetTexture(const Texture* texture, bool resetRect) { - AddPoint(Vector2f(x, y), color, outlineColor); + // Recompute the texture area if requested, or if there was no texture before + if (texture && (resetRect || !myTexture)) + SetTextureRect(IntRect(0, 0, texture->GetWidth(), texture->GetHeight())); + + // Assign the new texture + myTexture = texture; } //////////////////////////////////////////////////////////// -void Shape::AddPoint(const Vector2f& position, const Color& color, const Color& outlineColor) +const Texture* Shape::GetTexture() const { - myPoints.push_back(Point(position, color, outlineColor)); - myIsCompiled = false; + return myTexture; } //////////////////////////////////////////////////////////// -unsigned int Shape::GetPointsCount() const +void Shape::SetTextureRect(const IntRect& rect) { - return static_cast(myPoints.size() - 1); + myTextureRect = rect; + UpdateTexCoords(); } //////////////////////////////////////////////////////////// -void Shape::EnableFill(bool enable) +const IntRect& Shape::GetTextureRect() const { - myIsFillEnabled = enable; + return myTextureRect; } //////////////////////////////////////////////////////////// -void Shape::EnableOutline(bool enable) +void Shape::SetFillColor(const Color& color) { - myIsOutlineEnabled = enable; + myFillColor = color; + UpdateFillColors(); } //////////////////////////////////////////////////////////// -void Shape::SetPointPosition(unsigned int index, const Vector2f& position) +const Color& Shape::GetFillColor() const { - myPoints[index + 1].Position = position; - myIsCompiled = false; + return myFillColor; } //////////////////////////////////////////////////////////// -void Shape::SetPointPosition(unsigned int index, float x, float y) +void Shape::SetOutlineColor(const Color& color) { - SetPointPosition(index, Vector2f(x, y)); + myOutlineColor = color; + UpdateOutlineColors(); } //////////////////////////////////////////////////////////// -void Shape::SetPointColor(unsigned int index, const Color& color) +const Color& Shape::GetOutlineColor() const { - myPoints[index + 1].Col = color; - myIsCompiled = false; -} - - -//////////////////////////////////////////////////////////// -void Shape::SetPointOutlineColor(unsigned int index, const Color& color) -{ - myPoints[index + 1].OutlineCol = color; - myIsCompiled = false; + return myOutlineColor; } //////////////////////////////////////////////////////////// void Shape::SetOutlineThickness(float thickness) { - myOutline = thickness; -} - - -//////////////////////////////////////////////////////////// -const Vector2f& Shape::GetPointPosition(unsigned int index) const -{ - return myPoints[index + 1].Position; -} - - -//////////////////////////////////////////////////////////// -const Color& Shape::GetPointColor(unsigned int index) const -{ - return myPoints[index + 1].Col; -} - - -//////////////////////////////////////////////////////////// -const Color& Shape::GetPointOutlineColor(unsigned int index) const -{ - return myPoints[index + 1].OutlineCol; + myOutlineThickness = thickness; + Update(); // recompute everything because the whole shape must be offseted } //////////////////////////////////////////////////////////// float Shape::GetOutlineThickness() const { - return myOutline; + return myOutlineThickness; } //////////////////////////////////////////////////////////// -Shape Shape::Line(float p1x, float p1y, float p2x, float p2y, float thickness, const Color& color, float outline, const Color& outlineColor) +FloatRect Shape::GetLocalBounds() const { - Vector2f p1(p1x, p1y); - Vector2f p2(p2x, p2y); - - return Shape::Line(p1, p2, thickness, color, outline, outlineColor); + return myBounds; } //////////////////////////////////////////////////////////// -Shape Shape::Line(const Vector2f& p1, const Vector2f& p2, float thickness, const Color& color, float outline, const Color& outlineColor) +FloatRect Shape::GetGlobalBounds() const { - // Compute the extrusion direction - Vector2f normal; - ComputeNormal(p1, p2, normal); - normal *= thickness / 2; - - // Create the shape's points - Shape shape; - shape.AddPoint(p1 - normal, color, outlineColor); - shape.AddPoint(p2 - normal, color, outlineColor); - shape.AddPoint(p2 + normal, color, outlineColor); - shape.AddPoint(p1 + normal, color, outlineColor); - shape.SetOutlineThickness(outline); - - // Compile it - shape.Compile(); - - return shape; + return GetTransform().TransformRect(GetLocalBounds()); } //////////////////////////////////////////////////////////// -Shape Shape::Rectangle(float left, float top, float width, float height, const Color& color, float outline, const Color& outlineColor) +Shape::Shape() : +myTexture (NULL), +myTextureRect (), +myFillColor (255, 255, 255), +myOutlineColor (255, 255, 255), +myOutlineThickness(0), +myVertices (TrianglesFan), +myOutlineVertices (TrianglesStrip), +myInsideBounds (), +myBounds () { - // Create the shape's points - Shape shape; - shape.AddPoint(Vector2f(left, top), color, outlineColor); - shape.AddPoint(Vector2f(left + width, top), color, outlineColor); - shape.AddPoint(Vector2f(left + width, top + height), color, outlineColor); - shape.AddPoint(Vector2f(left, top + height), color, outlineColor); - shape.SetOutlineThickness(outline); - - // Compile it - shape.Compile(); - - return shape; } //////////////////////////////////////////////////////////// -Shape Shape::Rectangle(const FloatRect& rectangle, const Color& color, float outline, const Color& outlineColor) +void Shape::Update() { - return Shape::Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, color, outline, outlineColor); -} - - -//////////////////////////////////////////////////////////// -Shape Shape::Circle(float x, float y, float radius, const Color& color, float outline, const Color& outlineColor) -{ - return Shape::Circle(Vector2f(x, y), radius, color, outline, outlineColor); -} - - -//////////////////////////////////////////////////////////// -Shape Shape::Circle(const Vector2f& center, float radius, const Color& color, float outline, const Color& outlineColor) -{ - static const int nbSegments = 40; - - // Create the points set - Shape shape; - for (int i = 0; i < nbSegments; ++i) + // Get the total number of points of the shape + unsigned int count = GetOutlinePointsCount(); + if (count < 3) { - float angle = i * 2 * 3.141592654f / nbSegments; - Vector2f offset(std::cos(angle), std::sin(angle)); - - shape.AddPoint(center + offset * radius, color, outlineColor); - } - - // Compile it - shape.SetOutlineThickness(outline); - shape.Compile(); - - return shape; -} - - -//////////////////////////////////////////////////////////// -void Shape::Render(RenderTarget&, Renderer& renderer) const -{ - // Make sure the shape has at least 3 points (4 if we count the center) - if (myPoints.size() < 4) + sf::Err() << "Invalid shape: it has less than 3 points" << std::endl; + myVertices.Resize(0); + myOutlineVertices.Resize(0); return; - - // Make sure the shape is compiled - if (!myIsCompiled) - const_cast(this)->Compile(); - - // Shapes only use color, no texture - renderer.SetTexture(NULL); - - // Draw the shape - if (myIsFillEnabled) - { - if (myPoints.size() == 4) - { - // Special case of a triangle - renderer.Begin(Renderer::TriangleList); - renderer.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col); - renderer.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col); - renderer.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col); - renderer.End(); - } - else if (myPoints.size() == 5) - { - // Special case of a quad - renderer.Begin(Renderer::TriangleStrip); - renderer.AddVertex(myPoints[1].Position.x, myPoints[1].Position.y, myPoints[1].Col); - renderer.AddVertex(myPoints[2].Position.x, myPoints[2].Position.y, myPoints[2].Col); - renderer.AddVertex(myPoints[4].Position.x, myPoints[4].Position.y, myPoints[4].Col); - renderer.AddVertex(myPoints[3].Position.x, myPoints[3].Position.y, myPoints[3].Col); - renderer.End(); - } - else - { - renderer.Begin(Renderer::TriangleFan); - - // General case of a convex polygon - for (std::vector::const_iterator i = myPoints.begin(); i != myPoints.end(); ++i) - renderer.AddVertex(i->Position.x, i->Position.y, i->Col); - - // Close the shape by duplicating the first point at the end - const Point& first = myPoints[1]; - renderer.AddVertex(first.Position.x, first.Position.y, first.Col); - - renderer.End(); - } } - // Draw the outline - if (myIsOutlineEnabled && (myOutline != 0)) + myVertices.Resize(count + 2); // + 2 for center and repeated first point + + // Position + Vector2f offset(myOutlineThickness, myOutlineThickness); + for (unsigned int i = 0; i < count; ++i) + myVertices[i + 1].Position = GetOutlinePoint(i) + offset; + myVertices[count + 1].Position = myVertices[1].Position; + + // Update the bounding rectangle + myInsideBounds = myVertices.GetBounds(); + + // Compute the center and make it the first vertex + myVertices[0].Position.x = myInsideBounds.Left + myInsideBounds.Width / 2; + myVertices[0].Position.y = myInsideBounds.Top + myInsideBounds.Height / 2; + + // Color + UpdateFillColors(); + + // Texture coordinates + UpdateTexCoords(); + + // Outline + UpdateOutline(); +} + + +//////////////////////////////////////////////////////////// +void Shape::Draw(RenderTarget& target, RenderStates states) const +{ + states.Transform *= GetTransform(); + + // Render the inside + if (myFillColor.a > 0) { - renderer.Begin(Renderer::TriangleStrip); + states.Texture = myTexture; + target.Draw(myVertices, states); + } - for (std::vector::const_iterator i = myPoints.begin() + 1; i != myPoints.end(); ++i) - { - Vector2f point1 = i->Position; - Vector2f point2 = i->Position + i->Normal * myOutline; - renderer.AddVertex(point1.x, point1.y, i->OutlineCol); - renderer.AddVertex(point2.x, point2.y, i->OutlineCol); - } - - // Close the shape by duplicating the first point at the end - const Point& first = myPoints[1]; - Vector2f point1 = first.Position; - Vector2f point2 = first.Position + first.Normal * myOutline; - renderer.AddVertex(point1.x, point1.y, first.OutlineCol); - renderer.AddVertex(point2.x, point2.y, first.OutlineCol); - - renderer.End(); + // Render the outline + if ((myOutlineColor.a > 0) && (myOutlineThickness > 0)) + { + states.Texture = NULL; + target.Draw(myOutlineVertices, states); } } //////////////////////////////////////////////////////////// -void Shape::Compile() +void Shape::UpdateFillColors() { - // Compute the center - float nbPoints = static_cast(myPoints.size() - 1); - float r = 0, g = 0, b = 0, a = 0; - Point center(Vector2f(0, 0), Color(0, 0, 0, 0)); - for (std::size_t i = 1; i < myPoints.size(); ++i) - { - center.Position += myPoints[i].Position; - r += myPoints[i].Col.r; - g += myPoints[i].Col.g; - b += myPoints[i].Col.b; - a += myPoints[i].Col.a; - } - center.Position /= nbPoints; - center.Col.r = static_cast(r / nbPoints); - center.Col.g = static_cast(g / nbPoints); - center.Col.b = static_cast(b / nbPoints); - center.Col.a = static_cast(a / nbPoints); - myPoints[0] = center; + for (unsigned int i = 0; i < myVertices.GetVerticesCount(); ++i) + myVertices[i].Color = myFillColor; +} - // Compute the outline - for (std::size_t i = 1; i < myPoints.size(); ++i) + +//////////////////////////////////////////////////////////// +void Shape::UpdateTexCoords() +{ + for (unsigned int i = 0; i < myVertices.GetVerticesCount(); ++i) { + float xratio = (myVertices[i].Position.x - myInsideBounds.Left) / myInsideBounds.Width; + float yratio = (myVertices[i].Position.y - myInsideBounds.Top) / myInsideBounds.Height; + myVertices[i].TexCoords.x = static_cast(myTextureRect.Left + myTextureRect.Width * xratio); + myVertices[i].TexCoords.y = static_cast(myTextureRect.Top + myTextureRect.Height * yratio); + } +} + + +//////////////////////////////////////////////////////////// +void Shape::UpdateOutline() +{ + unsigned int count = myVertices.GetVerticesCount() - 2; + myOutlineVertices.Resize((count + 1) * 2); + + for (unsigned int i = 0; i < count; ++i) + { + unsigned int index = i + 1; + // Get the two segments shared by the current point - Point& p0 = (i == 1) ? myPoints[myPoints.size() - 1] : myPoints[i - 1]; - Point& p1 = myPoints[i]; - Point& p2 = (i == myPoints.size() - 1) ? myPoints[1] : myPoints[i + 1]; + Vector2f p0 = (i == 0) ? myVertices[count].Position : myVertices[index - 1].Position; + Vector2f p1 = myVertices[index].Position; + Vector2f p2 = myVertices[index + 1].Position; // Compute their normal - Vector2f normal1, normal2; - if (!ComputeNormal(p0.Position, p1.Position, normal1) || !ComputeNormal(p1.Position, p2.Position, normal2)) - continue; + Vector2f n1 = ComputeNormal(p0, p1); + Vector2f n2 = ComputeNormal(p1, p2); - // Add them to get the extrusion direction - float factor = 1.f + (normal1.x * normal2.x + normal1.y * normal2.y); - p1.Normal = (normal1 + normal2) / factor; + // Combine them to get the extrusion direction + float factor = 1.f + (n1.x * n2.x + n1.y * n2.y); + Vector2f normal = -(n1 + n2) / factor; - // Make sure it points towards the outside of the shape - float dot = (p1.Position.x - center.Position.x) * p1.Normal.x + (p1.Position.y - center.Position.y) * p1.Normal.y; - if (dot < 0) - p1.Normal = -p1.Normal; + // Update the outline points + myOutlineVertices[i * 2 + 0].Position = p1; + myOutlineVertices[i * 2 + 1].Position = p1 + normal * myOutlineThickness; } - myIsCompiled = true; + // Duplicate the first point at the end, to close the outline + myOutlineVertices[count * 2 + 0].Position = myOutlineVertices[0].Position; + myOutlineVertices[count * 2 + 1].Position = myOutlineVertices[1].Position; + + // Update outline colors + UpdateOutlineColors(); + + // Update the shape's bounds + myBounds = myOutlineVertices.GetBounds(); } //////////////////////////////////////////////////////////// -bool Shape::ComputeNormal(const Vector2f& p1, const Vector2f& p2, Vector2f& normal) +void Shape::UpdateOutlineColors() { - normal.x = p1.y - p2.y; - normal.y = p2.x - p1.x; - - float len = std::sqrt(normal.x * normal.x + normal.y * normal.y); - if (len == 0.f) - return false; - - normal.x /= len; - normal.y /= len; - - return true; -} - - -//////////////////////////////////////////////////////////// -Shape::Point::Point(const Vector2f& position, const Color& color, const Color& outlineColor) : -Position (position), -Normal (0.f, 0.f), -Col (color), -OutlineCol(outlineColor) -{ - + for (unsigned int i = 0; i < myOutlineVertices.GetVerticesCount(); ++i) + myOutlineVertices[i].Color = myOutlineColor; } } // namespace sf diff --git a/src/SFML/Graphics/Sprite.cpp b/src/SFML/Graphics/Sprite.cpp index 19405a7b6..23ac67a83 100644 --- a/src/SFML/Graphics/Sprite.cpp +++ b/src/SFML/Graphics/Sprite.cpp @@ -27,46 +27,44 @@ //////////////////////////////////////////////////////////// #include #include -#include -#include +#include namespace sf { //////////////////////////////////////////////////////////// Sprite::Sprite() : -Drawable (), -mySubRect (0, 0, 1, 1), -myIsFlippedX(false), -myIsFlippedY(false) +myTexture (NULL), +myTextureRect(0, 0, 0, 0) { - } //////////////////////////////////////////////////////////// Sprite::Sprite(const Texture& texture) : -Drawable (), -mySubRect (0, 0, 1, 1), -myIsFlippedX(false), -myIsFlippedY(false) +myTexture (NULL), +myTextureRect(0, 0, 0, 0) { SetTexture(texture); } //////////////////////////////////////////////////////////// -void Sprite::SetTexture(const Texture& texture, bool adjustToNewSize) +Sprite::Sprite(const Texture& texture, const IntRect& rectangle) : +myTexture (NULL), +myTextureRect(0, 0, 0, 0) { - // If there was no valid texture before, force adjusting to the new texture size - if (!myTexture) - adjustToNewSize = true; + SetTexture(texture); + SetTextureRect(rectangle); +} - // If we want to adjust the size and the new texture is valid, we adjust the source rectangle - if (adjustToNewSize && (texture.GetWidth() > 0) && (texture.GetHeight() > 0)) - { - SetSubRect(IntRect(0, 0, texture.GetWidth(), texture.GetHeight())); - } + +//////////////////////////////////////////////////////////// +void Sprite::SetTexture(const Texture& texture, bool resetRect) +{ + // Recompute the texture area if requested, or if there was no valid texture before + if (resetRect || !myTexture) + SetTextureRect(IntRect(0, 0, texture.GetWidth(), texture.GetHeight())); // Assign the new texture myTexture = &texture; @@ -74,38 +72,25 @@ void Sprite::SetTexture(const Texture& texture, bool adjustToNewSize) //////////////////////////////////////////////////////////// -void Sprite::SetSubRect(const IntRect& rectangle) +void Sprite::SetTextureRect(const IntRect& rectangle) { - mySubRect = rectangle; + if (rectangle != myTextureRect) + { + myTextureRect = rectangle; + UpdatePositions(); + UpdateTexCoords(); + } } //////////////////////////////////////////////////////////// -void Sprite::Resize(float width, float height) +void Sprite::SetColor(const Color& color) { - if ((mySubRect.Width > 0) && (mySubRect.Height > 0)) - SetScale(width / mySubRect.Width, height / mySubRect.Height); -} - - -//////////////////////////////////////////////////////////// -void Sprite::Resize(const Vector2f& size) -{ - Resize(size.x, size.y); -} - - -//////////////////////////////////////////////////////////// -void Sprite::FlipX(bool flipped) -{ - myIsFlippedX = flipped; -} - - -//////////////////////////////////////////////////////////// -void Sprite::FlipY(bool flipped) -{ - myIsFlippedY = flipped; + // Update the vertices' color + myVertices[0].Color = color; + myVertices[1].Color = color; + myVertices[2].Color = color; + myVertices[3].Color = color; } @@ -117,49 +102,73 @@ const Texture* Sprite::GetTexture() const //////////////////////////////////////////////////////////// -const IntRect& Sprite::GetSubRect() const +const IntRect& Sprite::GetTextureRect() const { - return mySubRect; + return myTextureRect; } //////////////////////////////////////////////////////////// -Vector2f Sprite::GetSize() const +const Color& Sprite::GetColor() const { - return Vector2f(mySubRect.Width * GetScale().x, mySubRect.Height * GetScale().y); + return myVertices[0].Color; } //////////////////////////////////////////////////////////// -void Sprite::Render(RenderTarget&, Renderer& renderer) const +FloatRect Sprite::GetLocalBounds() const { - // Get the sprite size - float width = static_cast(mySubRect.Width); - float height = static_cast(mySubRect.Height); + float width = static_cast(myTextureRect.Width); + float height = static_cast(myTextureRect.Height); - // Check if the texture is valid, and calculate the texture coordinates - FloatRect coords; + return FloatRect(0.f, 0.f, width, height); +} + + +//////////////////////////////////////////////////////////// +FloatRect Sprite::GetGlobalBounds() const +{ + return GetTransform().TransformRect(GetLocalBounds()); +} + + +//////////////////////////////////////////////////////////// +void Sprite::Draw(RenderTarget& target, RenderStates states) const +{ if (myTexture) - coords = myTexture->GetTexCoords(mySubRect); + { + states.Transform *= GetTransform(); + states.Texture = myTexture; + target.Draw(myVertices, 4, Quads, states); + } +} - // Compute the texture coordinates - float left = coords.Left; - float top = coords.Top; - float right = coords.Left + coords.Width; - float bottom = coords.Top + coords.Height; - if (myIsFlippedX) std::swap(left, right); - if (myIsFlippedY) std::swap(top, bottom); - // Bind the texture - renderer.SetTexture(myTexture); +//////////////////////////////////////////////////////////// +void Sprite::UpdatePositions() +{ + float width = static_cast(myTextureRect.Width); + float height = static_cast(myTextureRect.Height); - // Draw the sprite's geometry - renderer.Begin(Renderer::TriangleStrip); - renderer.AddVertex(0, 0, left, top); - renderer.AddVertex(width, 0, right, top); - renderer.AddVertex(0, height, left, bottom); - renderer.AddVertex(width, height, right, bottom); - renderer.End(); + myVertices[0].Position = Vector2f(0, 0); + myVertices[1].Position = Vector2f(0, height); + myVertices[2].Position = Vector2f(width, height); + myVertices[3].Position = Vector2f(width, 0); +} + + +//////////////////////////////////////////////////////////// +void Sprite::UpdateTexCoords() +{ + int left = myTextureRect.Left; + int right = myTextureRect.Left + myTextureRect.Width; + int top = myTextureRect.Top; + int bottom = myTextureRect.Top + myTextureRect.Height; + + myVertices[0].TexCoords = Vector2i(left, top); + myVertices[1].TexCoords = Vector2i(left, bottom); + myVertices[2].TexCoords = Vector2i(right, bottom); + myVertices[3].TexCoords = Vector2i(right, top); } } // namespace sf diff --git a/src/SFML/Graphics/StarShape.cpp b/src/SFML/Graphics/StarShape.cpp new file mode 100644 index 000000000..0f5696efe --- /dev/null +++ b/src/SFML/Graphics/StarShape.cpp @@ -0,0 +1,107 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +StarShape::StarShape() : +myInnerRadius(10), +myOuterRadius(20), +myPointsCount(5) +{ +} + + +//////////////////////////////////////////////////////////// +void StarShape::SetInnerRadius(float radius) +{ + myInnerRadius = radius; + Update(); +} + + +//////////////////////////////////////////////////////////// +float StarShape::GetInnerRadius() const +{ + return myInnerRadius; +} + + +//////////////////////////////////////////////////////////// +void StarShape::SetOuterRadius(float radius) +{ + myOuterRadius = radius; + Update(); +} + + +//////////////////////////////////////////////////////////// +float StarShape::GetOuterRadius() const +{ + return myOuterRadius; +} + + +//////////////////////////////////////////////////////////// +void StarShape::SetPointsCount(unsigned int count) +{ + myPointsCount = count; + Update(); +} + + +//////////////////////////////////////////////////////////// +unsigned int StarShape::GetPointsCount() const +{ + return myPointsCount; +} + + +//////////////////////////////////////////////////////////// +unsigned int StarShape::GetOutlinePointsCount() const +{ + return myPointsCount * 2; +} + + +//////////////////////////////////////////////////////////// +Vector2f StarShape::GetOutlinePoint(unsigned int index) const +{ + static const float pi = 3.141592654f; + float angle = index * pi / myPointsCount - pi / 2; + float x = std::cos(angle); + float y = std::sin(angle); + float radius = (index % 2 == 0 ? myOuterRadius : myInnerRadius); + + return Vector2f(myOuterRadius + x * radius, myOuterRadius + y * radius); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp index bed9c5e2b..cec998821 100644 --- a/src/SFML/Graphics/Text.cpp +++ b/src/SFML/Graphics/Text.cpp @@ -27,17 +27,20 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include +#include namespace sf { //////////////////////////////////////////////////////////// Text::Text() : +myString (), myFont (&Font::GetDefaultFont()), myCharacterSize(30), myStyle (Regular), -myRectUpdated (true) +myVertices (Quads), +myBounds () { } @@ -45,12 +48,14 @@ myRectUpdated (true) //////////////////////////////////////////////////////////// Text::Text(const String& string, const Font& font, unsigned int characterSize) : +myString (string), myFont (&font), myCharacterSize(characterSize), myStyle (Regular), -myRectUpdated (true) +myVertices (Quads), +myBounds () { - SetString(string); + UpdateGeometry(); } @@ -58,7 +63,7 @@ myRectUpdated (true) void Text::SetString(const String& string) { myString = string; - myRectUpdated = false; + UpdateGeometry(); } @@ -68,7 +73,7 @@ void Text::SetFont(const Font& font) if (myFont != &font) { myFont = &font; - myRectUpdated = false; + UpdateGeometry(); } } @@ -79,7 +84,7 @@ void Text::SetCharacterSize(unsigned int size) if (myCharacterSize != size) { myCharacterSize = size; - myRectUpdated = false; + UpdateGeometry(); } } @@ -90,7 +95,19 @@ void Text::SetStyle(unsigned long style) if (myStyle != style) { myStyle = style; - myRectUpdated = false; + UpdateGeometry(); + } +} + + +//////////////////////////////////////////////////////////// +void Text::SetColor(const Color& color) +{ + if (color != myColor) + { + myColor = color; + for (unsigned int i = 0; i < myVertices.GetVerticesCount(); ++i) + myVertices[i].Color = myColor; } } @@ -105,6 +122,7 @@ const String& Text::GetString() const //////////////////////////////////////////////////////////// const Font& Text::GetFont() const { + assert(myFont != NULL); // can never be NULL, always &Font::GetDefaultFont() by default return *myFont; } @@ -124,24 +142,29 @@ unsigned long Text::GetStyle() const //////////////////////////////////////////////////////////// -Vector2f Text::GetCharacterPos(std::size_t index) const +const Color& Text::GetColor() const { - // Make sure that we have a valid font - if (!myFont) - return Vector2f(0, 0); + return myColor; +} + + +//////////////////////////////////////////////////////////// +Vector2f Text::FindCharacterPos(std::size_t index) const +{ + assert(myFont != NULL); // Adjust the index if it's out of range if (index > myString.GetSize()) index = myString.GetSize(); - // We'll need this a lot - bool bold = (myStyle & Bold) != 0; - float space = static_cast(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); + // Precompute the variables needed by the algorithm + bool bold = (myStyle & Bold) != 0; + float hspace = static_cast(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); + float vspace = static_cast(myFont->GetLineSpacing(myCharacterSize)); // Compute the position Vector2f position; Uint32 prevChar = 0; - float lineSpacing = static_cast(myFont->GetLineSpacing(myCharacterSize)); for (std::size_t i = 0; i < index; ++i) { Uint32 curChar = myString[i]; @@ -153,69 +176,75 @@ Vector2f Text::GetCharacterPos(std::size_t index) const // Handle special characters switch (curChar) { - case L' ' : position.x += space; continue; - case L'\t' : position.x += space * 4; continue; - case L'\v' : position.y += lineSpacing * 4; continue; - case L'\n' : position.y += lineSpacing; position.x = 0; continue; + case L' ' : position.x += hspace; continue; + case L'\t' : position.x += hspace * 4; continue; + case L'\n' : position.y += vspace; position.x = 0; continue; + case L'\v' : position.y += vspace * 4; continue; } // For regular characters, add the advance offset of the glyph position.x += static_cast(myFont->GetGlyph(curChar, myCharacterSize, bold).Advance); } + // Transform the position to global coordinates + position = GetTransform().TransformPoint(position); + return position; } //////////////////////////////////////////////////////////// -FloatRect Text::GetRect() const +FloatRect Text::GetLocalBounds() const { - UpdateRect(); - - FloatRect rect; - rect.Left = (myBaseRect.Left - GetOrigin().x) * GetScale().x + GetPosition().x; - rect.Top = (myBaseRect.Top - GetOrigin().y) * GetScale().y + GetPosition().y; - rect.Width = myBaseRect.Width * GetScale().x; - rect.Height = myBaseRect.Height * GetScale().y; - - return rect; + return myBounds; } //////////////////////////////////////////////////////////// -void Text::Render(RenderTarget&, Renderer& renderer) const +FloatRect Text::GetGlobalBounds() const { - // No text or not font: nothing to render - if (!myFont || myString.IsEmpty()) + return GetTransform().TransformRect(GetLocalBounds()); +} + + +//////////////////////////////////////////////////////////// +void Text::Draw(RenderTarget& target, RenderStates states) const +{ + assert(myFont != NULL); + + states.Transform *= GetTransform(); + states.BlendMode = BlendAlpha; // alpha blending is mandatory for proper text rendering + states.Texture = &myFont->GetTexture(myCharacterSize); + target.Draw(myVertices, states); +} + + +//////////////////////////////////////////////////////////// +void Text::UpdateGeometry() +{ + assert(myFont != NULL); + + // Clear the previous geometry + myVertices.Clear(); + + // No text: nothing to draw + if (myString.IsEmpty()) return; - // Bind the font texture - const Texture& texture = myFont->GetTexture(myCharacterSize); - renderer.SetTexture(&texture); + // Compute values related to the text style + bool bold = (myStyle & Bold) != 0; + bool underlined = (myStyle & Underlined) != 0; + float italic = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees + float underlineOffset = myCharacterSize * 0.1f; + float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f); - // Computes values related to the text style - bool bold = (myStyle & Bold) != 0; - bool underlined = (myStyle & Underlined) != 0; - float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees - float underlineOffset = myCharacterSize * 0.1f; - float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f); - FloatRect underlineCoords = texture.GetTexCoords(IntRect(1, 1, 1, 1)); - float underlineLeft = underlineCoords.Left; - float underlineTop = underlineCoords.Top; - float underlineRight = underlineCoords.Left + underlineCoords.Width; - float underlineBottom = underlineCoords.Top + underlineCoords.Height; + // Precompute the variables needed by the algorithm + float hspace = static_cast(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); + float vspace = static_cast(myFont->GetLineSpacing(myCharacterSize)); + float x = 0.f; + float y = static_cast(myCharacterSize); - // Initialize the rendering coordinates - float space = static_cast(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); - float lineSpacing = static_cast(myFont->GetLineSpacing(myCharacterSize)); - float x = 0.f; - float y = static_cast(myCharacterSize); - - // Note: - // Here we use a Begin/End pair for each quad because - // the font's texture may change in a call to GetGlyph - - // Draw one quad for each character + // Create one quad for each character Uint32 prevChar = 0; for (std::size_t i = 0; i < myString.GetSize(); ++i) { @@ -231,44 +260,42 @@ void Text::Render(RenderTarget&, Renderer& renderer) const float top = y + underlineOffset; float bottom = top + underlineThickness; - renderer.Begin(Renderer::QuadList); - renderer.AddVertex(0, top, underlineLeft, underlineTop); - renderer.AddVertex(x, top, underlineRight, underlineTop); - renderer.AddVertex(x, bottom, underlineRight, underlineBottom); - renderer.AddVertex(0, bottom, underlineLeft, underlineBottom); - renderer.End(); + myVertices.Append(Vertex(Vector2f(0, top), myColor, Vector2i(1, 1))); + myVertices.Append(Vertex(Vector2f(x, top), myColor, Vector2i(2, 1))); + myVertices.Append(Vertex(Vector2f(x, bottom), myColor, Vector2i(2, 2))); + myVertices.Append(Vertex(Vector2f(0, bottom), myColor, Vector2i(1, 2))); } // Handle special characters switch (curChar) { - case L' ' : x += space; continue; - case L'\t' : x += space * 4; continue; - case L'\n' : y += lineSpacing; x = 0; continue; - case L'\v' : y += lineSpacing * 4; continue; + case L' ' : x += hspace; continue; + case L'\t' : x += hspace * 4; continue; + case L'\n' : y += vspace; x = 0; continue; + case L'\v' : y += vspace * 4; continue; } // Extract the current glyph's description - const Glyph& glyph = myFont->GetGlyph(curChar, myCharacterSize, bold); - int advance = glyph.Advance; - const IntRect& bounds = glyph.Bounds; - FloatRect coords = texture.GetTexCoords(glyph.SubRect); + const Glyph& glyph = myFont->GetGlyph(curChar, myCharacterSize, bold); - int boundsRight = bounds.Left + bounds.Width; - int boundsBottom = bounds.Top + bounds.Height; - float coordsRight = coords.Left + coords.Width; - float coordsBottom = coords.Top + coords.Height; + int left = glyph.Bounds.Left; + int top = glyph.Bounds.Top; + int right = glyph.Bounds.Left + glyph.Bounds.Width; + int bottom = glyph.Bounds.Top + glyph.Bounds.Height; - // Draw a textured quad for the current character - renderer.Begin(Renderer::QuadList); - renderer.AddVertex(x + bounds.Left - italicCoeff * bounds.Top, y + bounds.Top, coords.Left, coords.Top); - renderer.AddVertex(x + boundsRight - italicCoeff * bounds.Top, y + bounds.Top, coordsRight, coords.Top); - renderer.AddVertex(x + boundsRight - italicCoeff * boundsBottom, y + boundsBottom, coordsRight, coordsBottom); - renderer.AddVertex(x + bounds.Left - italicCoeff * boundsBottom, y + boundsBottom, coords.Left, coordsBottom); - renderer.End(); + int u1 = glyph.TextureRect.Left; + int v1 = glyph.TextureRect.Top; + int u2 = glyph.TextureRect.Left + glyph.TextureRect.Width; + int v2 = glyph.TextureRect.Top + glyph.TextureRect.Height; + + // Add a quad for the current character + myVertices.Append(Vertex(Vector2f(x + left - italic * top, y + top), myColor, Vector2i(u1, v1))); + myVertices.Append(Vertex(Vector2f(x + right - italic * top, y + top), myColor, Vector2i(u2, v1))); + myVertices.Append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), myColor, Vector2i(u2, v2))); + myVertices.Append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), myColor, Vector2i(u1, v2))); // Advance to the next character - x += advance; + x += glyph.Advance; } // If we're using the underlined style, add the last line @@ -277,113 +304,14 @@ void Text::Render(RenderTarget&, Renderer& renderer) const float top = y + underlineOffset; float bottom = top + underlineThickness; - renderer.Begin(Renderer::QuadList); - renderer.AddVertex(0, top, underlineLeft, underlineTop); - renderer.AddVertex(x, top, underlineRight, underlineTop); - renderer.AddVertex(x, bottom, underlineRight, underlineBottom); - renderer.AddVertex(0, bottom, underlineLeft, underlineBottom); - renderer.End(); - } -} - - -//////////////////////////////////////////////////////////// -void Text::UpdateRect() const -{ - if (myRectUpdated) - return; - - // Reset the previous states - myRectUpdated = true; - myBaseRect = FloatRect(0, 0, 0, 0); - - // No text or not font: empty box - if (!myFont || myString.IsEmpty()) - return; - - // Initial values - bool bold = (myStyle & Bold) != 0; - float charSize = static_cast(myCharacterSize); - float space = static_cast(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance); - float lineSpacing = static_cast(myFont->GetLineSpacing(myCharacterSize)); - float curWidth = 0; - float curHeight = 0; - float width = 0; - float height = 0; - Uint32 prevChar = 0; - - // Go through each character - for (std::size_t i = 0; i < myString.GetSize(); ++i) - { - Uint32 curChar = myString[i]; - - // Apply the kerning offset - curWidth += static_cast(myFont->GetKerning(prevChar, curChar, myCharacterSize)); - prevChar = curChar; - - // Handle special characters - switch (curChar) - { - case L' ' : - curWidth += space; - continue; - - case L'\t' : - curWidth += space * 4; - continue; - - case L'\v' : - height += lineSpacing * 4; - curHeight = 0; - continue; - - case L'\n' : - height += lineSpacing; - curHeight = 0; - if (curWidth > width) - width = curWidth; - curWidth = 0; - continue; - } - - // Extract the current glyph's description - const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize, bold); - - // Advance to the next character - curWidth += static_cast(curGlyph.Advance); - - // Update the maximum height - float charHeight = charSize + curGlyph.Bounds.Top + curGlyph.Bounds.Height; - if (charHeight > curHeight) - curHeight = charHeight; + myVertices.Append(Vertex(Vector2f(0, top), myColor, Vector2i(1, 1))); + myVertices.Append(Vertex(Vector2f(x, top), myColor, Vector2i(2, 1))); + myVertices.Append(Vertex(Vector2f(x, bottom), myColor, Vector2i(2, 2))); + myVertices.Append(Vertex(Vector2f(0, bottom), myColor, Vector2i(1, 2))); } - // Update the last line - if (curWidth > width) - width = curWidth; - height += curHeight; - - // Add a slight width if we're using the italic style - if (myStyle & Italic) - { - width += 0.208f * charSize; - } - - // Add a slight height if we're using the underlined style - if (myStyle & Underlined) - { - float underlineOffset = myCharacterSize * 0.1f; - float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f); - - if (curHeight < charSize + underlineOffset + underlineThickness) - height += underlineOffset + underlineThickness; - } - - // Finally update the rectangle - myBaseRect.Left = 0; - myBaseRect.Top = 0; - myBaseRect.Width = width; - myBaseRect.Height = height; + // Recompute the bounding rectangle + myBounds = myVertices.GetBounds(); } } // namespace sf diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index e623e325f..0c07cf347 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -44,6 +44,7 @@ myTextureWidth (0), myTextureHeight(0), myTexture (0), myIsSmooth (false), +myIsRepeated (false), myPixelsFlipped(false) { @@ -59,6 +60,7 @@ myTextureWidth (0), myTextureHeight(0), myTexture (0), myIsSmooth (copy.myIsSmooth), +myIsRepeated (copy.myIsRepeated), myPixelsFlipped(false) { LoadFromImage(copy.CopyToImage()); @@ -124,8 +126,8 @@ bool Texture::Create(unsigned int width, unsigned int height) // Initialize the texture GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); GLCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, myTextureWidth, myTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, myIsRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, myIsRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myIsSmooth ? GL_LINEAR : GL_NEAREST)); @@ -347,9 +349,38 @@ void Texture::Update(const Window& window, unsigned int x, unsigned int y) //////////////////////////////////////////////////////////// -void Texture::Bind() const +void Texture::Bind(CoordinateType coordinateType) const { + // Bind the texture GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + + // Check if we need to define a special texture matrix + if ((coordinateType == Pixels) || myPixelsFlipped) + { + GLfloat matrix[16] = {1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f}; + + // If non-normalized coordinates (= pixels) are requested, we need to + // setup scale factors that convert the range [0 .. size] to [0 .. 1] + if (coordinateType == Pixels) + { + matrix[0] = 1.f / myTextureWidth; + matrix[5] = 1.f / myTextureHeight; + } + + // If pixels are flipped we must invert the Y axis + if (myPixelsFlipped) + { + matrix[5] = -matrix[5]; + matrix[13] = static_cast(myHeight / myTextureHeight); + } + + // Load the matrix + GLCheck(glMatrixMode(GL_TEXTURE)); + GLCheck(glLoadMatrixf(matrix)); + } } @@ -380,32 +411,28 @@ bool Texture::IsSmooth() const //////////////////////////////////////////////////////////// -FloatRect Texture::GetTexCoords(const IntRect& rect) const +void Texture::SetRepeated(bool repeated) { - if ((myTextureWidth != 0) && (myTextureHeight != 0)) + if (repeated != myIsRepeated) { - float width = static_cast(myTextureWidth); - float height = static_cast(myTextureHeight); + myIsRepeated = repeated; - if (myPixelsFlipped) + if (myTexture) { - return FloatRect( rect.Left / width, - (myHeight - rect.Top) / height, - rect.Width / width, - -rect.Height / height); - } - else - { - return FloatRect(rect.Left / width, - rect.Top / height, - rect.Width / width, - rect.Height / height); + EnsureGlContext(); + + GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, myIsRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); + GLCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, myIsRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); } } - else - { - return FloatRect(0, 0, 0, 0); - } +} + + +//////////////////////////////////////////////////////////// +bool Texture::IsRepeated() const +{ + return myIsRepeated; } @@ -432,6 +459,7 @@ Texture& Texture::operator =(const Texture& right) std::swap(myTextureHeight, temp.myTextureHeight); std::swap(myTexture, temp.myTexture); std::swap(myIsSmooth, temp.myIsSmooth); + std::swap(myIsRepeated, temp.myIsRepeated); std::swap(myPixelsFlipped, temp.myPixelsFlipped); return *this; diff --git a/src/SFML/Graphics/Transform.cpp b/src/SFML/Graphics/Transform.cpp new file mode 100644 index 000000000..181e1bbd8 --- /dev/null +++ b/src/SFML/Graphics/Transform.cpp @@ -0,0 +1,270 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +const Transform Transform::Identity; + + +//////////////////////////////////////////////////////////// +Transform::Transform() +{ + // Identity matrix + myMatrix[0] = 1.f; myMatrix[4] = 0.f; myMatrix[8] = 0.f; myMatrix[12] = 0.f; + myMatrix[1] = 0.f; myMatrix[5] = 1.f; myMatrix[9] = 0.f; myMatrix[13] = 0.f; + myMatrix[2] = 0.f; myMatrix[6] = 0.f; myMatrix[10] = 1.f; myMatrix[14] = 0.f; + myMatrix[3] = 0.f; myMatrix[7] = 0.f; myMatrix[11] = 0.f; myMatrix[15] = 1.f; +} + + +//////////////////////////////////////////////////////////// +Transform::Transform(float a00, float a01, float a02, + float a10, float a11, float a12, + float a20, float a21, float a22) +{ + myMatrix[0] = a00; myMatrix[4] = a01; myMatrix[8] = 0.f; myMatrix[12] = a02; + myMatrix[1] = a10; myMatrix[5] = a11; myMatrix[9] = 0.f; myMatrix[13] = a12; + myMatrix[2] = 0.f; myMatrix[6] = 0.f; myMatrix[10] = 1.f; myMatrix[14] = 0.f; + myMatrix[3] = a20; myMatrix[7] = a21; myMatrix[11] = 0.f; myMatrix[15] = a22; +} + + +//////////////////////////////////////////////////////////// +const float* Transform::GetMatrix() const +{ + return myMatrix; +} + + +//////////////////////////////////////////////////////////// +Transform Transform::GetInverse() const +{ + // Compute the determinant + float det = myMatrix[0] * (myMatrix[15] * myMatrix[5] - myMatrix[7] * myMatrix[13]) - + myMatrix[1] * (myMatrix[15] * myMatrix[4] - myMatrix[7] * myMatrix[12]) + + myMatrix[3] * (myMatrix[13] * myMatrix[4] - myMatrix[5] * myMatrix[12]); + + // Compute the inverse if the determinant is not zero + // (don't use an epsilon because the determinant may *really* be tiny) + if (det != 0.f) + { + return Transform( (myMatrix[15] * myMatrix[5] - myMatrix[7] * myMatrix[13]) / det, + -(myMatrix[15] * myMatrix[4] - myMatrix[7] * myMatrix[12]) / det, + (myMatrix[13] * myMatrix[4] - myMatrix[5] * myMatrix[12]) / det, + -(myMatrix[15] * myMatrix[1] - myMatrix[3] * myMatrix[13]) / det, + (myMatrix[15] * myMatrix[0] - myMatrix[3] * myMatrix[12]) / det, + -(myMatrix[13] * myMatrix[0] - myMatrix[1] * myMatrix[12]) / det, + (myMatrix[7] * myMatrix[1] - myMatrix[3] * myMatrix[5]) / det, + -(myMatrix[7] * myMatrix[0] - myMatrix[3] * myMatrix[4]) / det, + (myMatrix[5] * myMatrix[0] - myMatrix[1] * myMatrix[4]) / det); + } + else + { + return Transform(); + } +} + + +//////////////////////////////////////////////////////////// +Vector2f Transform::TransformPoint(float x, float y) const +{ + return Vector2f(myMatrix[0] * x + myMatrix[4] * y + myMatrix[12], + myMatrix[1] * x + myMatrix[5] * y + myMatrix[13]); +} + + +//////////////////////////////////////////////////////////// +Vector2f Transform::TransformPoint(const Vector2f& point) const +{ + return TransformPoint(point.x, point.y); +} + + +//////////////////////////////////////////////////////////// +FloatRect Transform::TransformRect(const FloatRect& rectangle) const +{ + // Transform the 4 corners of the rectangle + const Vector2f points[] = + { + TransformPoint(rectangle.Left, rectangle.Top), + TransformPoint(rectangle.Left, rectangle.Top + rectangle.Height), + TransformPoint(rectangle.Left + rectangle.Width, rectangle.Top), + TransformPoint(rectangle.Left + rectangle.Width, rectangle.Top + rectangle.Height) + }; + + // Compute the bounding rectangle of the transformed points + float left = points[0].x; + float top = points[0].y; + float right = points[0].x; + float bottom = points[0].y; + for (int i = 1; i < 4; ++i) + { + if (points[i].x < left) left = points[i].x; + else if (points[i].x > right) right = points[i].x; + if (points[i].y < top) top = points[i].y; + else if (points[i].y > bottom) bottom = points[i].y; + } + + return FloatRect(left, top, right - left, bottom - top); +} + + +//////////////////////////////////////////////////////////// +Transform Transform::Combine(const Transform& transform) const +{ + const float* a = myMatrix; + const float* b = transform.myMatrix; + + return Transform(a[0] * b[0] + a[4] * b[1] + a[12] * b[3], + a[0] * b[4] + a[4] * b[5] + a[12] * b[7], + a[0] * b[12] + a[4] * b[13] + a[12] * b[15], + a[1] * b[0] + a[5] * b[1] + a[13] * b[3], + a[1] * b[4] + a[5] * b[5] + a[13] * b[7], + a[1] * b[12] + a[5] * b[13] + a[13] * b[15], + a[3] * b[0] + a[7] * b[1] + a[15] * b[3], + a[3] * b[4] + a[7] * b[5] + a[15] * b[7], + a[3] * b[12] + a[7] * b[13] + a[15] * b[15]); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Translate(float x, float y) +{ + Transform translation(1, 0, x, + 0, 1, y, + 0, 0, 1); + + return *this = Combine(translation); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Translate(const Vector2f& offset) +{ + return Translate(offset.x, offset.y); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Rotate(float angle) +{ + float rad = angle * 3.141592654f / 180.f; + float cos = std::cos(rad); + float sin = std::sin(rad); + + Transform rotation(cos, -sin, 0, + sin, cos, 0, + 0, 0, 1); + + return *this = Combine(rotation); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Rotate(float angle, float centerX, float centerY) +{ + float rad = angle * 3.141592654f / 180.f; + float cos = std::cos(rad); + float sin = std::sin(rad); + + Transform rotation(cos, -sin, centerX * (1 - cos) + centerY * sin, + sin, cos, centerY * (1 - cos) - centerX * sin, + 0, 0, 1); + + return *this = Combine(rotation); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Rotate(float angle, const Vector2f& center) +{ + return Rotate(angle, center.x, center.y); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Scale(float scaleX, float scaleY) +{ + Transform scaling(scaleX, 0, 0, + 0, scaleY, 0, + 0, 0, 1); + + return *this = Combine(scaling); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Scale(float scaleX, float scaleY, float centerX, float centerY) +{ + Transform scaling(scaleX, 0, centerX * (1 - scaleX), + 0, scaleY, centerY * (1 - scaleY), + 0, 0, 1); + + return *this = Combine(scaling); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Scale(const Vector2f& factors) +{ + return Scale(factors.x, factors.y); +} + + +//////////////////////////////////////////////////////////// +Transform& Transform::Scale(const Vector2f& factors, const Vector2f& center) +{ + return Scale(factors.x, factors.y, center.x, center.y); +} + + +//////////////////////////////////////////////////////////// +Transform operator *(const Transform& left, const Transform& right) +{ + return left.Combine(right); +} + + +//////////////////////////////////////////////////////////// +Transform& operator *=(Transform& left, const Transform& right) +{ + return left = left.Combine(right); +} + + +//////////////////////////////////////////////////////////// +Vector2f operator *(const Transform& left, const Vector2f& right) +{ + return left.TransformPoint(right); +} + +} // namespace sf diff --git a/src/SFML/Graphics/Transformable.cpp b/src/SFML/Graphics/Transformable.cpp new file mode 100644 index 000000000..31130bac7 --- /dev/null +++ b/src/SFML/Graphics/Transformable.cpp @@ -0,0 +1,210 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Transformable::Transformable() : +myOrigin (0, 0), +myPosition (0, 0), +myRotation (0), +myScale (1, 1), +myTransform (), +myTransformNeedUpdate (true), +myInverseTransform (), +myInverseTransformNeedUpdate(true) +{ +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetPosition(float x, float y) +{ + myPosition.x = x; + myPosition.y = y; + myTransformNeedUpdate = true; + myInverseTransformNeedUpdate = true; +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetPosition(const Vector2f& position) +{ + SetPosition(position.x, position.y); +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetRotation(float angle) +{ + myRotation = angle; + myTransformNeedUpdate = true; + myInverseTransformNeedUpdate = true; +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetScale(float factorX, float factorY) +{ + myScale.x = factorX; + myScale.y = factorY; + myTransformNeedUpdate = true; + myInverseTransformNeedUpdate = true; +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetScale(const Vector2f& factors) +{ + SetScale(factors.x, factors.y); +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetOrigin(float x, float y) +{ + myOrigin.x = x; + myOrigin.y = y; + myTransformNeedUpdate = true; + myInverseTransformNeedUpdate = true; +} + + +//////////////////////////////////////////////////////////// +void Transformable::SetOrigin(const Vector2f& origin) +{ + SetOrigin(origin.x, origin.y); +} + + +//////////////////////////////////////////////////////////// +const Vector2f& Transformable::GetPosition() const +{ + return myPosition; +} + + +//////////////////////////////////////////////////////////// +float Transformable::GetRotation() const +{ + return myRotation; +} + + +//////////////////////////////////////////////////////////// +const Vector2f& Transformable::GetScale() const +{ + return myScale; +} + + +//////////////////////////////////////////////////////////// +const Vector2f& Transformable::GetOrigin() const +{ + return myOrigin; +} + + +//////////////////////////////////////////////////////////// +void Transformable::Move(float offsetX, float offsetY) +{ + SetPosition(myPosition.x + offsetX, myPosition.y + offsetY); +} + + +//////////////////////////////////////////////////////////// +void Transformable::Move(const Vector2f& offset) +{ + SetPosition(myPosition.x + offset.x, myPosition.y + offset.y); +} + + +//////////////////////////////////////////////////////////// +void Transformable::Rotate(float angle) +{ + SetRotation(myRotation + angle); +} + + +//////////////////////////////////////////////////////////// +void Transformable::Scale(float factorX, float factorY) +{ + SetScale(myScale.x * factorX, myScale.y * factorY); +} + + +//////////////////////////////////////////////////////////// +void Transformable::Scale(const Vector2f& factor) +{ + SetScale(myScale.x * factor.x, myScale.y * factor.y); +} + + +//////////////////////////////////////////////////////////// +const Transform& Transformable::GetTransform() const +{ + // Recompute the combined transform if needed + if (myTransformNeedUpdate) + { + float angle = -myRotation * 3.141592654f / 180.f; + float cosine = static_cast(std::cos(angle)); + float sine = static_cast(std::sin(angle)); + float sxc = myScale.x * cosine; + float syc = myScale.y * cosine; + float sxs = myScale.x * sine; + float sys = myScale.y * sine; + float tx = -myOrigin.x * sxc - myOrigin.y * sys + myPosition.x; + float ty = myOrigin.x * sxs - myOrigin.y * syc + myPosition.y; + + myTransform = Transform( sxc, sys, tx, + -sxs, syc, ty, + 0.f, 0.f, 1.f); + myTransformNeedUpdate = false; + } + + return myTransform; +} + + +//////////////////////////////////////////////////////////// +const Transform& Transformable::GetInverseTransform() const +{ + // Recompute the inverse transform if needed + if (myInverseTransformNeedUpdate) + { + myInverseTransform = GetTransform().GetInverse(); + myInverseTransformNeedUpdate = false; + } + + return myInverseTransform; +} + +} // namespace sf diff --git a/src/SFML/Graphics/Vertex.cpp b/src/SFML/Graphics/Vertex.cpp new file mode 100644 index 000000000..43cf19056 --- /dev/null +++ b/src/SFML/Graphics/Vertex.cpp @@ -0,0 +1,77 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +Vertex::Vertex() : +Position (0, 0), +Color (255, 255, 255), +TexCoords(0, 0) +{ +} + + +//////////////////////////////////////////////////////////// +Vertex::Vertex(const Vector2f& position) : +Position (position), +Color (255, 255, 255), +TexCoords(0, 0) +{ +} + + +//////////////////////////////////////////////////////////// +Vertex::Vertex(const Vector2f& position, const sf::Color& color) : +Position (position), +Color (color), +TexCoords(0, 0) +{ +} + + +//////////////////////////////////////////////////////////// +Vertex::Vertex(const Vector2f& position, const Vector2i& texCoords) : +Position (position), +Color (255, 255, 255), +TexCoords(texCoords) +{ +} + + +//////////////////////////////////////////////////////////// +Vertex::Vertex(const Vector2f& position, const sf::Color& color, const Vector2i& texCoords) : +Position (position), +Color (color), +TexCoords(texCoords) +{ +} + +} // namespace sf diff --git a/src/SFML/Graphics/VertexArray.cpp b/src/SFML/Graphics/VertexArray.cpp new file mode 100644 index 000000000..eeb1d2300 --- /dev/null +++ b/src/SFML/Graphics/VertexArray.cpp @@ -0,0 +1,150 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) +// +// 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. +// +//////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +VertexArray::VertexArray() : +myVertices (), +myPrimitiveType(Points) +{ +} + + +//////////////////////////////////////////////////////////// +VertexArray::VertexArray(PrimitiveType type, unsigned int verticesCount) : +myVertices (verticesCount), +myPrimitiveType(type) +{ +} + + +//////////////////////////////////////////////////////////// +unsigned int VertexArray::GetVerticesCount() const +{ + return myVertices.size(); +} + + +//////////////////////////////////////////////////////////// +Vertex& VertexArray::operator [](unsigned int index) +{ + return myVertices[index]; +} + + +//////////////////////////////////////////////////////////// +const Vertex& VertexArray::operator [](unsigned int index) const +{ + return myVertices[index]; +} + + +//////////////////////////////////////////////////////////// +void VertexArray::Clear() +{ + myVertices.clear(); +} + + +//////////////////////////////////////////////////////////// +void VertexArray::Resize(unsigned int verticesCount) +{ + myVertices.resize(verticesCount); +} + + +//////////////////////////////////////////////////////////// +void VertexArray::Append(const Vertex& vertex) +{ + myVertices.push_back(vertex); +} + + +//////////////////////////////////////////////////////////// +void VertexArray::SetPrimitiveType(PrimitiveType type) +{ + myPrimitiveType = type; +} + + +//////////////////////////////////////////////////////////// +PrimitiveType VertexArray::GetPrimitiveType() const +{ + return myPrimitiveType; +} + + +//////////////////////////////////////////////////////////// +FloatRect VertexArray::GetBounds() const +{ + if (!myVertices.empty()) + { + float left = myVertices[0].Position.x; + float top = myVertices[0].Position.y; + float right = myVertices[0].Position.x; + float bottom = myVertices[0].Position.y; + + for (std::size_t i = 0; i < myVertices.size(); ++i) + { + Vector2f position = myVertices[i].Position; + + // Update left and right + if (position.x < left) + left = position.x; + else if (position.x > right) + right = position.x; + + // Update top and bottom + if (position.y < top) + top = position.y; + else if (position.y > bottom) + bottom = position.y; + } + + return FloatRect(left, top, right - left, bottom - top); + } + else + { + // Array is empty + return FloatRect(); + } +} + + +//////////////////////////////////////////////////////////// +void VertexArray::Draw(RenderTarget& target, RenderStates states) const +{ + if (!myVertices.empty()) + target.Draw(&myVertices[0], myVertices.size(), myPrimitiveType, states); +} + +} // namespace sf diff --git a/src/SFML/Graphics/View.cpp b/src/SFML/Graphics/View.cpp index 7c012ed82..ec95ddbaf 100644 --- a/src/SFML/Graphics/View.cpp +++ b/src/SFML/Graphics/View.cpp @@ -26,18 +26,19 @@ // Headers //////////////////////////////////////////////////////////// #include +#include namespace sf { //////////////////////////////////////////////////////////// View::View() : -myCenter (), -mySize (), -myRotation (0), -myViewport (0, 0, 1, 1), -myMatrixUpdated (false), -myInvMatrixUpdated(false) +myCenter (), +mySize (), +myRotation (0), +myViewport (0, 0, 1, 1), +myTransformUpdated (false), +myInvTransformUpdated(false) { Reset(FloatRect(0, 0, 1000, 1000)); } @@ -45,12 +46,12 @@ myInvMatrixUpdated(false) //////////////////////////////////////////////////////////// View::View(const FloatRect& rectangle) : -myCenter (), -mySize (), -myRotation (0), -myViewport (0, 0, 1, 1), -myMatrixUpdated (false), -myInvMatrixUpdated(false) +myCenter (), +mySize (), +myRotation (0), +myViewport (0, 0, 1, 1), +myTransformUpdated (false), +myInvTransformUpdated(false) { Reset(rectangle); } @@ -58,12 +59,12 @@ myInvMatrixUpdated(false) //////////////////////////////////////////////////////////// View::View(const Vector2f& center, const Vector2f& size) : -myCenter (center), -mySize (size), -myRotation (0), -myViewport (0, 0, 1, 1), -myMatrixUpdated (false), -myInvMatrixUpdated(false) +myCenter (center), +mySize (size), +myRotation (0), +myViewport (0, 0, 1, 1), +myTransformUpdated (false), +myInvTransformUpdated(false) { } @@ -74,8 +75,8 @@ void View::SetCenter(float x, float y) myCenter.x = x; myCenter.y = y; - myMatrixUpdated = false; - myInvMatrixUpdated = false; + myTransformUpdated = false; + myInvTransformUpdated = false; } @@ -92,8 +93,8 @@ void View::SetSize(float width, float height) mySize.x = width; mySize.y = height; - myMatrixUpdated = false; - myInvMatrixUpdated = false; + myTransformUpdated = false; + myInvTransformUpdated = false; } @@ -111,8 +112,8 @@ void View::SetRotation(float angle) if (myRotation < 0) myRotation += 360.f; - myMatrixUpdated = false; - myInvMatrixUpdated = false; + myTransformUpdated = false; + myInvTransformUpdated = false; } @@ -132,8 +133,8 @@ void View::Reset(const FloatRect& rectangle) mySize.y = rectangle.Height; myRotation = 0; - myMatrixUpdated = false; - myInvMatrixUpdated = false; + myTransformUpdated = false; + myInvTransformUpdated = false; } @@ -194,30 +195,46 @@ void View::Zoom(float factor) //////////////////////////////////////////////////////////// -const Matrix3& View::GetMatrix() const +const Transform& View::GetTransform() const { // Recompute the matrix if needed - if (!myMatrixUpdated) + if (!myTransformUpdated) { - myMatrix = Matrix3::Projection(myCenter, mySize, myRotation); - myMatrixUpdated = true; + // Rotation components + float angle = myRotation * 3.141592654f / 180.f; + float cosine = static_cast(std::cos(angle)); + float sine = static_cast(std::sin(angle)); + float tx = -myCenter.x * cosine - myCenter.y * sine + myCenter.x; + float ty = myCenter.x * sine - myCenter.y * cosine + myCenter.y; + + // Projection components + float a = 2.f / mySize.x; + float b = -2.f / mySize.y; + float c = -a * myCenter.x; + float d = -b * myCenter.y; + + // Rebuild the projection matrix + myTransform = Transform( a * cosine, a * sine, a * tx + c, + -b * sine, b * cosine, b * ty + d, + 0.f, 0.f, 1.f); + myTransformUpdated = true; } - return myMatrix; + return myTransform; } //////////////////////////////////////////////////////////// -const Matrix3& View::GetInverseMatrix() const +const Transform& View::GetInverseTransform() const { // Recompute the matrix if needed - if (!myInvMatrixUpdated) + if (!myInvTransformUpdated) { - myInverseMatrix = GetMatrix().GetInverse(); - myInvMatrixUpdated = true; + myInverseTransform = GetTransform().GetInverse(); + myInvTransformUpdated = true; } - return myInverseMatrix; + return myInverseTransform; } } // namespace sf diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp index 961c25083..354b4cdc6 100644 --- a/src/SFML/Window/Context.cpp +++ b/src/SFML/Window/Context.cpp @@ -53,6 +53,13 @@ bool Context::SetActive(bool active) } +//////////////////////////////////////////////////////////// +ContextId Context::GetCurrentContextId() +{ + return priv::GlContext::GetCurrentContext(); +} + + //////////////////////////////////////////////////////////// Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height) { diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp index 196ed9c8b..51f808aeb 100644 --- a/src/SFML/Window/GlContext.cpp +++ b/src/SFML/Window/GlContext.cpp @@ -177,6 +177,13 @@ GlContext* GlContext::New(const ContextSettings& settings, unsigned int width, u } +//////////////////////////////////////////////////////////// +GlContext* GlContext::GetCurrentContext() +{ + return currentContext; +} + + //////////////////////////////////////////////////////////// GlContext::~GlContext() { diff --git a/src/SFML/Window/GlContext.hpp b/src/SFML/Window/GlContext.hpp index f6eb193a0..015ef72a8 100644 --- a/src/SFML/Window/GlContext.hpp +++ b/src/SFML/Window/GlContext.hpp @@ -118,6 +118,16 @@ public : //////////////////////////////////////////////////////////// static GlContext* New(const ContextSettings& settings, unsigned int width, unsigned int height); + //////////////////////////////////////////////////////////// + /// \brief Return the current active context + /// + /// This function returns 0 if no context is active. + /// + /// \return Context currently active in this thread + /// + //////////////////////////////////////////////////////////// + static GlContext* GetCurrentContext(); + public : ////////////////////////////////////////////////////////////