Merge branch 'drawables'

This commit is contained in:
Laurent Gomila 2011-12-25 23:08:02 +01:00
commit f55da8d8bc
81 changed files with 5671 additions and 3805 deletions

View File

@ -4,7 +4,6 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>
////////////////////////////////////////////////////////////
/// 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();

View File

@ -19,172 +19,216 @@ int main()
{
std::srand(static_cast<unsigned int>(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();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

View File

@ -2,7 +2,9 @@
set(SRCROOT ${PROJECT_SOURCE_DIR}/examples/shader)
# all source files
set(SRC ${SRCROOT}/Shader.cpp)
set(SRC
${SRCROOT}/Effect.hpp
${SRCROOT}/Shader.cpp)
# define the shader target
sfml_add_example(shader GUI_APP

View File

@ -0,0 +1,74 @@
#ifndef EFFECT_HPP
#define EFFECT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <string>
////////////////////////////////////////////////////////////
// Base class for effects
////////////////////////////////////////////////////////////
class Effect : public sf::Drawable
{
public :
virtual ~Effect()
{
}
const std::string& GetName() const
{
return myName;
}
void Load()
{
myIsLoaded = sf::Shader::IsAvailable() && OnLoad();
}
void Update(float time, float x, float y)
{
if (myIsLoaded)
OnUpdate(time, x, y);
}
void Draw(sf::RenderTarget& target, sf::RenderStates states) const
{
if (myIsLoaded)
{
OnDraw(target, states);
}
else
{
sf::Text error("Shader not\nsupported");
error.SetPosition(320.f, 200.f);
error.SetCharacterSize(36);
target.Draw(error, states);
}
}
protected :
Effect(const std::string& name) :
myName(name),
myIsLoaded(false)
{
}
private :
// Virtual functions to be implemented in derived effects
virtual bool OnLoad() = 0;
virtual void OnUpdate(float time, float x, float y) = 0;
virtual void OnDraw(sf::RenderTarget& target, sf::RenderStates states) const = 0;
private :
std::string myName;
bool myIsLoaded;
};
#endif // EFFECT_HPP

View File

@ -2,71 +2,257 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "Effect.hpp"
#include <SFML/Graphics.hpp>
#include <map>
#include <vector>
#include <cmath>
void DisplayError();
////////////////////////////////////////////////////////////
/// A class to simplify shader selection
///
// "Pixelate" fragment shader
////////////////////////////////////////////////////////////
class ShaderSelector
class Pixelate : public Effect
{
public :
// Constructor
ShaderSelector(std::map<std::string, sf::Shader>& owner, const std::string& shader) :
myOwner (&owner),
myIterator(owner.find(shader))
Pixelate() :
Effect("pixelate")
{
}
// Select the previous shader
void GotoPrevious()
bool OnLoad()
{
if (myIterator == myOwner->begin())
myIterator = myOwner->end();
myIterator--;
// Load the texture and initialize the sprite
if (!myTexture.LoadFromFile("resources/background.jpg"))
return false;
mySprite.SetTexture(myTexture);
// Load the shader
if (!myShader.LoadFromFile("resources/pixelate.frag", sf::Shader::Fragment))
return false;
myShader.SetParameter("texture", sf::Shader::CurrentTexture);
return true;
}
// Select the next shader
void GotoNext()
void OnUpdate(float, float x, float y)
{
myIterator++;
if (myIterator == myOwner->end())
myIterator = myOwner->begin();
myShader.SetParameter("pixel_threshold", (x + y) / 30);
}
// Update the shader parameters
void Update(float x, float y)
void OnDraw(sf::RenderTarget& target, sf::RenderStates states) const
{
if (myIterator->first == "blur") myIterator->second.SetParameter("offset", x * y * 0.03f);
else if (myIterator->first == "colorize") myIterator->second.SetParameter("color", 0.3f, x, y);
else if (myIterator->first == "edge") myIterator->second.SetParameter("threshold", x * y);
else if (myIterator->first == "fisheye") myIterator->second.SetParameter("mouse", x, y);
else if (myIterator->first == "wave") myIterator->second.SetParameter("offset", x, y);
else if (myIterator->first == "pixelate") myIterator->second.SetParameter("mouse", x, y);
states.Shader = &myShader;
target.Draw(mySprite, states);
}
// Get the name of the current shader
const std::string& GetName() const
private:
sf::Texture myTexture;
sf::Sprite mySprite;
sf::Shader myShader;
};
////////////////////////////////////////////////////////////
// "Wave" vertex shader + "blur" fragment shader
////////////////////////////////////////////////////////////
class WaveBlur : public Effect
{
public :
WaveBlur() :
Effect("wave + blur")
{
return myIterator->first;
}
// Get the current shader
const sf::Shader& GetShader() const
bool OnLoad()
{
return myIterator->second;
// Create the text
myText.SetString("Praesent suscipit augue in velit pulvinar hendrerit varius purus aliquam.\n"
"Mauris mi odio, bibendum quis fringilla a, laoreet vel orci. Proin vitae vulputate tortor.\n"
"Praesent cursus ultrices justo, ut feugiat ante vehicula quis.\n"
"Donec fringilla scelerisque mauris et viverra.\n"
"Maecenas adipiscing ornare scelerisque. Nullam at libero elit.\n"
"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.\n"
"Nullam leo urna, tincidunt id semper eget, ultricies sed mi.\n"
"Morbi mauris massa, commodo id dignissim vel, lobortis et elit.\n"
"Fusce vel libero sed neque scelerisque venenatis.\n"
"Integer mattis tincidunt quam vitae iaculis.\n"
"Vivamus fringilla sem non velit venenatis fermentum.\n"
"Vivamus varius tincidunt nisi id vehicula.\n"
"Integer ullamcorper, enim vitae euismod rutrum, massa nisl semper ipsum,\n"
"vestibulum sodales sem ante in massa.\n"
"Vestibulum in augue non felis convallis viverra.\n"
"Mauris ultricies dolor sed massa convallis sed aliquet augue fringilla.\n"
"Duis erat eros, porta in accumsan in, blandit quis sem.\n"
"In hac habitasse platea dictumst. Etiam fringilla est id odio dapibus sit amet semper dui laoreet.\n");
myText.SetCharacterSize(22);
myText.SetPosition(30, 20);
// Load the shader
//if (!myShader.LoadFromFile("resources/wave.vert", sf::Shader::Vertex))
if (!myShader.LoadFromFile("resources/wave.vert", "resources/blur.frag"))
return false;
return true;
}
private :
void OnUpdate(float time, float x, float y)
{
myShader.SetParameter("wave_phase", time);
myShader.SetParameter("wave_amplitude", x * 40, y * 40);
myShader.SetParameter("blur_radius", (x + y) * 0.008f);
}
std::map<std::string, sf::Shader>* myOwner;
std::map<std::string, sf::Shader>::iterator myIterator;
void OnDraw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.Shader = &myShader;
target.Draw(myText, states);
}
private:
sf::Text myText;
sf::Shader myShader;
};
////////////////////////////////////////////////////////////
// "Storm" vertex shader + "blink" fragment shader
////////////////////////////////////////////////////////////
class StormBlink : public Effect
{
public :
StormBlink() :
Effect("storm + blink")
{
}
bool OnLoad()
{
// Create the points
myPoints.SetPrimitiveType(sf::Points);
for (int i = 0; i < 40000; ++i)
{
float x = static_cast<float>(std::rand() % 800);
float y = static_cast<float>(std::rand() % 600);
sf::Uint8 r = std::rand() % 255;
sf::Uint8 g = std::rand() % 255;
sf::Uint8 b = std::rand() % 255;
myPoints.Append(sf::Vertex(sf::Vector2f(x, y), sf::Color(r, g, b)));
}
// Load the shader
if (!myShader.LoadFromFile("resources/storm.vert", "resources/blink.frag"))
return false;
return true;
}
void OnUpdate(float time, float x, float y)
{
float radius = 200 + std::cos(time) * 150;
myShader.SetParameter("storm_position", x * 800, y * 600);
myShader.SetParameter("storm_inner_radius", radius / 3);
myShader.SetParameter("storm_total_radius", radius);
myShader.SetParameter("blink_alpha", 0.5f + std::cos(time * 3) * 0.25f);
}
void OnDraw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.Shader = &myShader;
target.Draw(myPoints, states);
}
private:
sf::VertexArray myPoints;
sf::Shader myShader;
};
////////////////////////////////////////////////////////////
// "Edge" post-effect fragment shader
////////////////////////////////////////////////////////////
class Edge : public Effect
{
public :
Edge() :
Effect("edge post-effect")
{
}
bool OnLoad()
{
// Create the off-screen surface
if (!mySurface.Create(800, 600))
return false;
mySurface.SetSmooth(true);
// Load the textures
if (!myBackgroundTexture.LoadFromFile("resources/sfml.png"))
return false;
myBackgroundTexture.SetSmooth(true);
if (!myEntityTexture.LoadFromFile("resources/devices.png"))
return false;
myEntityTexture.SetSmooth(true);
// Initialize the background sprite
myBackgroundSprite.SetTexture(myBackgroundTexture);
myBackgroundSprite.SetPosition(135, 100);
// Load the moving entities
for (int i = 0; i < 6; ++i)
{
sf::Sprite entity(myEntityTexture, sf::IntRect(96 * i, 0, 96, 96));
myEntities.push_back(entity);
}
// Load the shader
if (!myShader.LoadFromFile("resources/edge.frag", sf::Shader::Fragment))
return false;
myShader.SetParameter("texture", sf::Shader::CurrentTexture);
return true;
}
void OnUpdate(float time, float x, float y)
{
myShader.SetParameter("edge_threshold", 1 - (x + y) / 2);
// Update the position of the moving entities
for (std::size_t i = 0; i < myEntities.size(); ++i)
{
float x = std::cos(0.25f * (time * i + (myEntities.size() - i))) * 300 + 350;
float y = std::sin(0.25f * (time * (myEntities.size() - i) + i)) * 200 + 250;
myEntities[i].SetPosition(x, y);
}
// Render the updated scene to the off-screen surface
mySurface.Clear(sf::Color::White);
mySurface.Draw(myBackgroundSprite);
for (std::size_t i = 0; i < myEntities.size(); ++i)
mySurface.Draw(myEntities[i]);
mySurface.Display();
}
void OnDraw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.Shader = &myShader;
target.Draw(sf::Sprite(mySurface.GetTexture()), states);
}
private:
sf::RenderTexture mySurface;
sf::Texture myBackgroundTexture;
sf::Texture myEntityTexture;
sf::Sprite myBackgroundSprite;
std::vector<sf::Sprite> myEntities;
sf::Shader myShader;
};
@ -78,203 +264,110 @@ private :
////////////////////////////////////////////////////////////
int main()
{
// Check that the system can use shaders
if (sf::Shader::IsAvailable() == false)
{
DisplayError();
return EXIT_SUCCESS;
}
// Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader");
window.EnableVerticalSync(true);
// Create the render texture
sf::RenderTexture texture;
if (!texture.Create(window.GetWidth(), window.GetHeight()))
// Create the effects
std::vector<Effect*> effects;
effects.push_back(new Pixelate);
effects.push_back(new WaveBlur);
effects.push_back(new StormBlink);
effects.push_back(new Edge);
std::size_t current = 0;
// Initialize them
for (std::size_t i = 0; i < effects.size(); ++i)
effects[i]->Load();
// Create the messages background
sf::Texture textBackgroundTexture;
if (!textBackgroundTexture.LoadFromFile("resources/text-background.png"))
return EXIT_FAILURE;
sf::Sprite textBackground(textBackgroundTexture);
textBackground.SetPosition(0, 520);
textBackground.SetColor(sf::Color(255, 255, 255, 200));
// Load a background texture to display
sf::Texture backgroundTexture;
if (!backgroundTexture.LoadFromFile("resources/background.jpg"))
return EXIT_FAILURE;
sf::Sprite background(backgroundTexture);
// Load a sprite which we'll move into the scene
sf::Texture entityTexture;
if (!entityTexture.LoadFromFile("resources/sprite.png"))
return EXIT_FAILURE;
sf::Sprite entity(entityTexture);
// Load the text font
// Load the messages font
sf::Font font;
if (!font.LoadFromFile("resources/sansation.ttf"))
return EXIT_FAILURE;
// Load the texture needed for the wave shader
sf::Texture waveTexture;
if (!waveTexture.LoadFromFile("resources/wave.jpg"))
return EXIT_FAILURE;
// Create the description text
sf::Text description("Current effect: " + effects[current]->GetName(), font, 20);
description.SetPosition(10, 530);
description.SetColor(sf::Color(80, 80, 80));
// Load all shaders
std::map<std::string, sf::Shader> shaders;
if (!shaders["nothing"].LoadFromFile("resources/nothing.sfx")) return EXIT_FAILURE;
if (!shaders["blur"].LoadFromFile("resources/blur.sfx")) return EXIT_FAILURE;
if (!shaders["colorize"].LoadFromFile("resources/colorize.sfx")) return EXIT_FAILURE;
if (!shaders["edge"].LoadFromFile("resources/edge.sfx")) return EXIT_FAILURE;
if (!shaders["fisheye"].LoadFromFile("resources/fisheye.sfx")) return EXIT_FAILURE;
if (!shaders["wave"].LoadFromFile("resources/wave.sfx")) return EXIT_FAILURE;
if (!shaders["pixelate"].LoadFromFile("resources/pixelate.sfx")) return EXIT_FAILURE;
ShaderSelector backgroundShader(shaders, "nothing");
ShaderSelector entityShader(shaders, "nothing");
ShaderSelector globalShader(shaders, "nothing");
// Do specific initializations
shaders["nothing"].SetCurrentTexture("texture");
shaders["blur"].SetCurrentTexture("texture");
shaders["blur"].SetParameter("offset", 0.f);
shaders["colorize"].SetCurrentTexture("texture");
shaders["colorize"].SetParameter("color", 1.f, 1.f, 1.f);
shaders["edge"].SetCurrentTexture("texture");
shaders["fisheye"].SetCurrentTexture("texture");
shaders["wave"].SetCurrentTexture("texture");
shaders["wave"].SetTexture("wave", waveTexture);
shaders["pixelate"].SetCurrentTexture("texture");
// Define a string for displaying the description of the current shader
sf::Text shaderStr;
shaderStr.SetFont(font);
shaderStr.SetCharacterSize(20);
shaderStr.SetPosition(5.f, 0.f);
shaderStr.SetColor(sf::Color(250, 100, 30));
shaderStr.SetString("Background shader: \"" + backgroundShader.GetName() + "\"\n"
"Flower shader: \"" + entityShader.GetName() + "\"\n"
"Global shader: \"" + globalShader.GetName() + "\"\n");
// Define a string for displaying help
sf::Text infoStr;
infoStr.SetFont(font);
infoStr.SetCharacterSize(20);
infoStr.SetPosition(5.f, 500.f);
infoStr.SetColor(sf::Color(250, 100, 30));
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"
"Press numpad 3/6 to change the global shader");
// Create a clock to measure the total time elapsed
sf::Clock clock;
// Create the instructions text
sf::Text instructions("Press left and right arrows to change the current shader", font, 20);
instructions.SetPosition(280, 555);
instructions.SetColor(sf::Color(80, 80, 80));
// Start the game loop
sf::Clock clock;
while (window.IsOpened())
{
// Process events
sf::Event event;
while (window.PollEvent(event))
{
// Close window : exit
// Close window: exit
if (event.Type == sf::Event::Closed)
window.Close();
if (event.Type == sf::Event::KeyPressed)
{
// Escape key : exit
if (event.Key.Code == sf::Keyboard::Escape)
window.Close();
// Numpad : switch effect
switch (event.Key.Code)
{
case sf::Keyboard::Numpad1 : backgroundShader.GotoPrevious(); break;
case sf::Keyboard::Numpad4 : backgroundShader.GotoNext(); break;
case sf::Keyboard::Numpad2 : entityShader.GotoPrevious(); break;
case sf::Keyboard::Numpad5 : entityShader.GotoNext(); break;
case sf::Keyboard::Numpad3 : globalShader.GotoPrevious(); break;
case sf::Keyboard::Numpad6 : globalShader.GotoNext(); break;
default : break;
}
// Escape key: exit
case sf::Keyboard::Escape:
window.Close();
break;
// Update the text
shaderStr.SetString("Background shader: \"" + backgroundShader.GetName() + "\"\n"
"Entity shader: \"" + entityShader.GetName() + "\"\n"
"Global shader: \"" + globalShader.GetName() + "\"\n");
// Left arrow key: previous shader
case sf::Keyboard::Left:
if (current == 0)
current = effects.size() - 1;
else
current--;
description.SetString("Current effect: " + effects[current]->GetName());
break;
// Right arrow key: next shader
case sf::Keyboard::Right:
if (current == effects.size() - 1)
current = 0;
else
current++;
description.SetString("Current effect: " + effects[current]->GetName());
break;
}
}
}
// Get the mouse position in the range [0, 1]
float mouseX = sf::Mouse::GetPosition(window).x / static_cast<float>(window.GetWidth());
float mouseY = sf::Mouse::GetPosition(window).y / static_cast<float>(window.GetHeight());
// Update the current example
float x = static_cast<float>(sf::Mouse::GetPosition(window).x) / window.GetWidth();
float y = static_cast<float>(sf::Mouse::GetPosition(window).y) / window.GetHeight();
effects[current]->Update(clock.GetElapsedTime() / 1000.f, x, y);
// Update the shaders
backgroundShader.Update(mouseX, mouseY);
entityShader.Update(mouseX, mouseY);
globalShader.Update(mouseX, mouseY);
// Clear the window
window.Clear(sf::Color(255, 128, 0));
// Animate the entity
float entityX = (std::cos(clock.GetElapsedTime() * 0.0013f) + 1.2f) * 300;
float entityY = (std::cos(clock.GetElapsedTime() * 0.0008f) + 1.2f) * 200;
entity.SetPosition(entityX, entityY);
entity.Rotate(window.GetFrameTime() * 0.1f);
// Draw the current example
window.Draw(*effects[current]);
// Draw the background and the moving entity to the render texture
texture.Clear();
texture.Draw(background, backgroundShader.GetShader());
texture.Draw(entity, entityShader.GetShader());
texture.Display();
// Draw the contents of the render texture to the window
sf::Sprite screen(texture.GetTexture());
window.Draw(screen, globalShader.GetShader());
// Draw the interface texts
window.Draw(shaderStr);
window.Draw(infoStr);
// Draw the text
window.Draw(textBackground);
window.Draw(instructions);
window.Draw(description);
// Finally, display the rendered frame on screen
window.Display();
}
// delete the effects
for (std::size_t i = 0; i < effects.size(); ++i)
delete effects[i];
return EXIT_SUCCESS;
}
////////////////////////////////////////////////////////////
/// Fonction called when the post-effects are not supported ;
/// Display an error message and wait until the user exits
///
////////////////////////////////////////////////////////////
void DisplayError()
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader");
// 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));
// Start the game loop
while (window.IsOpened())
{
// Process events
sf::Event event;
while (window.PollEvent(event))
{
// Close window : exit
if (event.Type == sf::Event::Closed)
window.Close();
// Escape key : exit
if ((event.Type == sf::Event::KeyPressed) && (event.Key.Code == sf::Keyboard::Escape))
window.Close();
}
// Clear the window
window.Clear();
// Draw the error message
window.Draw(error);
// Finally, display the rendered frame on screen
window.Display();
}
}

View File

@ -0,0 +1,9 @@
uniform sampler2D texture;
uniform float blink_alpha;
void main()
{
vec4 pixel = gl_Color;
pixel.a = blink_alpha;
gl_FragColor = pixel;
}

View File

@ -1,12 +1,12 @@
uniform sampler2D texture;
uniform float offset;
uniform float blur_radius;
void main()
{
vec2 offx = vec2(offset, 0.0);
vec2 offy = vec2(0.0, offset);
vec2 offx = vec2(blur_radius, 0.0);
vec2 offy = vec2(0.0, blur_radius);
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 1.0 +
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 4.0 +
texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy + offx) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy - offy) * 2.0 +
@ -16,5 +16,5 @@ void main()
texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0;
gl_FragColor = gl_Color * (pixel / 13.0);
gl_FragColor = gl_Color * (pixel / 16.0);
}

View File

@ -1,11 +0,0 @@
uniform sampler2D texture;
uniform vec3 color;
void main()
{
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;
float gray = pixel.r * 0.39 + pixel.g * 0.50 + pixel.b * 0.11;
gl_FragColor = vec4(gray * color, 1.0) * 0.6 + pixel * 0.4;
gl_FragColor.a = pixel.a;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,5 +1,5 @@
uniform sampler2D texture;
uniform float threshold;
uniform float edge_threshold;
void main()
{
@ -23,9 +23,10 @@ void main()
vec3 result = sqrt(hEdge.rgb * hEdge.rgb + vEdge.rgb * vEdge.rgb);
float edge = length(result);
if (edge > threshold)
gl_FragColor.rgb = vec3(0, 0, 0);
vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy);
if (edge > (edge_threshold * 8.0))
pixel.rgb = vec3(0.0, 0.0, 0.0);
else
gl_FragColor.rgb = vec3(1, 1, 1);
gl_FragColor.a = gl_Color.a * texture2D(texture, gl_TexCoord[0].xy).a;
pixel.a = edge_threshold;
gl_FragColor = pixel;
}

View File

@ -1,13 +0,0 @@
uniform sampler2D texture;
uniform vec2 mouse;
void main()
{
float len = distance(gl_TexCoord[0].xy, mouse) * 7.0;
vec2 coords = gl_TexCoord[0].xy;
if (len < 1.0)
coords += (gl_TexCoord[0].xy - mouse) * len;
gl_FragColor = texture2D(texture, coords) * gl_Color;
}

View File

@ -1,6 +0,0 @@
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;
}

View File

@ -1,10 +1,9 @@
uniform sampler2D texture;
uniform vec2 mouse;
uniform float pixel_threshold;
void main()
{
float factor = 5.0 + 100.0 * length(mouse);
float factor = 1.0 / (pixel_threshold + 0.001);
vec2 pos = floor(gl_TexCoord[0].xy * factor + 0.5) / factor;
gl_FragColor = texture2D(texture, pos) * gl_Color;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,19 @@
uniform vec2 storm_position;
uniform float storm_total_radius;
uniform float storm_inner_radius;
void main()
{
vec4 vertex = gl_ModelViewMatrix * gl_Vertex;
vec2 offset = vertex.xy - storm_position;
float len = length(offset);
if (len < storm_total_radius)
{
float push_distance = storm_inner_radius + len / storm_total_radius * (storm_total_radius - storm_inner_radius);
vertex.xy = storm_position + normalize(offset) * push_distance;
}
gl_Position = gl_ProjectionMatrix * vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,12 +0,0 @@
uniform sampler2D texture;
uniform sampler2D wave;
uniform vec2 offset;
void main()
{
vec2 texoffset = vec2(texture2D(wave, (gl_TexCoord[0].xy * offset).xy));
texoffset -= vec2(0.5, 0.5);
texoffset *= 0.05;
gl_FragColor = texture2D(texture, gl_TexCoord[0].xy + texoffset) * gl_Color;
}

View File

@ -0,0 +1,15 @@
uniform float wave_phase;
uniform vec2 wave_amplitude;
void main()
{
vec4 vertex = gl_Vertex;
vertex.x += cos(gl_Vertex.y * 0.02 + wave_phase * 3.8) * wave_amplitude.x
+ sin(gl_Vertex.y * 0.02 + wave_phase * 6.3) * wave_amplitude.x * 0.3;
vertex.y += sin(gl_Vertex.x * 0.02 + wave_phase * 2.4) * wave_amplitude.y
+ cos(gl_Vertex.x * 0.02 + wave_phase * 5.2) * wave_amplitude.y * 0.3;
gl_Position = gl_ModelViewProjectionMatrix * vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -30,18 +30,25 @@
////////////////////////////////////////////////////////////
#include <SFML/Window.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics/CircleShape.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/ConvexShape.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/View.hpp>

View File

@ -0,0 +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.
//
////////////////////////////////////////////////////////////
#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

View File

@ -0,0 +1,148 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Shape.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a circle
///
////////////////////////////////////////////////////////////
class SFML_API CircleShape : public Shape
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param radius Radius of the circle
/// \param pointsCount Number of points composing the circle
///
////////////////////////////////////////////////////////////
explicit CircleShape(float radius = 0, unsigned int pointsCount = 30);
////////////////////////////////////////////////////////////
/// \brief Set the radius of the circle
///
/// \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;
////////////////////////////////////////////////////////////
/// \brief Set the number of points of the circle
///
/// \param count New number of points of the circle
///
/// \see GetPointsCount
///
////////////////////////////////////////////////////////////
void SetPointsCount(unsigned int count);
////////////////////////////////////////////////////////////
/// \brief Get the number of points of the shape
///
/// \return Number of points of the shape
///
/// \see SetPointsCount
///
////////////////////////////////////////////////////////////
virtual unsigned int GetPointsCount() 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 GetPoint(unsigned int index) const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
float myRadius; ///< Radius of the circle
unsigned int myPointsCount; ///< Number of points composing 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
///
/// Since the graphics card can't draw perfect circles, we have to
/// fake them with multiple triangles connected to each other. The
/// "points count" property of sf::CircleShape defines how many of these
/// triangles to use, and therefore defines the quality of the circle.
///
/// The number of points can also be used for another purpose; with
/// small numbers you can create any regular polygon shape:
/// equilateral triangle, square, pentagon, hexagon, ...
///
/// \see sf::Shape, sf::RectangleShape, sf::ConvexShape
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -0,0 +1,142 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Shape.hpp>
#include <vector>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a convex polygon
///
////////////////////////////////////////////////////////////
class SFML_API ConvexShape : public Shape
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param pointsCount Number of points of the polygon
///
////////////////////////////////////////////////////////////
explicit ConvexShape(unsigned int pointsCount = 0);
////////////////////////////////////////////////////////////
/// \brief Set the number of points of the polygon
///
/// \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
///
////////////////////////////////////////////////////////////
virtual 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
///
////////////////////////////////////////////////////////////
virtual Vector2f GetPoint(unsigned int index) const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<Vector2f> 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::RectangleShape, sf::CircleShape
///
////////////////////////////////////////////////////////////

View File

@ -28,32 +28,14 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Matrix3.hpp>
#include <SFML/Config.hpp>
#include <SFML/Graphics/RenderStates.hpp>
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
///
////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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 <SFML/Config.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <cmath>
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 <SFML/Graphics/Matrix3.inl>
} // 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.
///
////////////////////////////////////////////////////////////

View File

@ -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<float>(std::cos(angle));
float sine = static_cast<float>(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<float>(std::cos(angle));
float sine = static_cast<float>(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);
}

View File

@ -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

View File

@ -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 <typename T>
bool operator ==(const Rect<T>& left, const Rect<T>& 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 <typename T>
bool operator !=(const Rect<T>& left, const Rect<T>& right);
#include <SFML/Graphics/Rect.inl>
// Create typedefs for the most common types

View File

@ -118,3 +118,21 @@ bool Rect<T>::Intersects(const Rect<T>& rectangle, Rect<T>& intersection) const
return false;
}
}
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator ==(const Rect<T>& left, const Rect<T>& right)
{
return (left.Left == right.Left) && (left.Width == right.Width) &&
(left.Top == right.Top) && (left.Height == right.Height);
}
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator !=(const Rect<T>& left, const Rect<T>& right)
{
return (left.Left != right.Left) || (left.Width != right.Width) ||
(left.Top != right.Top) || (left.Height != right.Height);
}

View File

@ -0,0 +1,125 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Shape.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Specialized shape representing a rectangle
///
////////////////////////////////////////////////////////////
class SFML_API RectangleShape : public Shape
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// \param size Size of the rectangle
///
////////////////////////////////////////////////////////////
explicit RectangleShape(const Vector2f& size = Vector2f(0, 0));
////////////////////////////////////////////////////////////
/// \brief Set the size of the rectangle
///
/// \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;
////////////////////////////////////////////////////////////
/// \brief Get the number of points defining the shape
///
/// \return Number of points of the shape
///
////////////////////////////////////////////////////////////
virtual unsigned int GetPointsCount() 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 GetPoint(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::CircleShape, sf::ConvexShape
///
////////////////////////////////////////////////////////////

View File

@ -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 <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/Transform.hpp>
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
///
////////////////////////////////////////////////////////////

View File

@ -31,14 +31,17 @@
#include <SFML/System/NonCopyable.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/View.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Vertex.hpp>
namespace sf
{
class Drawable;
class Shader;
////////////////////////////////////////////////////////////
/// \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 :
@ -277,6 +303,44 @@ protected :
////////////////////////////////////////////////////////////
void Initialize();
////////////////////////////////////////////////////////////
/// \brief Apply the current view
///
////////////////////////////////////////////////////////////
void ApplyCurrentView();
////////////////////////////////////////////////////////////
/// \brief Apply a new blending mode
///
/// \param mode Blending mode to apply
///
////////////////////////////////////////////////////////////
void ApplyBlendMode(BlendMode mode);
////////////////////////////////////////////////////////////
/// \brief Apply a new transform
///
/// \param transform Transform to apply
///
////////////////////////////////////////////////////////////
void ApplyTransform(const Transform& transform);
////////////////////////////////////////////////////////////
/// \brief Apply a new texture
///
/// \param texture Texture to apply
///
////////////////////////////////////////////////////////////
void ApplyTexture(const Texture* texture);
////////////////////////////////////////////////////////////
/// \brief Apply a new shader
///
/// \param shader Shader to apply
///
////////////////////////////////////////////////////////////
void ApplyShader(const Shader* shader);
private :
////////////////////////////////////////////////////////////
@ -293,14 +357,27 @@ private :
////////////////////////////////////////////////////////////
virtual bool Activate(bool active) = 0;
////////////////////////////////////////////////////////////
/// \brief Render states cache
///
////////////////////////////////////////////////////////////
struct StatesCache
{
enum {VertexCacheSize = 4};
bool ViewChanged; ///< Has the current view changed since last draw?
BlendMode LastBlendMode; ///< Cached blending mode
Uint64 LastTextureId; ///< Cached texture
bool UseVertexCache; ///< Did we previously use the vertex cache?
Vertex VertexCache[VertexCacheSize]; ///< Pre-transformed vertices cache
};
////////////////////////////////////////////////////////////
// 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
StatesCache myCache; ///< Render states cache
};
} // namespace sf
@ -328,8 +405,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
///

View File

@ -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();

View File

@ -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 <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Matrix3.hpp>
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.
///
////////////////////////////////////////////////////////////

View File

@ -29,8 +29,10 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp>
#include <map>
@ -39,32 +41,45 @@
namespace sf
{
class Renderer;
class InputStream;
class Texture;
////////////////////////////////////////////////////////////
/// \brief Pixel/fragment shader class
/// \brief Shader class (vertex and fragment)
///
////////////////////////////////////////////////////////////
class SFML_API Shader : GlResource
class SFML_API Shader : GlResource, NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Types of shaders
///
////////////////////////////////////////////////////////////
enum Type
{
Vertex, ///< Vertex shader
Fragment ///< Fragment (pixel) shader
};
////////////////////////////////////////////////////////////
/// \brief Special type/value that can be passed to SetParameter,
/// and that represents the texture of the object being drawn
///
////////////////////////////////////////////////////////////
struct CurrentTextureType {};
static CurrentTextureType CurrentTexture;
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor creates an invalid shader
/// This constructor creates an invalid shader.
///
////////////////////////////////////////////////////////////
Shader();
////////////////////////////////////////////////////////////
/// \brief Copy constructor
///
/// \param copy Instance to copy
///
////////////////////////////////////////////////////////////
Shader(const Shader& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
@ -72,64 +87,139 @@ public :
~Shader();
////////////////////////////////////////////////////////////
/// \brief Load the shader from a file
/// \brief Load either the vertex or fragment shader from a file
///
/// This function loads a single shader, either vertex or
/// fragment, identified by the second argument.
/// The source must be a text file containing a valid
/// fragment shader in GLSL language. GLSL is a C-like
/// language dedicated to OpenGL shaders; you'll probably
/// need to read a good documentation for it before writing
/// your own shaders.
/// shader in GLSL language. GLSL is a C-like language
/// dedicated to OpenGL shaders; you'll probably need to
/// read a good documentation for it before writing your
/// own shaders.
///
/// \param filename Path of the shader file to load
/// \param filename Path of the vertex or fragment shader file to load
/// \param type Type of shader (vertex or fragment)
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromMemory, LoadFromStream
///
////////////////////////////////////////////////////////////
bool LoadFromFile(const std::string& filename);
bool LoadFromFile(const std::string& filename, Type type);
////////////////////////////////////////////////////////////
/// \brief Load the shader from a source code in memory
/// \brief Load both the vertex and fragment shaders from files
///
/// The source code must be a valid fragment shader in
/// GLSL language. GLSL is a C-like language dedicated
/// to OpenGL shaders; you'll probably need to read a
/// good documentation for it before writing your own shaders.
/// This function loads both the vertex and the fragment
/// shaders. If one of them fails to load, the shader is left
/// empty (the valid shader is unloaded).
/// The sources must be text files containing valid shaders
/// in GLSL language. GLSL is a C-like language dedicated to
/// OpenGL shaders; you'll probably need to read a good documentation
/// for it before writing your own shaders.
///
/// \param vertexShaderFilename Path of the vertex shader file to load
/// \param fragmentShaderFilename Path of the fragment shader file to load
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromMemory, LoadFromStream
///
////////////////////////////////////////////////////////////
bool LoadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename);
////////////////////////////////////////////////////////////
/// \brief Load either the vertex or fragment shader from a source code in memory
///
/// This function loads a single shader, either vertex or
/// fragment, identified by the second argument.
/// The source code must be a valid shader in GLSL language.
/// GLSL is a C-like language dedicated to OpenGL shaders;
/// you'll probably need to read a good documentation for
/// it before writing your own shaders.
///
/// \param shader String containing the source code of the shader
/// \param type Type of shader (vertex or fragment)
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromFile, LoadFromStream
///
////////////////////////////////////////////////////////////
bool LoadFromMemory(const std::string& shader);
bool LoadFromMemory(const std::string& shader, Type type);
////////////////////////////////////////////////////////////
/// \brief Load the shader from a custom stream
/// \brief Load both the vertex and fragment shaders from source codes in memory
///
/// The source code must be a valid fragment shader in
/// GLSL language. GLSL is a C-like language dedicated
/// to OpenGL shaders; you'll probably need to read a
/// good documentation for it before writing your own shaders.
/// This function loads both the vertex and the fragment
/// shaders. If one of them fails to load, the shader is left
/// empty (the valid shader is unloaded).
/// The sources must be valid shaders in GLSL language. GLSL is
/// a C-like language dedicated to OpenGL shaders; you'll
/// probably need to read a good documentation for it before
/// writing your own shaders.
///
/// \param vertexShader String containing the source code of the vertex shader
/// \param fragmentShader String containing the source code of the fragment shader
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromFile, LoadFromStream
///
////////////////////////////////////////////////////////////
bool LoadFromMemory(const std::string& vertexShader, const std::string& fragmentShader);
////////////////////////////////////////////////////////////
/// \brief Load either the vertex or fragment shader from a custom stream
///
/// This function loads a single shader, either vertex or
/// fragment, identified by the second argument.
/// The source code must be a valid shader in GLSL language.
/// GLSL is a C-like language dedicated to OpenGL shaders;
/// you'll probably need to read a good documentation for it
/// before writing your own shaders.
///
/// \param stream Source stream to read from
/// \param type Type of shader (vertex or fragment)
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromFile, LoadFromMemory
///
////////////////////////////////////////////////////////////
bool LoadFromStream(InputStream& stream);
bool LoadFromStream(InputStream& stream, Type type);
////////////////////////////////////////////////////////////
/// \brief Load both the vertex and fragment shaders from custom streams
///
/// This function loads both the vertex and the fragment
/// shaders. If one of them fails to load, the shader is left
/// empty (the valid shader is unloaded).
/// The source codes must be valid shaders in GLSL language.
/// GLSL is a C-like language dedicated to OpenGL shaders;
/// you'll probably need to read a good documentation for
/// it before writing your own shaders.
///
/// \param vertexShaderStream Source stream to read the vertex shader from
/// \param fragmentShaderStream Source stream to read the fragment shader from
///
/// \return True if loading succeeded, false if it failed
///
/// \see LoadFromFile, LoadFromMemory
///
////////////////////////////////////////////////////////////
bool LoadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream);
////////////////////////////////////////////////////////////
/// \brief Change a float parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a float
/// (float GLSL type).
///
/// Example:
/// \code
/// uniform float myparam; // this is the variable in the pixel shader
/// uniform float myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", 5.2f);
@ -138,8 +228,6 @@ public :
/// \param name Name of the parameter in the shader
/// \param x Value to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x);
@ -147,9 +235,12 @@ public :
/// \brief Change a 2-components vector parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a 2x1 vector
/// (vec2 GLSL type).
///
/// Example:
/// \code
/// uniform vec2 myparam; // this is the variable in the pixel shader
/// uniform vec2 myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", 5.2f, 6.0f);
@ -159,8 +250,6 @@ public :
/// \param x First component of the value to assign
/// \param y Second component of the value to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y);
@ -168,9 +257,12 @@ public :
/// \brief Change a 3-components vector parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a 3x1 vector
/// (vec3 GLSL type).
///
/// Example:
/// \code
/// uniform vec3 myparam; // this is the variable in the pixel shader
/// uniform vec3 myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", 5.2f, 6.0f, -8.1f);
@ -181,8 +273,6 @@ public :
/// \param y Second component of the value to assign
/// \param z Third component of the value to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y, float z);
@ -190,9 +280,12 @@ public :
/// \brief Change a 4-components vector parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a 4x1 vector
/// (vec4 GLSL type).
///
/// Example:
/// \code
/// uniform vec4 myparam; // this is the variable in the pixel shader
/// uniform vec4 myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", 5.2f, 6.0f, -8.1f, 0.4f);
@ -204,8 +297,6 @@ public :
/// \param z Third component of the value to assign
/// \param w Fourth component of the value to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y, float z, float w);
@ -213,9 +304,12 @@ public :
/// \brief Change a 2-components vector parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a 2x1 vector
/// (vec2 GLSL type).
///
/// Example:
/// \code
/// uniform vec2 myparam; // this is the variable in the pixel shader
/// uniform vec2 myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", sf::Vector2f(5.2f, 6.0f));
@ -224,8 +318,6 @@ public :
/// \param name Name of the parameter in the shader
/// \param vector Vector to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const Vector2f& vector);
@ -233,9 +325,12 @@ public :
/// \brief Change a 2-components vector parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// For example:
/// The corresponding parameter in the shader must be a 3x1 vector
/// (vec3 GLSL type).
///
/// Example:
/// \code
/// uniform vec3 myparam; // this is the variable in the pixel shader
/// uniform vec3 myparam; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("myparam", sf::Vector3f(5.2f, 6.0f, -8.1f));
@ -244,59 +339,113 @@ public :
/// \param name Name of the parameter in the shader
/// \param vector Vector to assign
///
/// \see SetTexture, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const Vector3f& vector);
////////////////////////////////////////////////////////////
/// \brief Change a texture parameter of the shader
/// \brief Change a color parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// The corresponding parameter in the shader must be a 4x1 vector
/// (vec4 GLSL type).
///
/// It is important to note that the components of the color are
/// normalized before being passed to the shader. Therefore,
/// they are converted from range [0 .. 255] to range [0 .. 1].
/// For example, a sf::Color(255, 125, 0, 255) will be transformed
/// to a vec4(1.0, 0.5, 0.0, 1.0) in the shader.
///
/// \a name is the name of the texture to change in the shader.
/// This function maps an external texture to the given shader
/// variable; to use the current texture of the object being drawn,
/// use SetCurrentTexture instead.
/// Example:
/// \code
/// // These are the variables in the pixel shader
/// uniform sampler2D the_texture;
/// uniform vec4 color; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetParameter("color", sf::Color(255, 128, 0, 255));
/// \endcode
///
/// \param name Name of the parameter in the shader
/// \param color Color to assign
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const Color& color);
////////////////////////////////////////////////////////////
/// \brief Change a matrix parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// The corresponding parameter in the shader must be a 4x4 matrix
/// (mat4 GLSL type).
///
/// Example:
/// \code
/// uniform mat4 matrix; // this is the variable in the shader
/// \endcode
/// \code
/// sf::Transform transform;
/// transform.Translate(5, 10);
/// shader.SetParameter("matrix", transform);
/// \endcode
///
/// \param name Name of the parameter in the shader
/// \param transform Transform to assign
///
////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const sf::Transform& transform);
////////////////////////////////////////////////////////////
/// \brief Change a texture parameter of the shader
///
/// \a name is the name of the variable to change in the shader.
/// The corresponding parameter in the shader must be a 2D texture
/// (sampler2D GLSL type).
///
/// Example:
/// \code
/// uniform sampler2D the_texture; // this is the variable in the shader
/// \endcode
/// \code
/// sf::Texture texture;
/// ...
/// shader.SetTexture("the_texture", texture);
/// shader.SetParameter("the_texture", texture);
/// \endcode
/// It is important to note that \a texture must remain alive as long
/// as the shader uses it, no copy is made internally.
///
/// To use the texture of the object being draw, which cannot be
/// known in advance, you can pass the special value
/// sf::Shader::CurrentTexture:
/// \code
/// shader.SetParameter("the_texture", sf::Shader::CurrentTexture).
/// \endcode
///
/// \param name Name of the texture in the shader
/// \param texture Texture to assign
///
/// \see SetParameter, SetCurrentTexture
///
////////////////////////////////////////////////////////////
void SetTexture(const std::string& name, const Texture& texture);
void SetParameter(const std::string& name, const Texture& texture);
////////////////////////////////////////////////////////////
/// \brief Set the current object texture in the shader
/// \brief Change a texture parameter of the shader
///
/// This overload maps a shader texture variable to the
/// texture of the object being drawn, which cannot be
/// known in advance. The second argument must be
/// sf::Shader::CurrentTexture.
/// The corresponding parameter in the shader must be a 2D texture
/// (sampler2D GLSL type).
///
/// This function maps a shader texture variable to the
/// texture of the object being drawn.
/// Example:
/// \code
/// // This is the variable in the pixel shader
/// uniform sampler2D current;
/// uniform sampler2D current; // this is the variable in the shader
/// \endcode
/// \code
/// shader.SetCurrentTexture("current");
/// shader.SetParameter("current", sf::Shader::CurrentTexture);
/// \endcode
///
/// \param name Name of the texture in the shader
///
/// \see SetParameter, SetTexture
///
////////////////////////////////////////////////////////////
void SetCurrentTexture(const std::string& name);
void SetParameter(const std::string& name, CurrentTextureType);
////////////////////////////////////////////////////////////
/// \brief Bind the shader for rendering (activate it)
@ -328,16 +477,6 @@ public :
////////////////////////////////////////////////////////////
void Unbind() const;
////////////////////////////////////////////////////////////
/// \brief Overload of assignment operator
///
/// \param right Instance to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
Shader& operator =(const Shader& right);
////////////////////////////////////////////////////////////
/// \brief Tell whether or not the system supports shaders
///
@ -352,15 +491,19 @@ public :
private :
friend class Renderer;
////////////////////////////////////////////////////////////
/// \brief Create the program and attach the shaders
/// \brief Compile the shader(s) and create the program
///
/// If one of the arguments is NULL, the corresponding shader
/// is not created.
///
/// \param vertexShaderCode Source code of the vertex shader
/// \param fragmentShaderCode Source code of the fragment shader
///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
bool CompileProgram();
bool CompileProgram(const char* vertexShaderCode, const char* fragmentShaderCode);
////////////////////////////////////////////////////////////
/// \brief Bind all the textures used by the shader
@ -371,16 +514,6 @@ private :
////////////////////////////////////////////////////////////
void BindTextures() const;
////////////////////////////////////////////////////////////
/// \brief Make sure that the shader is ready to be used
///
/// This function is called by the Renderer class, to make
/// sure that the shader's parameters are properly applied
/// even when Use() is not called due to internal optimizations.
///
////////////////////////////////////////////////////////////
void Use() const;
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
@ -392,7 +525,6 @@ private :
unsigned int myShaderProgram; ///< OpenGL identifier for the program
int myCurrentTexture; ///< Location of the current texture in the shader
TextureTable myTextures; ///< Texture variables in the shader, mapped to their location
std::string myFragmentShader; ///< Fragment shader source code
};
} // namespace sf
@ -405,34 +537,44 @@ private :
/// \class sf::Shader
/// \ingroup graphics
///
/// Pixel shaders (or fragment shaders) are programs written
/// using a specific language, executed directly by the
/// graphics card and allowing to apply per-pixel real-time
/// operations to the rendered entities.
/// Shaders are programs written using a specific language,
/// executed directly by the graphics card and allowing
/// to apply real-time operations to the rendered entities.
///
/// Pixel shaders are written in GLSL, which is a C-like
/// There are two kinds of shaders:
/// \li Vertex shaders, that process vertices
/// \li Fragment (pixel) shaders, that process pixels
///
/// A sf::Shader can be composed of either a vertex shader
/// alone, a fragment shader alone, or both combined
/// (see the variants of the Load functions).
///
/// Shaders are written in GLSL, which is a C-like
/// language dedicated to OpenGL shaders. You'll probably
/// need to learn its basics before writing your own shaders
/// for SFML.
///
/// Like any C/C++ program, a shader has its own variables
/// that you can set from your C++ application. sf::Shader
/// handles 3 different types of variables:
/// handles 4 different types of variables:
/// \li floats
/// \li vectors (2, 3 or 4 components)
/// \li textures
/// \li transforms (matrices)
///
/// The value of the variables can be changed at any time
/// with either Shader::SetParameter or Shader::SetTexture:
/// with either the various overloads of the SetParameter function:
/// \code
/// shader.SetParameter("offset", 2.f);
/// shader.SetParameter("color", 0.5f, 0.8f, 0.3f);
/// shader.SetTexture("overlay", texture); // texture is a sf::Texture
/// shader.SetCurrentTexture("texture");
/// shader.SetParameter("matrix", transform); // transform is a sf::Transform
/// shader.SetParameter("overlay", texture); // texture is a sf::Texture
/// shader.SetParameter("texture", sf::Shader::CurrentTexture);
/// \endcode
///
/// Shader::SetCurrentTexture maps the given texture variable
/// to the current texture of the object being drawn.
/// The special Shader::CurrentTexture argument maps the
/// given texture variable to the current texture of the
/// object being drawn (which cannot be known in advance).
///
/// To apply a shader to a drawable, you must pass it as an
/// additional parameter to the Draw function:
@ -440,15 +582,22 @@ private :
/// window.Draw(sprite, shader);
/// \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
/// 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.
/// ... 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 some combinations are
/// not interesting. For example, using a vertex shader on a sf::Sprite
/// is limited because there are only 4 vertices, the sprite would
/// have to be subdivided in order to apply wave effects.
/// Another bad example is a fragment shader with sf::Text: 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.
///
/// Shaders can also be used to apply global post-effects to the
/// current contents of the target (like the old sf::PostFx class
@ -462,11 +611,11 @@ 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
/// shader for custom OpenGL geometry.
/// sf::Shader can also be used directly as a raw shader for
/// custom OpenGL geometry.
/// \code
/// window.SetActive();
/// shader.Bind();

View File

@ -29,208 +29,155 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/System/Vector2.hpp>
#include <vector>
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,118 @@ public :
float GetOutlineThickness() const;
////////////////////////////////////////////////////////////
/// \brief Create a new line
/// \brief Get the total number of points of the 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 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.
///
/// \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 Number of points of the shape
///
////////////////////////////////////////////////////////////
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));
virtual unsigned int GetPointsCount() const = 0;
////////////////////////////////////////////////////////////
/// \brief Create a new line
/// \brief Get a point of the 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 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.
/// \param index Index of the point to get, in range [0 .. GetPointsCount() - 1]
///
/// \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 Index-th point of the shape
///
////////////////////////////////////////////////////////////
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));
virtual Vector2f GetPoint(unsigned int index) const = 0;
////////////////////////////////////////////////////////////
/// \brief Create a new rectangular shape
/// \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 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.
/// 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 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
/// \return Local bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
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));
FloatRect GetLocalBounds() const;
////////////////////////////////////////////////////////////
/// \brief Create a new rectangular shape
/// \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::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.
/// 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 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
/// \return Global bounding rectangle of the entity
///
////////////////////////////////////////////////////////////
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 Draw the shape to a render target
///
/// This function precomputes all the internal parameters
/// needed to properly render the shape (center, outline points).
/// \param target Render target to draw to
/// \param states Current render states
///
////////////////////////////////////////////////////////////
void Compile();
virtual void Draw(RenderTarget& target, RenderStates states) const;
////////////////////////////////////////////////////////////
/// \brief Compute the normal of a given 2D segment
///
/// \param p1 First point of the segment
/// \param p2 Second point of the segment
/// \param normal Variable to fill with the calculated normal
///
/// \return False if the normal couldn't be calculated (segment is null)
/// \brief Update the fill vertices' color
///
////////////////////////////////////////////////////////////
static bool ComputeNormal(const Vector2f& p1, const Vector2f& p2, Vector2f& normal);
void UpdateFillColors();
////////////////////////////////////////////////////////////
/// \brief Define a simple 2D point with position, normal and colors
/// \brief Update the fill vertices' texture coordinates
///
////////////////////////////////////////////////////////////
struct Point
{
Point(const Vector2f& position = Vector2f(0, 0), const Color& color = Color(255, 255, 255), const Color& outlineColor = Color(255, 255, 255));
void UpdateTexCoords();
Vector2f Position; ///< Position
Vector2f Normal; ///< Extruded normal
Color Col; ///< Color of the point
Color OutlineCol; ///< Outline color of the point
};
////////////////////////////////////////////////////////////
/// \brief Update the outline vertices' position
///
////////////////////////////////////////////////////////////
void UpdateOutline();
////////////////////////////////////////////////////////////
/// \brief Update the outline vertices' color
///
////////////////////////////////////////////////////////////
void UpdateOutlineColors();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
std::vector<Point> 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 +311,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
///
////////////////////////////////////////////////////////////

View File

@ -29,6 +29,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/Rect.hpp>
@ -38,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 :
@ -56,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
///
@ -69,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.
///
@ -165,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
////////////////////////////////////////////////////////////
const Texture* 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
@ -222,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.
@ -236,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).
///
@ -253,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
///
////////////////////////////////////////////////////////////

View File

@ -30,9 +30,12 @@
////////////////////////////////////////////////////////////
#include <SFML/System/String.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <string>
#include <vector>
namespace sf
@ -41,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 :
@ -99,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().
///
@ -135,6 +144,18 @@ public :
////////////////////////////////////////////////////////////
void SetStyle(Uint32 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
///
@ -187,14 +208,23 @@ public :
////////////////////////////////////////////////////////////
Uint32 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.
///
@ -203,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
const Font* myFont; ///< Font used to display the string
unsigned int myCharacterSize; ///< Base size of characters, in pixels
Uint32 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
Uint32 myStyle; ///< Text style (see 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
@ -258,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
@ -293,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
///
////////////////////////////////////////////////////////////

View File

@ -35,7 +35,7 @@
namespace sf
{
class Window;
class Renderer;
class RenderTarget;
class RenderTexture;
class InputStream;
@ -45,6 +45,18 @@ class InputStream;
////////////////////////////////////////////////////////////
class SFML_API Texture : 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 :
////////////////////////////////////////////////////////////
@ -353,12 +365,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
@ -387,18 +410,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
@ -424,8 +467,8 @@ public :
private :
friend class Renderer;
friend class RenderTexture;
friend class RenderTarget;
////////////////////////////////////////////////////////////
/// \brief Get a valid image size according to hardware support
@ -451,7 +494,9 @@ 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
Uint64 myCacheId; ///< Unique number that identifies the texture to the render target's cache
};
} // namespace sf
@ -514,7 +559,7 @@ private :
/// sprite.SetTexture(texture);
///
/// // Draw the textured sprite
/// window.Draw(sprite); // window is a sf::RenderWindow
/// window.Draw(sprite);
/// \endcode
///
/// \code

View File

@ -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 <SFML/Config.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/System/Vector2.hpp>
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
///
////////////////////////////////////////////////////////////

View File

@ -0,0 +1,416 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Transform.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Decomposed transform defined by a position, a rotation and a scale
///
////////////////////////////////////////////////////////////
class SFML_API Transformable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
Transformable();
////////////////////////////////////////////////////////////
/// \brief Virtual destructor
///
////////////////////////////////////////////////////////////
virtual ~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
///
/// 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
///
/// 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
///
////////////////////////////////////////////////////////////

View File

@ -0,0 +1,147 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
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 sf::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 Vector2f& 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 sf::Color& color, const Vector2f& texCoords);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Vector2f Position; ///< 2D position of the vertex
sf::Color Color; ///< Color of the vertex
Vector2f 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::Vector2f( 0, 0)),
/// sf::Vertex(sf::Vector2f( 0, 100), sf::Color::Red, sf::Vector2f( 0, 10)),
/// sf::Vertex(sf::Vector2f(100, 100), sf::Color::Red, sf::Vector2f(10, 10)),
/// sf::Vertex(sf::Vector2f(100, 0), sf::Color::Red, sf::Vector2f(10, 0))
/// };
///
/// // draw it
/// window.Draw(vertices, 4, sf::Quads);
/// \endcode
///
/// Note: although texture coordinates are supposed to be an integer
/// amount of pixels, their type is float because of some buggy graphics
/// drivers that are not able to process integer coordinates correctly.
///
/// \see sf::VertexArray
///
////////////////////////////////////////////////////////////

View File

@ -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 <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <vector>
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<Vertex> 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
///
////////////////////////////////////////////////////////////

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Matrix3.hpp>
#include <SFML/Graphics/Transform.hpp>
#include <SFML/System/Vector2.hpp>
@ -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

View File

@ -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
///

View File

@ -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
///

View File

@ -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}/ConvexShape.cpp
${INCROOT}/ConvexShape.hpp
${SRCROOT}/Sprite.cpp
${INCROOT}/Sprite.hpp
${SRCROOT}/Text.cpp
${INCROOT}/Text.hpp
${SRCROOT}/Texture.cpp
${INCROOT}/Texture.hpp
${SRCROOT}/TextureSaver.cpp
${SRCROOT}/TextureSaver.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
)

View File

@ -0,0 +1,84 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/CircleShape.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
CircleShape::CircleShape(float radius, unsigned int pointsCount) :
myRadius (radius),
myPointsCount(pointsCount)
{
Update();
}
////////////////////////////////////////////////////////////
void CircleShape::SetRadius(float radius)
{
myRadius = radius;
Update();
}
////////////////////////////////////////////////////////////
float CircleShape::GetRadius() const
{
return myRadius;
}
////////////////////////////////////////////////////////////
void CircleShape::SetPointsCount(unsigned int count)
{
myPointsCount = count;
Update();
}
////////////////////////////////////////////////////////////
unsigned int CircleShape::GetPointsCount() const
{
return myPointsCount;
}
////////////////////////////////////////////////////////////
Vector2f CircleShape::GetPoint(unsigned int index) const
{
static const float pi = 3.141592654f;
float angle = index * 2 * pi / myPointsCount - pi / 2;
float x = std::cos(angle) * myRadius;
float y = std::sin(angle) * myRadius;
return Vector2f(myRadius + x, myRadius + y);
}
} // namespace sf

View File

@ -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);
////////////////////////////////////////////////////////////

View File

@ -0,0 +1,69 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/ConvexShape.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
ConvexShape::ConvexShape(unsigned int pointsCount)
{
SetPointsCount(pointsCount);
}
////////////////////////////////////////////////////////////
void ConvexShape::SetPointsCount(unsigned int count)
{
myPoints.resize(count);
Update();
}
////////////////////////////////////////////////////////////
unsigned int ConvexShape::GetPointsCount() const
{
return myPoints.size();
}
////////////////////////////////////////////////////////////
void ConvexShape::SetPoint(unsigned int index, const Vector2f& point)
{
myPoints[index] = point;
Update();
}
////////////////////////////////////////////////////////////
Vector2f ConvexShape::GetPoint(unsigned int index) const
{
return myPoints[index];
}
} // namespace sf

View File

@ -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 <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cmath>
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<float>(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

View File

@ -451,7 +451,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;
@ -492,10 +492,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);
}

View File

@ -44,7 +44,7 @@ namespace priv
#ifdef SFML_DEBUG
// In debug mode, perform a test on every OpenGL call
#define GLCheck(call) ((call), sf::priv::GLCheckError(__FILE__, __LINE__))
#define GLCheck(call) ((call), sf::priv::GLCheckError(__FILE__, __LINE__))
#else

View File

@ -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 <SFML/Graphics/RectangleShape.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
RectangleShape::RectangleShape(const Vector2f& size)
{
SetSize(size);
}
////////////////////////////////////////////////////////////
void RectangleShape::SetSize(const Vector2f& size)
{
mySize = size;
Update();
}
////////////////////////////////////////////////////////////
const Vector2f& RectangleShape::GetSize() const
{
return mySize;
}
////////////////////////////////////////////////////////////
unsigned int RectangleShape::GetPointsCount() const
{
return 4;
}
////////////////////////////////////////////////////////////
Vector2f RectangleShape::GetPoint(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

View File

@ -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 <SFML/Graphics/RenderStates.hpp>
#include <cstddef>
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

View File

@ -27,96 +27,37 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <iostream>
#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 (),
myCache ()
{
}
////////////////////////////////////////////////////////////
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;
myCache.ViewChanged = true;
}
////////////////////////////////////////////////////////////
const View& RenderTarget::GetView() const
{
return myCurrentView;
return myView;
}
@ -175,35 +115,166 @@ Vector2f RenderTarget::ConvertCoords(unsigned int x, unsigned int y, const View&
coords.y = 1.f - 2.f * (static_cast<int>(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;
// Check if the vertex count is low enough so that we can pre-transform them
bool useVertexCache = (verticesCount <= StatesCache::VertexCacheSize);
if (useVertexCache)
{
// Pre-transform the vertices and store them into the vertex cache
for (unsigned int i = 0; i < verticesCount; ++i)
{
Vertex& vertex = myCache.VertexCache[i];
vertex.Position = states.Transform * vertices[i].Position;
vertex.Color = vertices[i].Color;
vertex.TexCoords = vertices[i].TexCoords;
}
// Restore the render states and the current view, for SFML rendering
myRenderer.Initialize();
SetView(GetView());
// Since vertices are transformed, we must use an identity transform to render them
if (!myCache.UseVertexCache)
ApplyTransform(Transform::Identity);
}
else
{
ApplyTransform(states.Transform);
}
// Apply the view
if (myCache.ViewChanged)
ApplyCurrentView();
// Apply the blend mode
if (states.BlendMode != myCache.LastBlendMode)
ApplyBlendMode(states.BlendMode);
// Apply the texture
Uint64 textureId = states.Texture ? states.Texture->myCacheId : 0;
if (textureId != myCache.LastTextureId)
ApplyTexture(states.Texture);
// Apply the shader
if (states.Shader)
ApplyShader(states.Shader);
// If we pre-transform the vertices, we must use our internal vertex cache
if (useVertexCache)
{
// ... and if we already used it previously, we don't need to set the pointers again
if (!myCache.UseVertexCache)
vertices = myCache.VertexCache;
else
vertices = NULL;
}
// Setup the pointers to the vertices' components
if (vertices)
{
const char* data = reinterpret_cast<const char*>(vertices);
GLCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0));
GLCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8));
GLCheck(glTexCoordPointer(2, GL_FLOAT, 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));
// Unbind the shader, if any
if (states.Shader)
ApplyShader(NULL);
// Update the cache
myCache.UseVertexCache = useVertexCache;
}
}
////////////////////////////////////////////////////////////
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();
// Define the default OpenGL states
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(glMatrixMode(GL_MODELVIEW));
GLCheck(glEnableClientState(GL_VERTEX_ARRAY));
GLCheck(glEnableClientState(GL_COLOR_ARRAY));
GLCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
// Apply the default SFML states
ApplyBlendMode(BlendAlpha);
ApplyTransform(Transform::Identity);
ApplyTexture(NULL);
ApplyShader(NULL);
myCache.UseVertexCache = false;
// Set the default view
SetView(GetView());
}
}
@ -211,13 +282,135 @@ void RenderTarget::RestoreGLStates()
////////////////////////////////////////////////////////////
void RenderTarget::Initialize()
{
// Setup the default view
// Setup the default and current views
myDefaultView.Reset(FloatRect(0, 0, static_cast<float>(GetWidth()), static_cast<float>(GetHeight())));
SetView(myDefaultView);
myView = myDefaultView;
// Initialize the renderer
if (Activate(true))
myRenderer.Initialize();
// Initialize the default OpenGL render-states
ResetGLStates();
}
////////////////////////////////////////////////////////////
void RenderTarget::ApplyCurrentView()
{
// Set the viewport
IntRect viewport = GetViewport(myView);
int top = GetHeight() - (viewport.Top + viewport.Height);
GLCheck(glViewport(viewport.Left, top, viewport.Width, viewport.Height));
// Set the projection matrix
GLCheck(glMatrixMode(GL_PROJECTION));
GLCheck(glLoadMatrixf(myView.GetTransform().GetMatrix()));
// Go back to model-view mode
GLCheck(glMatrixMode(GL_MODELVIEW));
myCache.ViewChanged = false;
}
////////////////////////////////////////////////////////////
void RenderTarget::ApplyBlendMode(BlendMode mode)
{
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 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;
}
myCache.LastBlendMode = mode;
}
////////////////////////////////////////////////////////////
void RenderTarget::ApplyTransform(const Transform& transform)
{
// No need to call glMatrixMode(GL_MODELVIEW), it is always the
// current mode (for optimization purpose, since it's the most used)
GLCheck(glLoadMatrixf(transform.GetMatrix()));
}
////////////////////////////////////////////////////////////
void RenderTarget::ApplyTexture(const Texture* texture)
{
if (texture)
texture->Bind(Texture::Pixels);
else
GLCheck(glBindTexture(GL_TEXTURE_2D, 0));
myCache.LastTextureId = texture ? texture->myCacheId : 0;
}
////////////////////////////////////////////////////////////
void RenderTarget::ApplyShader(const Shader* shader)
{
if (shader)
shader->Bind();
else
GLCheck(glUseProgramObjectARB(0));
}
} // namespace sf
////////////////////////////////////////////////////////////
// Render states caching strategies
//
// * View
// If SetView was called since last draw, the projection
// matrix is updated. We don't need more, the view doesn't
// change frequently.
//
// * Transform
// The transform matrix is usually expensive because each
// entity will most likely use a different transform. This can
// lead, in worst case, to changing it every 4 vertices.
// To avoid that, when the vertex count is low enough, we
// pre-transform them and therefore use an identity transform
// to render them.
//
// * Blending mode
// It's a simple integral value, so we can easily check
// whether the value to apply is the same as before or not.
//
// * Texture
// Storing the pointer or OpenGL ID of the last used texture
// is not enough; if the sf::Texture instance is destroyed,
// both the pointer and the OpenGL ID might be recycled in
// a new texture instance. We need to use our own unique
// identifier system to ensure consistent caching.
//
// * Shader
// Shaders are very hard to optimize, because they have
// parameters that can be hard (if not impossible) to track,
// like matrices or textures. The only optimization that we
// do is that we avoid setting a null shader if there was
// already none for the previous draw.
//
////////////////////////////////////////////////////////////

View File

@ -27,6 +27,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Graphics/TextureSaver.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
@ -77,6 +78,9 @@ bool RenderTextureImplDefault::Activate(bool active)
////////////////////////////////////////////////////////////
void RenderTextureImplDefault::UpdateTexture(unsigned int textureId)
{
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Copy the rendered pixels to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));

View File

@ -83,7 +83,7 @@ bool RenderTextureImplFBO::IsAvailable()
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{
//Create the context
// Create the context
myContext = new Context;
// Create the framebuffer object

View File

@ -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 <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/GLCheck.hpp>
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

View File

@ -27,6 +27,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
@ -46,30 +47,50 @@ namespace
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &maxUnits));
return maxUnits;
}
// Read the contents of a file into an array of char
bool GetFileContents(const std::string& filename, std::vector<char>& buffer)
{
std::ifstream file(filename.c_str(), std::ios_base::binary);
if (file)
{
file.seekg(0, std::ios_base::end);
std::streamsize size = file.tellg();
file.seekg(0, std::ios_base::beg);
buffer.resize(size);
file.read(&buffer[0], size);
buffer.push_back('\0');
return true;
}
else
{
return false;
}
}
// Read the contents of a stream into an array of char
bool GetStreamContents(sf::InputStream& stream, std::vector<char>& buffer)
{
sf::Int64 size = stream.GetSize();
buffer.resize(static_cast<std::size_t>(size));
sf::Int64 read = stream.Read(&buffer[0], size);
buffer.push_back('\0');
return read == size;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Shader::CurrentTextureType Shader::CurrentTexture;
////////////////////////////////////////////////////////////
Shader::Shader() :
myShaderProgram (0),
myCurrentTexture(-1)
{
}
////////////////////////////////////////////////////////////
Shader::Shader(const Shader& copy) :
myShaderProgram (0),
myCurrentTexture(copy.myCurrentTexture),
myTextures (copy.myTextures),
myFragmentShader(copy.myFragmentShader)
{
// Create the shaders and the program
if (copy.myShaderProgram)
CompileProgram();
}
@ -85,48 +106,107 @@ Shader::~Shader()
////////////////////////////////////////////////////////////
bool Shader::LoadFromFile(const std::string& filename)
bool Shader::LoadFromFile(const std::string& filename, Type type)
{
// Open the file
std::ifstream file(filename.c_str());
if (!file)
// Read the file
std::vector<char> shader;
if (!GetFileContents(filename, shader))
{
Err() << "Failed to open shader file \"" << filename << "\"" << std::endl;
return false;
}
// Read the shader code from the file
myFragmentShader.clear();
std::string line;
while (std::getline(file, line))
myFragmentShader += line + "\n";
// Create the shaders and the program
return CompileProgram();
// Compile the shader program
if (type == Vertex)
return CompileProgram(&shader[0], NULL);
else
return CompileProgram(NULL, &shader[0]);
}
////////////////////////////////////////////////////////////
bool Shader::LoadFromMemory(const std::string& shader)
bool Shader::LoadFromFile(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename)
{
// Save the shader code
myFragmentShader = shader;
// Read the vertex shader file
std::vector<char> vertexShader;
if (!GetFileContents(vertexShaderFilename, vertexShader))
{
Err() << "Failed to open vertex shader file \"" << vertexShaderFilename << "\"" << std::endl;
return false;
}
// Create the shaders and the program
return CompileProgram();
// Read the fragment shader file
std::vector<char> fragmentShader;
if (!GetFileContents(fragmentShaderFilename, fragmentShader))
{
Err() << "Failed to open fragment shader file \"" << fragmentShaderFilename << "\"" << std::endl;
return false;
}
// Compile the shader program
return CompileProgram(&vertexShader[0], &fragmentShader[0]);
}
////////////////////////////////////////////////////////////
bool Shader::LoadFromStream(InputStream& stream)
bool Shader::LoadFromMemory(const std::string& shader, Type type)
{
// Compile the shader program
if (type == Vertex)
return CompileProgram(shader.c_str(), NULL);
else
return CompileProgram(NULL, shader.c_str());
}
////////////////////////////////////////////////////////////
bool Shader::LoadFromMemory(const std::string& vertexShader, const std::string& fragmentShader)
{
// Compile the shader program
return CompileProgram(vertexShader.c_str(), fragmentShader.c_str());
}
////////////////////////////////////////////////////////////
bool Shader::LoadFromStream(InputStream& stream, Type type)
{
// Read the shader code from the stream
std::vector<char> buffer(static_cast<std::size_t>(stream.GetSize()));
Int64 read = stream.Read(&buffer[0], buffer.size());
myFragmentShader.assign(&buffer[0], &buffer[0] + read);
std::vector<char> shader;
if (!GetStreamContents(stream, shader))
{
Err() << "Failed to read shader from stream" << std::endl;
return false;
}
// Create the shaders and the program
return CompileProgram();
// Compile the shader program
if (type == Vertex)
return CompileProgram(&shader[0], NULL);
else
return CompileProgram(NULL, &shader[0]);
}
////////////////////////////////////////////////////////////
bool Shader::LoadFromStream(InputStream& vertexShaderStream, InputStream& fragmentShaderStream)
{
// Read the vertex shader code from the stream
std::vector<char> vertexShader;
if (!GetStreamContents(vertexShaderStream, vertexShader))
{
Err() << "Failed to read vertex shader from stream" << std::endl;
return false;
}
// Read the fragment shader code from the stream
std::vector<char> fragmentShader;
if (!GetStreamContents(fragmentShaderStream, fragmentShader))
{
Err() << "Failed to read fragment shader from stream" << std::endl;
return false;
}
// Compile the shader program
return CompileProgram(&vertexShader[0], &fragmentShader[0]);
}
@ -241,7 +321,38 @@ void Shader::SetParameter(const std::string& name, const Vector3f& v)
////////////////////////////////////////////////////////////
void Shader::SetTexture(const std::string& name, const Texture& texture)
void Shader::SetParameter(const std::string& name, const Color& color)
{
SetParameter(name, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
}
////////////////////////////////////////////////////////////
void Shader::SetParameter(const std::string& name, const sf::Transform& transform)
{
if (myShaderProgram)
{
EnsureGlContext();
// Enable program
GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
GLCheck(glUseProgramObjectARB(myShaderProgram));
// Get parameter location and assign it new values
GLint location = glGetUniformLocationARB(myShaderProgram, name.c_str());
if (location != -1)
GLCheck(glUniformMatrix4fvARB(location, 1, GL_FALSE, transform.GetMatrix()));
else
Err() << "Parameter \"" << name << "\" not found in shader" << std::endl;
// Disable program
GLCheck(glUseProgramObjectARB(program));
}
}
////////////////////////////////////////////////////////////
void Shader::SetParameter(const std::string& name, const Texture& texture)
{
if (myShaderProgram)
{
@ -279,7 +390,7 @@ void Shader::SetTexture(const std::string& name, const Texture& texture)
////////////////////////////////////////////////////////////
void Shader::SetCurrentTexture(const std::string& name)
void Shader::SetParameter(const std::string& name, CurrentTextureType)
{
if (myShaderProgram)
{
@ -322,20 +433,6 @@ void Shader::Unbind() const
}
////////////////////////////////////////////////////////////
Shader& Shader::operator =(const Shader& right)
{
Shader temp(right);
std::swap(myShaderProgram, temp.myShaderProgram);
std::swap(myCurrentTexture, temp.myCurrentTexture);
std::swap(myTextures, temp.myTextures);
std::swap(myFragmentShader, temp.myFragmentShader);
return *this;
}
////////////////////////////////////////////////////////////
bool Shader::IsAvailable()
{
@ -352,7 +449,7 @@ bool Shader::IsAvailable()
////////////////////////////////////////////////////////////
bool Shader::CompileProgram()
bool Shader::CompileProgram(const char* vertexShaderCode, const char* fragmentShaderCode)
{
EnsureGlContext();
@ -368,74 +465,73 @@ bool Shader::CompileProgram()
if (myShaderProgram)
GLCheck(glDeleteObjectARB(myShaderProgram));
// Define the vertex shader source (we provide it directly as it doesn't have to change)
static const char* vertexSrc =
"void main()"
"{"
" gl_TexCoord[0] = gl_MultiTexCoord0;"
" gl_FrontColor = gl_Color;"
" gl_Position = ftransform();"
"}";
// Create the program
myShaderProgram = glCreateProgramObjectARB();
// Create the shaders
GLhandleARB vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
GLhandleARB fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
// Compile them
const char* fragmentSrc = myFragmentShader.c_str();
GLCheck(glShaderSourceARB(vertexShader, 1, &vertexSrc, NULL));
GLCheck(glShaderSourceARB(fragmentShader, 1, &fragmentSrc, NULL));
GLCheck(glCompileShaderARB(vertexShader));
GLCheck(glCompileShaderARB(fragmentShader));
// Check the compile logs
GLint success;
GLCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
if (success == GL_FALSE)
// Create the vertex shader if needed
if (vertexShaderCode)
{
char log[1024];
GLCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log));
Err() << "Failed to compile shader:" << std::endl
<< log << std::endl;
// Create and compile the shader
GLhandleARB vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
GLCheck(glShaderSourceARB(vertexShader, 1, &vertexShaderCode, NULL));
GLCheck(glCompileShaderARB(vertexShader));
// Check the compile log
GLint success;
GLCheck(glGetObjectParameterivARB(vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
if (success == GL_FALSE)
{
char log[1024];
GLCheck(glGetInfoLogARB(vertexShader, sizeof(log), 0, log));
Err() << "Failed to compile vertex shader:" << std::endl
<< log << std::endl;
GLCheck(glDeleteObjectARB(vertexShader));
GLCheck(glDeleteObjectARB(myShaderProgram));
myShaderProgram = 0;
return false;
}
// Attach the shader to the program, and delete it (not needed anymore)
GLCheck(glAttachObjectARB(myShaderProgram, vertexShader));
GLCheck(glDeleteObjectARB(vertexShader));
GLCheck(glDeleteObjectARB(fragmentShader));
GLCheck(glDeleteObjectARB(myShaderProgram));
myShaderProgram = 0;
return false;
}
GLCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
if (success == GL_FALSE)
{
char log[1024];
GLCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log));
Err() << "Failed to compile shader:" << std::endl
<< log << std::endl;
GLCheck(glDeleteObjectARB(vertexShader));
GLCheck(glDeleteObjectARB(fragmentShader));
GLCheck(glDeleteObjectARB(myShaderProgram));
myShaderProgram = 0;
return false;
}
// Attach the shaders to the program
GLCheck(glAttachObjectARB(myShaderProgram, vertexShader));
GLCheck(glAttachObjectARB(myShaderProgram, fragmentShader));
// Create the fragment shader if needed
if (fragmentShaderCode)
{
// Create and compile the shader
GLhandleARB fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
GLCheck(glShaderSourceARB(fragmentShader, 1, &fragmentShaderCode, NULL));
GLCheck(glCompileShaderARB(fragmentShader));
// We can now delete the shaders
GLCheck(glDeleteObjectARB(vertexShader));
GLCheck(glDeleteObjectARB(fragmentShader));
// Check the compile log
GLint success;
GLCheck(glGetObjectParameterivARB(fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &success));
if (success == GL_FALSE)
{
char log[1024];
GLCheck(glGetInfoLogARB(fragmentShader, sizeof(log), 0, log));
Err() << "Failed to compile fragment shader:" << std::endl
<< log << std::endl;
GLCheck(glDeleteObjectARB(fragmentShader));
GLCheck(glDeleteObjectARB(myShaderProgram));
myShaderProgram = 0;
return false;
}
// Attach the shader to the program, and delete it (not needed anymore)
GLCheck(glAttachObjectARB(myShaderProgram, fragmentShader));
GLCheck(glDeleteObjectARB(fragmentShader));
}
// Link the program
GLCheck(glLinkProgramARB(myShaderProgram));
// Get link log
// Check the link log
GLint success;
GLCheck(glGetObjectParameterivARB(myShaderProgram, GL_OBJECT_LINK_STATUS_ARB, &success));
if (success == GL_FALSE)
{
// Oops... link errors
char log[1024];
GLCheck(glGetInfoLogARB(myShaderProgram, sizeof(log), 0, log));
Err() << "Failed to link shader:" << std::endl
@ -466,11 +562,4 @@ void Shader::BindTextures() const
GLCheck(glActiveTextureARB(GL_TEXTURE0_ARB));
}
////////////////////////////////////////////////////////////
void Shader::Use() const
{
BindTextures();
}
} // namespace sf

View File

@ -26,365 +26,270 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/Err.hpp>
#include <cmath>
////////////////////////////////////////////////////////////
// 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<unsigned int>(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 offset
}
////////////////////////////////////////////////////////////
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 = GetPointsCount();
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)
myVertices.Resize(0);
myOutlineVertices.Resize(0);
return;
// Make sure the shape is compiled
if (!myIsCompiled)
const_cast<Shape*>(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<Point>::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
for (unsigned int i = 0; i < count; ++i)
myVertices[i + 1].Position = GetPoint(i);
myVertices[count + 1].Position = myVertices[1].Position;
// Update the bounding rectangle
myVertices[0] = myVertices[1]; // so that the result of GetBounds() is correct
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<Point>::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<float>(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<Uint8>(r / nbPoints);
center.Col.g = static_cast<Uint8>(g / nbPoints);
center.Col.b = static_cast<Uint8>(b / nbPoints);
center.Col.a = static_cast<Uint8>(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 = myTextureRect.Left + myTextureRect.Width * xratio;
myVertices[i].TexCoords.y = 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

View File

@ -27,48 +27,44 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <utility>
#include <SFML/Graphics/RenderTarget.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Sprite::Sprite() :
Drawable (),
myTexture (NULL),
mySubRect (0, 0, 1, 1),
myIsFlippedX(false),
myIsFlippedY(false)
myTexture (NULL),
myTextureRect(0, 0, 0, 0)
{
}
////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture) :
Drawable (),
myTexture (NULL),
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;
@ -76,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;
}
@ -119,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<float>(mySubRect.Width);
float height = static_cast<float>(mySubRect.Height);
float width = static_cast<float>(myTextureRect.Width);
float height = static_cast<float>(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<float>(myTextureRect.Width);
float height = static_cast<float>(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()
{
float left = static_cast<float>(myTextureRect.Left);
float right = left + myTextureRect.Width;
float top = static_cast<float>(myTextureRect.Top);
float bottom = top + myTextureRect.Height;
myVertices[0].TexCoords = Vector2f(left, top);
myVertices[1].TexCoords = Vector2f(left, bottom);
myVertices[2].TexCoords = Vector2f(right, bottom);
myVertices[3].TexCoords = Vector2f(right, top);
}
} // namespace sf

View File

@ -27,17 +27,20 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Renderer.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cassert>
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(Uint32 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 @@ Uint32 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<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
// Precompute the variables needed by the algorithm
bool bold = (myStyle & Bold) != 0;
float hspace = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float vspace = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
// Compute the position
Vector2f position;
Uint32 prevChar = 0;
float lineSpacing = static_cast<float>(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<float>(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<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float vspace = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float x = 0.f;
float y = static_cast<float>(myCharacterSize);
// Initialize the rendering coordinates
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
float x = 0.f;
float y = static_cast<float>(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, Vector2f(1, 1)));
myVertices.Append(Vertex(Vector2f(x, top), myColor, Vector2f(2, 1)));
myVertices.Append(Vertex(Vector2f(x, bottom), myColor, Vector2f(2, 2)));
myVertices.Append(Vertex(Vector2f(0, bottom), myColor, Vector2f(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();
float u1 = static_cast<float>(glyph.TextureRect.Left);
float v1 = static_cast<float>(glyph.TextureRect.Top);
float u2 = static_cast<float>(glyph.TextureRect.Left + glyph.TextureRect.Width);
float v2 = static_cast<float>(glyph.TextureRect.Top + glyph.TextureRect.Height);
// Add a quad for the current character
myVertices.Append(Vertex(Vector2f(x + left - italic * top, y + top), myColor, Vector2f(u1, v1)));
myVertices.Append(Vertex(Vector2f(x + right - italic * top, y + top), myColor, Vector2f(u2, v1)));
myVertices.Append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), myColor, Vector2f(u2, v2)));
myVertices.Append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), myColor, Vector2f(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<float>(myCharacterSize);
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
float lineSpacing = static_cast<float>(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<float>(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<float>(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, Vector2f(1, 1)));
myVertices.Append(Vertex(Vector2f(x, top), myColor, Vector2f(2, 1)));
myVertices.Append(Vertex(Vector2f(x, bottom), myColor, Vector2f(2, 2)));
myVertices.Append(Vertex(Vector2f(0, bottom), myColor, Vector2f(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

View File

@ -28,12 +28,33 @@
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Graphics/TextureSaver.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <cstring>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
// Thread-safe unique identifier generator,
// is used for states cache (see RenderTarget)
sf::Uint64 GetUniqueId()
{
static sf::Uint64 id = 1; // start at 1, zero is "no texture"
static sf::Mutex mutex;
sf::Lock lock(mutex);
return id++;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
@ -44,7 +65,9 @@ myTextureWidth (0),
myTextureHeight(0),
myTexture (0),
myIsSmooth (false),
myPixelsFlipped(false)
myIsRepeated (false),
myPixelsFlipped(false),
myCacheId (GetUniqueId())
{
}
@ -58,7 +81,9 @@ myTextureWidth (0),
myTextureHeight(0),
myTexture (0),
myIsSmooth (copy.myIsSmooth),
myPixelsFlipped(false)
myIsRepeated (copy.myIsRepeated),
myPixelsFlipped(false),
myCacheId (GetUniqueId())
{
if (copy.myTexture)
LoadFromImage(copy.CopyToImage());
@ -121,13 +146,17 @@ bool Texture::Create(unsigned int width, unsigned int height)
myTexture = static_cast<unsigned int>(texture);
}
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// 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));
myCacheId = GetUniqueId();
return true;
}
@ -193,6 +222,9 @@ bool Texture::LoadFromImage(const Image& image, const IntRect& area)
// Create the texture and upload the pixels
if (Create(rectangle.Width, rectangle.Height))
{
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Copy the pixels to the texture, row by row
const Uint8* pixels = image.GetPixelsPtr() + 4 * (rectangle.Left + (width * rectangle.Top));
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
@ -235,6 +267,9 @@ Image Texture::CopyToImage() const
EnsureGlContext();
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Create an array of pixels
std::vector<Uint8> pixels(myWidth * myHeight * 4);
@ -300,10 +335,14 @@ void Texture::Update(const Uint8* pixels, unsigned int width, unsigned int heigh
{
EnsureGlContext();
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Copy pixels from the given array to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
myPixelsFlipped = false;
myCacheId = GetUniqueId();
}
}
@ -338,18 +377,54 @@ void Texture::Update(const Window& window, unsigned int x, unsigned int y)
if (myTexture && window.SetActive(true))
{
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
// Copy pixels from the back-buffer to the texture
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 0, 0, window.GetWidth(), window.GetHeight()));
myPixelsFlipped = true;
myCacheId = GetUniqueId();
}
}
////////////////////////////////////////////////////////////
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<float>(myHeight / myTextureHeight);
}
// Load the matrix
GLCheck(glMatrixMode(GL_TEXTURE));
GLCheck(glLoadMatrixf(matrix));
// Go back to model-view mode (sf::RenderTarget relies on it)
GLCheck(glMatrixMode(GL_MODELVIEW));
}
}
@ -364,6 +439,9 @@ void Texture::SetSmooth(bool smooth)
{
EnsureGlContext();
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
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));
@ -380,32 +458,31 @@ 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<float>(myTextureWidth);
float height = static_cast<float>(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();
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
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,7 +509,9 @@ 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);
myCacheId = GetUniqueId();
return *this;
}

View File

@ -1,40 +1,50 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Matrix3.hpp>
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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/TextureSaver.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
TextureSaver::TextureSaver()
{
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &myTextureBinding));
}
////////////////////////////////////////////////////////////
TextureSaver::~TextureSaver()
{
GLCheck(glBindTexture(GL_TEXTURE_2D, myTextureBinding));
}
} // namespace priv
} // namespace sf

View File

@ -0,0 +1,75 @@
////////////////////////////////////////////////////////////
//
// 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_TEXTURESAVER_HPP
#define SFML_TEXTURESAVER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/GLCheck.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Automatic wrapper for saving and restoring the current texture binding
///
////////////////////////////////////////////////////////////
class TextureSaver
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// The current texture binding is saved.
///
////////////////////////////////////////////////////////////
TextureSaver();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
/// The previous texture binding is restored.
///
////////////////////////////////////////////////////////////
~TextureSaver();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
GLint myTextureBinding; ///< Texture binding to restore
};
} // namespace priv
} // namespace sf
#endif // SFML_TEXTURESAVER_HPP

View File

@ -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 <SFML/Graphics/Transform.hpp>
#include <cmath>
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 Identity;
}
}
////////////////////////////////////////////////////////////
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

View File

@ -0,0 +1,216 @@
////////////////////////////////////////////////////////////
//
// 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 <SFML/Graphics/Transformable.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
Transformable::Transformable() :
myOrigin (0, 0),
myPosition (0, 0),
myRotation (0),
myScale (1, 1),
myTransform (),
myTransformNeedUpdate (true),
myInverseTransform (),
myInverseTransformNeedUpdate(true)
{
}
////////////////////////////////////////////////////////////
Transformable::~Transformable()
{
}
////////////////////////////////////////////////////////////
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<float>(std::cos(angle));
float sine = static_cast<float>(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

View File

@ -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 <SFML/Graphics/Vertex.hpp>
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 Vector2f& texCoords) :
Position (position),
Color (255, 255, 255),
TexCoords(texCoords)
{
}
////////////////////////////////////////////////////////////
Vertex::Vertex(const Vector2f& position, const sf::Color& color, const Vector2f& texCoords) :
Position (position),
Color (color),
TexCoords(texCoords)
{
}
} // namespace sf

View File

@ -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 <SFML/Graphics/VertexArray.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
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

View File

@ -26,18 +26,19 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/View.hpp>
#include <cmath>
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<float>(std::cos(angle));
float sine = static_cast<float>(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